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 /sys/dev/pci/pci.c | |
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
Diffstat (limited to 'sys/dev/pci/pci.c')
-rw-r--r-- | sys/dev/pci/pci.c | 40 |
1 files changed, 40 insertions, 0 deletions
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; |