diff options
author | jhb <jhb@FreeBSD.org> | 2010-01-05 20:42:25 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2010-01-05 20:42:25 +0000 |
commit | 2dd11a3eaaa7e7f9ee8766d13f00bfef1766ff90 (patch) | |
tree | de14655cb75970d20c9f5724184782b10b6a3cae | |
parent | a0dce5cf22b7c2ceef7a745abd732f54a5447b7c (diff) | |
download | FreeBSD-src-2dd11a3eaaa7e7f9ee8766d13f00bfef1766ff90.zip FreeBSD-src-2dd11a3eaaa7e7f9ee8766d13f00bfef1766ff90.tar.gz |
Move the PCI-specific logic of removing a cardbus device into a
pci_delete_child() function called by the cardbus driver. The new function
uses resource_list_unreserve() to release the BARs decoded by the device
being removed.
Reviewed by: imp
Tested by: brooks
-rw-r--r-- | sys/dev/cardbus/cardbus.c | 31 | ||||
-rw-r--r-- | sys/dev/pci/pci.c | 40 | ||||
-rw-r--r-- | sys/dev/pci/pci_private.h | 1 |
3 files changed, 42 insertions, 30 deletions
diff --git a/sys/dev/cardbus/cardbus.c b/sys/dev/cardbus/cardbus.c index 8a333ad..6edf183 100644 --- a/sys/dev/cardbus/cardbus.c +++ b/sys/dev/cardbus/cardbus.c @@ -80,8 +80,6 @@ static void cardbus_driver_added(device_t cbdev, driver_t *driver); static int cardbus_probe(device_t cbdev); static int cardbus_read_ivar(device_t cbdev, device_t child, int which, uintptr_t *result); -static void cardbus_release_all_resources(device_t cbdev, - struct cardbus_devinfo *dinfo); /************************************************************************/ /* Probe/Attach */ @@ -226,16 +224,11 @@ cardbus_detach_card(device_t cbdev) for (tmp = 0; tmp < numdevs; tmp++) { struct cardbus_devinfo *dinfo = device_get_ivars(devlist[tmp]); - int status = device_get_state(devlist[tmp]); if (dinfo->pci.cfg.dev != devlist[tmp]) device_printf(cbdev, "devinfo dev mismatch\n"); - if (status == DS_ATTACHED || status == DS_BUSY) - device_detach(devlist[tmp]); - cardbus_release_all_resources(cbdev, dinfo); cardbus_device_destroy(dinfo); - device_delete_child(cbdev, devlist[tmp]); - pci_freecfg((struct pci_devinfo *)dinfo); + pci_delete_child(cbdev, devlist[tmp]); } POWER_DISABLE_SOCKET(device_get_parent(cbdev), cbdev); free(devlist, M_TEMP); @@ -283,28 +276,6 @@ cardbus_driver_added(device_t cbdev, driver_t *driver) free(devlist, M_TEMP); } -static void -cardbus_release_all_resources(device_t cbdev, struct cardbus_devinfo *dinfo) -{ - struct resource_list_entry *rle; - device_t dev; - - /* Turn off access to resources we're about to free */ - dev = dinfo->pci.cfg.dev; - pci_write_config(dev, PCIR_COMMAND, - pci_read_config(dev, PCIR_COMMAND, 2) & - ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN), 2); - /* Free all allocated resources */ - STAILQ_FOREACH(rle, &dinfo->pci.resources, link) { - if (rle->res) { - BUS_RELEASE_RESOURCE(device_get_parent(cbdev), - cbdev, rle->type, rle->rid, rle->res); - rle->res = NULL; - } - } - resource_list_free(&dinfo->pci.resources); -} - /************************************************************************/ /* Other Bus Methods */ /************************************************************************/ diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 008377a..2402de1 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -3797,6 +3797,46 @@ pci_deactivate_resource(device_t dev, device_t child, int type, } void +pci_delete_child(device_t dev, device_t child) +{ + struct resource_list_entry *rle; + struct resource_list *rl; + struct pci_devinfo *dinfo; + + dinfo = device_get_ivars(child); + rl = &dinfo->resources; + + if (device_is_attached(child)) + device_detach(child); + + /* Turn off access to resources we're about to free */ + pci_write_config(child, PCIR_COMMAND, pci_read_config(child, + PCIR_COMMAND, 2) & ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN), 2); + + /* Free all allocated resources */ + STAILQ_FOREACH(rle, rl, link) { + if (rle->res) { + if (rman_get_flags(rle->res) & RF_ACTIVE || + resource_list_busy(rl, rle->type, rle->rid)) { + pci_printf(&dinfo->cfg, + "Resource still owned, oops. " + "(type=%d, rid=%d, addr=%lx)\n", + rle->type, rle->rid, + rman_get_start(rle->res)); + bus_release_resource(child, rle->type, rle->rid, + rle->res); + } + resource_list_unreserve(rl, dev, child, rle->type, + rle->rid); + } + } + resource_list_free(rl); + + device_delete_child(dev, child); + pci_freecfg(dinfo); +} + +void pci_delete_resource(device_t dev, device_t child, int type, int rid) { struct pci_devinfo *dinfo; diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h index 1cb28e9..2240b4f 100644 --- a/sys/dev/pci/pci_private.h +++ b/sys/dev/pci/pci_private.h @@ -43,6 +43,7 @@ void pci_add_children(device_t dev, int domain, int busno, void pci_add_child(device_t bus, struct pci_devinfo *dinfo); void pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask); +void pci_delete_child(device_t dev, device_t child); void pci_driver_added(device_t dev, driver_t *driver); int pci_print_child(device_t dev, device_t child); void pci_probe_nomatch(device_t dev, device_t child); |