svn commit: r201609 - in head/sys/dev: cardbus pci

John Baldwin jhb at FreeBSD.org
Tue Jan 5 20:42:25 UTC 2010


Author: jhb
Date: Tue Jan  5 20:42:25 2010
New Revision: 201609
URL: http://svn.freebsd.org/changeset/base/201609

Log:
  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

Modified:
  head/sys/dev/cardbus/cardbus.c
  head/sys/dev/pci/pci.c
  head/sys/dev/pci/pci_private.h

Modified: head/sys/dev/cardbus/cardbus.c
==============================================================================
--- head/sys/dev/cardbus/cardbus.c	Tue Jan  5 20:40:40 2010	(r201608)
+++ head/sys/dev/cardbus/cardbus.c	Tue Jan  5 20:42:25 2010	(r201609)
@@ -80,8 +80,6 @@ static void	cardbus_driver_added(device_
 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, dri
 	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							*/
 /************************************************************************/

Modified: head/sys/dev/pci/pci.c
==============================================================================
--- head/sys/dev/pci/pci.c	Tue Jan  5 20:40:40 2010	(r201608)
+++ head/sys/dev/pci/pci.c	Tue Jan  5 20:42:25 2010	(r201609)
@@ -3797,6 +3797,46 @@ pci_deactivate_resource(device_t dev, de
 }
 
 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;

Modified: head/sys/dev/pci/pci_private.h
==============================================================================
--- head/sys/dev/pci/pci_private.h	Tue Jan  5 20:40:40 2010	(r201608)
+++ head/sys/dev/pci/pci_private.h	Tue Jan  5 20:42:25 2010	(r201609)
@@ -43,6 +43,7 @@ void		pci_add_children(device_t dev, int
 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);


More information about the svn-src-all mailing list