summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci/pci.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2010-01-05 20:42:25 +0000
committerjhb <jhb@FreeBSD.org>2010-01-05 20:42:25 +0000
commit2dd11a3eaaa7e7f9ee8766d13f00bfef1766ff90 (patch)
treede14655cb75970d20c9f5724184782b10b6a3cae /sys/dev/pci/pci.c
parenta0dce5cf22b7c2ceef7a745abd732f54a5447b7c (diff)
downloadFreeBSD-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.c40
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;
OpenPOWER on IntegriCloud