1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Freescale data path resource container (DPRC) driver 4 * 5 * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. 6 * Author: German Rivera <German.Rivera@freescale.com> 7 * 8 */ 9 10 #include <linux/module.h> 11 #include <linux/slab.h> 12 #include <linux/interrupt.h> 13 #include <linux/msi.h> 14 #include <linux/fsl/mc.h> 15 16 #include "fsl-mc-private.h" 17 18 #define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc" 19 20 struct fsl_mc_child_objs { 21 int child_count; 22 struct fsl_mc_obj_desc *child_array; 23 }; 24 25 static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev, 26 struct fsl_mc_obj_desc *obj_desc) 27 { 28 return mc_dev->obj_desc.id == obj_desc->id && 29 strcmp(mc_dev->obj_desc.type, obj_desc->type) == 0; 30 31 } 32 33 static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) 34 { 35 int i; 36 struct fsl_mc_child_objs *objs; 37 struct fsl_mc_device *mc_dev; 38 39 mc_dev = to_fsl_mc_device(dev); 40 objs = data; 41 42 for (i = 0; i < objs->child_count; i++) { 43 struct fsl_mc_obj_desc *obj_desc = &objs->child_array[i]; 44 45 if (strlen(obj_desc->type) != 0 && 46 fsl_mc_device_match(mc_dev, obj_desc)) 47 break; 48 } 49 50 if (i == objs->child_count) 51 fsl_mc_device_remove(mc_dev); 52 53 return 0; 54 } 55 56 static int __fsl_mc_device_remove(struct device *dev, void *data) 57 { 58 fsl_mc_device_remove(to_fsl_mc_device(dev)); 59 return 0; 60 } 61 62 /** 63 * dprc_remove_devices - Removes devices for objects removed from a DPRC 64 * 65 * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object 66 * @obj_desc_array: array of object descriptors for child objects currently 67 * present in the DPRC in the MC. 68 * @num_child_objects_in_mc: number of entries in obj_desc_array 69 * 70 * Synchronizes the state of the Linux bus driver with the actual state of 71 * the MC by removing devices that represent MC objects that have 72 * been dynamically removed in the physical DPRC. 73 */ 74 static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev, 75 struct fsl_mc_obj_desc *obj_desc_array, 76 int num_child_objects_in_mc) 77 { 78 if (num_child_objects_in_mc != 0) { 79 /* 80 * Remove child objects that are in the DPRC in Linux, 81 * but not in the MC: 82 */ 83 struct fsl_mc_child_objs objs; 84 85 objs.child_count = num_child_objects_in_mc; 86 objs.child_array = obj_desc_array; 87 device_for_each_child(&mc_bus_dev->dev, &objs, 88 __fsl_mc_device_remove_if_not_in_mc); 89 } else { 90 /* 91 * There are no child objects for this DPRC in the MC. 92 * So, remove all the child devices from Linux: 93 */ 94 device_for_each_child(&mc_bus_dev->dev, NULL, 95 __fsl_mc_device_remove); 96 } 97 } 98 99 static int __fsl_mc_device_match(struct device *dev, void *data) 100 { 101 struct fsl_mc_obj_desc *obj_desc = data; 102 struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 103 104 return fsl_mc_device_match(mc_dev, obj_desc); 105 } 106 107 static struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc 108 *obj_desc, 109 struct fsl_mc_device 110 *mc_bus_dev) 111 { 112 struct device *dev; 113 114 dev = device_find_child(&mc_bus_dev->dev, obj_desc, 115 __fsl_mc_device_match); 116 117 return dev ? to_fsl_mc_device(dev) : NULL; 118 } 119 120 /** 121 * check_plugged_state_change - Check change in an MC object's plugged state 122 * 123 * @mc_dev: pointer to the fsl-mc device for a given MC object 124 * @obj_desc: pointer to the MC object's descriptor in the MC 125 * 126 * If the plugged state has changed from unplugged to plugged, the fsl-mc 127 * device is bound to the corresponding device driver. 128 * If the plugged state has changed from plugged to unplugged, the fsl-mc 129 * device is unbound from the corresponding device driver. 130 */ 131 static void check_plugged_state_change(struct fsl_mc_device *mc_dev, 132 struct fsl_mc_obj_desc *obj_desc) 133 { 134 int error; 135 u32 plugged_flag_at_mc = 136 obj_desc->state & FSL_MC_OBJ_STATE_PLUGGED; 137 138 if (plugged_flag_at_mc != 139 (mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED)) { 140 if (plugged_flag_at_mc) { 141 mc_dev->obj_desc.state |= FSL_MC_OBJ_STATE_PLUGGED; 142 error = device_attach(&mc_dev->dev); 143 if (error < 0) { 144 dev_err(&mc_dev->dev, 145 "device_attach() failed: %d\n", 146 error); 147 } 148 } else { 149 mc_dev->obj_desc.state &= ~FSL_MC_OBJ_STATE_PLUGGED; 150 device_release_driver(&mc_dev->dev); 151 } 152 } 153 } 154 155 /** 156 * dprc_add_new_devices - Adds devices to the logical bus for a DPRC 157 * 158 * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object 159 * @obj_desc_array: array of device descriptors for child devices currently 160 * present in the physical DPRC. 161 * @num_child_objects_in_mc: number of entries in obj_desc_array 162 * 163 * Synchronizes the state of the Linux bus driver with the actual 164 * state of the MC by adding objects that have been newly discovered 165 * in the physical DPRC. 166 */ 167 static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev, 168 struct fsl_mc_obj_desc *obj_desc_array, 169 int num_child_objects_in_mc) 170 { 171 int error; 172 int i; 173 174 for (i = 0; i < num_child_objects_in_mc; i++) { 175 struct fsl_mc_device *child_dev; 176 struct fsl_mc_obj_desc *obj_desc = &obj_desc_array[i]; 177 178 if (strlen(obj_desc->type) == 0) 179 continue; 180 181 /* 182 * Check if device is already known to Linux: 183 */ 184 child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev); 185 if (child_dev) { 186 check_plugged_state_change(child_dev, obj_desc); 187 put_device(&child_dev->dev); 188 continue; 189 } 190 191 error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev, 192 &child_dev); 193 if (error < 0) 194 continue; 195 } 196 } 197 198 /** 199 * dprc_scan_objects - Discover objects in a DPRC 200 * 201 * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object 202 * @total_irq_count: If argument is provided the function populates the 203 * total number of IRQs created by objects in the DPRC. 204 * 205 * Detects objects added and removed from a DPRC and synchronizes the 206 * state of the Linux bus driver, MC by adding and removing 207 * devices accordingly. 208 * Two types of devices can be found in a DPRC: allocatable objects (e.g., 209 * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni). 210 * All allocatable devices needed to be probed before all non-allocatable 211 * devices, to ensure that device drivers for non-allocatable 212 * devices can allocate any type of allocatable devices. 213 * That is, we need to ensure that the corresponding resource pools are 214 * populated before they can get allocation requests from probe callbacks 215 * of the device drivers for the non-allocatable devices. 216 */ 217 static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, 218 unsigned int *total_irq_count) 219 { 220 int num_child_objects; 221 int dprc_get_obj_failures; 222 int error; 223 unsigned int irq_count = mc_bus_dev->obj_desc.irq_count; 224 struct fsl_mc_obj_desc *child_obj_desc_array = NULL; 225 struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); 226 227 error = dprc_get_obj_count(mc_bus_dev->mc_io, 228 0, 229 mc_bus_dev->mc_handle, 230 &num_child_objects); 231 if (error < 0) { 232 dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n", 233 error); 234 return error; 235 } 236 237 if (num_child_objects != 0) { 238 int i; 239 240 child_obj_desc_array = 241 devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects, 242 sizeof(*child_obj_desc_array), 243 GFP_KERNEL); 244 if (!child_obj_desc_array) 245 return -ENOMEM; 246 247 /* 248 * Discover objects currently present in the physical DPRC: 249 */ 250 dprc_get_obj_failures = 0; 251 for (i = 0; i < num_child_objects; i++) { 252 struct fsl_mc_obj_desc *obj_desc = 253 &child_obj_desc_array[i]; 254 255 error = dprc_get_obj(mc_bus_dev->mc_io, 256 0, 257 mc_bus_dev->mc_handle, 258 i, obj_desc); 259 if (error < 0) { 260 dev_err(&mc_bus_dev->dev, 261 "dprc_get_obj(i=%d) failed: %d\n", 262 i, error); 263 /* 264 * Mark the obj entry as "invalid", by using the 265 * empty string as obj type: 266 */ 267 obj_desc->type[0] = '\0'; 268 obj_desc->id = error; 269 dprc_get_obj_failures++; 270 continue; 271 } 272 273 /* 274 * add a quirk for all versions of dpsec < 4.0...none 275 * are coherent regardless of what the MC reports. 276 */ 277 if ((strcmp(obj_desc->type, "dpseci") == 0) && 278 (obj_desc->ver_major < 4)) 279 obj_desc->flags |= 280 FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY; 281 282 irq_count += obj_desc->irq_count; 283 dev_dbg(&mc_bus_dev->dev, 284 "Discovered object: type %s, id %d\n", 285 obj_desc->type, obj_desc->id); 286 } 287 288 if (dprc_get_obj_failures != 0) { 289 dev_err(&mc_bus_dev->dev, 290 "%d out of %d devices could not be retrieved\n", 291 dprc_get_obj_failures, num_child_objects); 292 } 293 } 294 295 /* 296 * Allocate IRQ's before binding the scanned devices with their 297 * respective drivers. 298 */ 299 if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) { 300 if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { 301 dev_warn(&mc_bus_dev->dev, 302 "IRQs needed (%u) exceed IRQs preallocated (%u)\n", 303 irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); 304 } 305 306 error = fsl_mc_populate_irq_pool(mc_bus, 307 FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); 308 if (error < 0) 309 return error; 310 } 311 312 if (total_irq_count) 313 *total_irq_count = irq_count; 314 315 dprc_remove_devices(mc_bus_dev, child_obj_desc_array, 316 num_child_objects); 317 318 dprc_add_new_devices(mc_bus_dev, child_obj_desc_array, 319 num_child_objects); 320 321 if (child_obj_desc_array) 322 devm_kfree(&mc_bus_dev->dev, child_obj_desc_array); 323 324 return 0; 325 } 326 327 /** 328 * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state 329 * 330 * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object 331 * 332 * Scans the physical DPRC and synchronizes the state of the Linux 333 * bus driver with the actual state of the MC by adding and removing 334 * devices as appropriate. 335 */ 336 static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) 337 { 338 int error; 339 struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); 340 341 fsl_mc_init_all_resource_pools(mc_bus_dev); 342 343 /* 344 * Discover objects in the DPRC: 345 */ 346 mutex_lock(&mc_bus->scan_mutex); 347 error = dprc_scan_objects(mc_bus_dev, NULL); 348 mutex_unlock(&mc_bus->scan_mutex); 349 if (error < 0) { 350 fsl_mc_cleanup_all_resource_pools(mc_bus_dev); 351 return error; 352 } 353 354 return 0; 355 } 356 357 /** 358 * dprc_irq0_handler - Regular ISR for DPRC interrupt 0 359 * 360 * @irq: IRQ number of the interrupt being handled 361 * @arg: Pointer to device structure 362 */ 363 static irqreturn_t dprc_irq0_handler(int irq_num, void *arg) 364 { 365 return IRQ_WAKE_THREAD; 366 } 367 368 /** 369 * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0 370 * 371 * @irq: IRQ number of the interrupt being handled 372 * @arg: Pointer to device structure 373 */ 374 static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) 375 { 376 int error; 377 u32 status; 378 struct device *dev = arg; 379 struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 380 struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); 381 struct fsl_mc_io *mc_io = mc_dev->mc_io; 382 struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc; 383 384 dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n", 385 irq_num, smp_processor_id()); 386 387 if (!(mc_dev->flags & FSL_MC_IS_DPRC)) 388 return IRQ_HANDLED; 389 390 mutex_lock(&mc_bus->scan_mutex); 391 if (!msi_desc || msi_desc->irq != (u32)irq_num) 392 goto out; 393 394 status = 0; 395 error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0, 396 &status); 397 if (error < 0) { 398 dev_err(dev, 399 "dprc_get_irq_status() failed: %d\n", error); 400 goto out; 401 } 402 403 error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, 404 status); 405 if (error < 0) { 406 dev_err(dev, 407 "dprc_clear_irq_status() failed: %d\n", error); 408 goto out; 409 } 410 411 if (status & (DPRC_IRQ_EVENT_OBJ_ADDED | 412 DPRC_IRQ_EVENT_OBJ_REMOVED | 413 DPRC_IRQ_EVENT_CONTAINER_DESTROYED | 414 DPRC_IRQ_EVENT_OBJ_DESTROYED | 415 DPRC_IRQ_EVENT_OBJ_CREATED)) { 416 unsigned int irq_count; 417 418 error = dprc_scan_objects(mc_dev, &irq_count); 419 if (error < 0) { 420 /* 421 * If the error is -ENXIO, we ignore it, as it indicates 422 * that the object scan was aborted, as we detected that 423 * an object was removed from the DPRC in the MC, while 424 * we were scanning the DPRC. 425 */ 426 if (error != -ENXIO) { 427 dev_err(dev, "dprc_scan_objects() failed: %d\n", 428 error); 429 } 430 431 goto out; 432 } 433 434 if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { 435 dev_warn(dev, 436 "IRQs needed (%u) exceed IRQs preallocated (%u)\n", 437 irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); 438 } 439 } 440 441 out: 442 mutex_unlock(&mc_bus->scan_mutex); 443 return IRQ_HANDLED; 444 } 445 446 /* 447 * Disable and clear interrupt for a given DPRC object 448 */ 449 static int disable_dprc_irq(struct fsl_mc_device *mc_dev) 450 { 451 int error; 452 struct fsl_mc_io *mc_io = mc_dev->mc_io; 453 454 /* 455 * Disable generation of interrupt, while we configure it: 456 */ 457 error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0); 458 if (error < 0) { 459 dev_err(&mc_dev->dev, 460 "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", 461 error); 462 return error; 463 } 464 465 /* 466 * Disable all interrupt causes for the interrupt: 467 */ 468 error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0); 469 if (error < 0) { 470 dev_err(&mc_dev->dev, 471 "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", 472 error); 473 return error; 474 } 475 476 /* 477 * Clear any leftover interrupts: 478 */ 479 error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U); 480 if (error < 0) { 481 dev_err(&mc_dev->dev, 482 "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n", 483 error); 484 return error; 485 } 486 487 return 0; 488 } 489 490 static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) 491 { 492 int error; 493 struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; 494 495 /* 496 * NOTE: devm_request_threaded_irq() invokes the device-specific 497 * function that programs the MSI physically in the device 498 */ 499 error = devm_request_threaded_irq(&mc_dev->dev, 500 irq->msi_desc->irq, 501 dprc_irq0_handler, 502 dprc_irq0_handler_thread, 503 IRQF_NO_SUSPEND | IRQF_ONESHOT, 504 dev_name(&mc_dev->dev), 505 &mc_dev->dev); 506 if (error < 0) { 507 dev_err(&mc_dev->dev, 508 "devm_request_threaded_irq() failed: %d\n", 509 error); 510 return error; 511 } 512 513 return 0; 514 } 515 516 static int enable_dprc_irq(struct fsl_mc_device *mc_dev) 517 { 518 int error; 519 520 /* 521 * Enable all interrupt causes for the interrupt: 522 */ 523 error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 524 ~0x0u); 525 if (error < 0) { 526 dev_err(&mc_dev->dev, 527 "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", 528 error); 529 530 return error; 531 } 532 533 /* 534 * Enable generation of the interrupt: 535 */ 536 error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1); 537 if (error < 0) { 538 dev_err(&mc_dev->dev, 539 "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", 540 error); 541 542 return error; 543 } 544 545 return 0; 546 } 547 548 /* 549 * Setup interrupt for a given DPRC device 550 */ 551 static int dprc_setup_irq(struct fsl_mc_device *mc_dev) 552 { 553 int error; 554 555 error = fsl_mc_allocate_irqs(mc_dev); 556 if (error < 0) 557 return error; 558 559 error = disable_dprc_irq(mc_dev); 560 if (error < 0) 561 goto error_free_irqs; 562 563 error = register_dprc_irq_handler(mc_dev); 564 if (error < 0) 565 goto error_free_irqs; 566 567 error = enable_dprc_irq(mc_dev); 568 if (error < 0) 569 goto error_free_irqs; 570 571 return 0; 572 573 error_free_irqs: 574 fsl_mc_free_irqs(mc_dev); 575 return error; 576 } 577 578 /** 579 * dprc_probe - callback invoked when a DPRC is being bound to this driver 580 * 581 * @mc_dev: Pointer to fsl-mc device representing a DPRC 582 * 583 * It opens the physical DPRC in the MC. 584 * It scans the DPRC to discover the MC objects contained in it. 585 * It creates the interrupt pool for the MC bus associated with the DPRC. 586 * It configures the interrupts for the DPRC device itself. 587 */ 588 static int dprc_probe(struct fsl_mc_device *mc_dev) 589 { 590 int error; 591 size_t region_size; 592 struct device *parent_dev = mc_dev->dev.parent; 593 struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); 594 bool mc_io_created = false; 595 bool msi_domain_set = false; 596 u16 major_ver, minor_ver; 597 598 if (!is_fsl_mc_bus_dprc(mc_dev)) 599 return -EINVAL; 600 601 if (dev_get_msi_domain(&mc_dev->dev)) 602 return -EINVAL; 603 604 if (!mc_dev->mc_io) { 605 /* 606 * This is a child DPRC: 607 */ 608 if (!dev_is_fsl_mc(parent_dev)) 609 return -EINVAL; 610 611 if (mc_dev->obj_desc.region_count == 0) 612 return -EINVAL; 613 614 region_size = resource_size(mc_dev->regions); 615 616 error = fsl_create_mc_io(&mc_dev->dev, 617 mc_dev->regions[0].start, 618 region_size, 619 NULL, 620 FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, 621 &mc_dev->mc_io); 622 if (error < 0) 623 return error; 624 625 mc_io_created = true; 626 627 /* 628 * Inherit parent MSI domain: 629 */ 630 dev_set_msi_domain(&mc_dev->dev, 631 dev_get_msi_domain(parent_dev)); 632 msi_domain_set = true; 633 } else { 634 /* 635 * This is a root DPRC 636 */ 637 struct irq_domain *mc_msi_domain; 638 639 if (dev_is_fsl_mc(parent_dev)) 640 return -EINVAL; 641 642 error = fsl_mc_find_msi_domain(parent_dev, 643 &mc_msi_domain); 644 if (error < 0) { 645 dev_warn(&mc_dev->dev, 646 "WARNING: MC bus without interrupt support\n"); 647 } else { 648 dev_set_msi_domain(&mc_dev->dev, mc_msi_domain); 649 msi_domain_set = true; 650 } 651 } 652 653 error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id, 654 &mc_dev->mc_handle); 655 if (error < 0) { 656 dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error); 657 goto error_cleanup_msi_domain; 658 } 659 660 error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle, 661 &mc_bus->dprc_attr); 662 if (error < 0) { 663 dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n", 664 error); 665 goto error_cleanup_open; 666 } 667 668 error = dprc_get_api_version(mc_dev->mc_io, 0, 669 &major_ver, 670 &minor_ver); 671 if (error < 0) { 672 dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n", 673 error); 674 goto error_cleanup_open; 675 } 676 677 if (major_ver < DPRC_MIN_VER_MAJOR || 678 (major_ver == DPRC_MIN_VER_MAJOR && 679 minor_ver < DPRC_MIN_VER_MINOR)) { 680 dev_err(&mc_dev->dev, 681 "ERROR: DPRC version %d.%d not supported\n", 682 major_ver, minor_ver); 683 error = -ENOTSUPP; 684 goto error_cleanup_open; 685 } 686 687 mutex_init(&mc_bus->scan_mutex); 688 689 /* 690 * Discover MC objects in DPRC object: 691 */ 692 error = dprc_scan_container(mc_dev); 693 if (error < 0) 694 goto error_cleanup_open; 695 696 /* 697 * Configure interrupt for the DPRC object associated with this MC bus: 698 */ 699 error = dprc_setup_irq(mc_dev); 700 if (error < 0) 701 goto error_cleanup_open; 702 703 dev_info(&mc_dev->dev, "DPRC device bound to driver"); 704 return 0; 705 706 error_cleanup_open: 707 (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); 708 709 error_cleanup_msi_domain: 710 if (msi_domain_set) 711 dev_set_msi_domain(&mc_dev->dev, NULL); 712 713 if (mc_io_created) { 714 fsl_destroy_mc_io(mc_dev->mc_io); 715 mc_dev->mc_io = NULL; 716 } 717 718 return error; 719 } 720 721 /* 722 * Tear down interrupt for a given DPRC object 723 */ 724 static void dprc_teardown_irq(struct fsl_mc_device *mc_dev) 725 { 726 struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; 727 728 (void)disable_dprc_irq(mc_dev); 729 730 devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev); 731 732 fsl_mc_free_irqs(mc_dev); 733 } 734 735 /** 736 * dprc_remove - callback invoked when a DPRC is being unbound from this driver 737 * 738 * @mc_dev: Pointer to fsl-mc device representing the DPRC 739 * 740 * It removes the DPRC's child objects from Linux (not from the MC) and 741 * closes the DPRC device in the MC. 742 * It tears down the interrupts that were configured for the DPRC device. 743 * It destroys the interrupt pool associated with this MC bus. 744 */ 745 static int dprc_remove(struct fsl_mc_device *mc_dev) 746 { 747 int error; 748 struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); 749 750 if (!is_fsl_mc_bus_dprc(mc_dev)) 751 return -EINVAL; 752 if (!mc_dev->mc_io) 753 return -EINVAL; 754 755 if (!mc_bus->irq_resources) 756 return -EINVAL; 757 758 if (dev_get_msi_domain(&mc_dev->dev)) 759 dprc_teardown_irq(mc_dev); 760 761 device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove); 762 763 if (dev_get_msi_domain(&mc_dev->dev)) { 764 fsl_mc_cleanup_irq_pool(mc_bus); 765 dev_set_msi_domain(&mc_dev->dev, NULL); 766 } 767 768 fsl_mc_cleanup_all_resource_pools(mc_dev); 769 770 error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); 771 if (error < 0) 772 dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error); 773 774 if (!fsl_mc_is_root_dprc(&mc_dev->dev)) { 775 fsl_destroy_mc_io(mc_dev->mc_io); 776 mc_dev->mc_io = NULL; 777 } 778 779 dev_info(&mc_dev->dev, "DPRC device unbound from driver"); 780 return 0; 781 } 782 783 static const struct fsl_mc_device_id match_id_table[] = { 784 { 785 .vendor = FSL_MC_VENDOR_FREESCALE, 786 .obj_type = "dprc"}, 787 {.vendor = 0x0}, 788 }; 789 790 static struct fsl_mc_driver dprc_driver = { 791 .driver = { 792 .name = FSL_MC_DPRC_DRIVER_NAME, 793 .owner = THIS_MODULE, 794 .pm = NULL, 795 }, 796 .match_id_table = match_id_table, 797 .probe = dprc_probe, 798 .remove = dprc_remove, 799 }; 800 801 int __init dprc_driver_init(void) 802 { 803 return fsl_mc_driver_register(&dprc_driver); 804 } 805 806 void dprc_driver_exit(void) 807 { 808 fsl_mc_driver_unregister(&dprc_driver); 809 } 810