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