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