PERFORCE change 123220 for review

Maxim Zhuravlev thioretic at FreeBSD.org
Mon Jul 9 18:08:24 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=123220

Change 123220 by thioretic at thioretic on 2007/07/09 18:08:19

	TODO: softc, device_set_driver semantics 
		and some cleanups.
	DONE: unified parents/children manipulation

Affected files ...

.. //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#11 edit

Differences ...

==== //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#11 (text+ko) ====

@@ -2038,7 +2038,47 @@
 	return (device_add_child_ordered(dev, 0, name, unit));
 }
 
+static int
+device_add_to_dev_list (device_t addwhat, pdevice_list_t *addwhere){
+	pdevice *pd;
+	TAILQ_FOREACH (pd, addwhere, link){
+		if (pd->device_ptr == addwhat)
+			return (1);
+	}
+	
+	pd = malloc(sizeof(struct pdevice), M_BUS, M_NOWAIT|M_ZERO);
+	if (!pd) 
+		return (0);
+
+	pd->device_ptr = addwhat;
+	TAILQ_INSERT_TAIL(addwhere, pd, link);
+	pd->device_ptr->refs++;
+
+	bus_data_generation_update();
+	return (1);
+}
+
 /**
+ * @brief Add a new child, which is a device, that already exists
+ * 
+ * This adds a new parent (if not yet in parents)
+ */
+int 
+device_add_existing_child (device_t dev, device_t child){
+	device_add_to_dev_list (child, &(dev->children));
+}
+/**
+ * @brief Add a new parent, which is a device, that already exists
+ * 
+ * This adds a new parent (if not yet in parents)
+ */
+int
+device_add_existing_parent (device_t dev, device_t parent){
+	device_add_to_dev_list (parent, &(dev->parents));
+}
+
+
+/**
  * @brief Create a new device
  *
  * This creates a new device and adds it as a child of an existing
@@ -2099,72 +2139,105 @@
 	return (child);
 }
 
-/**
- * @brief Delete a device
- *
- * This function deletes a device along with all of its children. If
- * the device currently has a driver attached to it, the device is
- * detached first using device_detach().
- * 
- * @param dev		the parent device
- * @param child		the device to delete
- *
- * @retval 0		success
- * @retval non-zero	a unit error code describing the error
- */
-int
-device_delete_child(device_t dev, device_t child) /*TODO*/
-{
+#define CHILDREN	-1
+#define PARENTS	1
+
+static int
+destroy_recurse (device_t dev, device_t devtodel, int direction){
 	int error;
-	/*device_t*/ pdevice *grandchild;
+	pdevice *grand;
 	pdevice *pd;
+	pdevice_list_t *list;
 
 	PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
 	
-	child->refs--;
-	if (child->refs) goto deletefromparent;
 	/* remove children first */
-	while ( (grandchild = TAILQ_FIRST(&child->children)) ) {
-		error = device_delete_child(child, grandchild->device_ptr);
+	list = (direction == CHILDREN) ? &devtodel->children : &devtodel->parents;
+	if (--devtodel->refs) goto deleteself;
+	while ( (grand = TAILQ_FIRST(list)) ) {
+		error = destroy_recurse(devtodel, grand->device_ptr, direction);
 		if (error)
 			return (error);
-		free (grandchild);
+		free (grand);
 	}
 
-	if ((error = device_detach(child)) != 0)
+	if ((error = device_detach(devtodel)) != 0)
 		return (error);
-	if (child->devclass)
-		devclass_delete_device(child->devclass, child);
+	if (devtodel->devclass)
+		devclass_delete_device(devtodel->devclass, devtodel);
 deletefromparent:
-	TAILQ_FOREACH_SAFE(pd, &dev->children, link){
-		if (pd->device_ptr == child){
-			TAILQ_REMOVE(&dev->children, child, link);
+	TAILQ_FOREACH_SAFE(pd, list, link){
+		if (pd->device_ptr == devtodel){
+			TAILQ_REMOVE(list, devtodel, link);
 			free (pd);
 			break;
 		}
 	}
 
-	if (child->refs) 
+	if (devtodel->refs) 
 		return (0);
 
-	TAILQ_REMOVE(&bus_data_devices, child, devlink);
-	kobj_delete((kobj_t) child, M_BUS);
+	TAILQ_REMOVE(&bus_data_devices, devtodel, devlink);
+	kobj_delete((kobj_t) devtodel, M_BUS);
 	
 	bus_data_generation_update();
 	return (0);
 }
 
+
+void
+device_delete_existing_child (device_t dev, device_t child){
+	destroy_recurse (dev, child, CHILDREN);
+}
+
+void
+device_add_existing_parent (device_t dev, device_t parent){
+	destroy_recurse (dev, parent, PARENTS);
+}
+
+/**
+ * @brief Delete a device
+ *
+ * This function deletes a device along with all of its children. If
+ * the device currently has a driver attached to it, the device is
+ * detached first using device_detach().
+ * 
+ * @param dev		the parent device
+ * @param child		the device to delete
+ *
+ * @retval 0		success
+ * @retval non-zero	a unit error code describing the error
+ */
+int
+device_delete_child(device_t dev, device_t child) /*TODO*/
+{
+	return (destroy_recurse(dev, child, CHILDREN));
+}
+
 static int
-is_device_parent (device_t dev, device_t child){
+is_device_relation (device_t dev, device_t tocheck, int direction){
 	pdevice *dc;
-	TAILQ_FOREACH (dc, &(child->parents), link){
+	pdevice_list_t list;
+
+	list = (direction == CHILDREN) ? &tocheck->parents : &tocheck->children;
+	TAILQ_FOREACH (dc, list, link){
 		if (dc->device_ptr == dev) return (TRUE);
 	}
 	return (FALSE);
 }
 
+static int
+is_device_child (device_t dev, device_t child){
+	return (is_device_relation(dev, child, CHILDREN));
+}
+
+static int
+is_device_parent (device_t dev, device_t parent){
+	return (is_device_relation(dev, parent, PARENTS));
+}
+
 /**
- * @brief Find a device given a unit number
+ * @brief Find a relation device given a unit number
  *
  * This is similar to devclass_get_devices() but only searches for
  * devices which have @p dev as a parent.
@@ -2178,31 +2251,43 @@
  *			NULL if there is no such device
  */
 device_t
-device_find_child(device_t dev, const char *classname, int unit)
+device_find_relation(device_t dev, const char *classname, int unit, int direction)
 {
 	devclass_t dc;
-	device_t child;
+	device_t relation;
 
 	dc = devclass_find(classname);
 	if (!dc)
 		return (NULL);
 
 	if (unit != -1) {
-		child = devclass_get_device(dc, unit);
-		if (child && /*child->parent == dev*/
-			is_device_parent(dev, child))
-			return (child);
+		relation = devclass_get_device(dc, unit);
+		if (relation && 
+			((direction==CHILDREN) ? is_device_child(dev, relation) : 
+			is_device_parent(dev, relation)))
+			return (relation);
 	} else {
 		for (unit = 0; unit < devclass_get_maxunit(dc); unit++) {
-			child = devclass_get_device(dc, unit);
-			if (child && /*child->parent == dev*/
-				is_device_parent(dev, child))
-				return (child);
+			relation = devclass_get_device(dc, unit);
+			if (relation &&
+				((direction==CHILDREN) ? is_device_child(dev, relation) : 
+				is_device_parent(dev, relation)))
+				return (relation);
 		}
 	}
 	return (NULL);
 }
 
+device_t
+device_find_child(device_t dev, const char* classname, int unit){
+	return (device_find_relation (dev, classname, unit, CHILDREN));
+}
+
+device_t
+device_find_parent(device_t dev, const char* classname, int unit){
+	return (device_find_relation (dev, classname, unit, PARENTS));
+}
+
 /**
  * @internal
  */
@@ -2403,14 +2488,16 @@
  * @retval ENOMEM	the array allocation failed
  */
 int
-device_get_children(device_t dev, device_t **devlistp, int *devcountp)
+device_get_relations(device_t dev, device_t **devlistp, int *devcountp, int direction)
 {
 	int count;
-	/*device_t*/ pdevice *child;
+	/*device_t*/ pdevice *relation;
 	device_t *list;
+	pdevice_list_t wherelist;
 
+	wherelist = (direction == CHILDREN) : &dev->children : &dev->parents;
 	count = 0;
-	TAILQ_FOREACH(child, &dev->children, link) {
+	TAILQ_FOREACH(relation, wherelist, link) {
 		count++;
 	}
 
@@ -2419,8 +2506,8 @@
 		return (ENOMEM);
 
 	count = 0;
-	TAILQ_FOREACH(child, &dev->children, link) {
-		list[count] = child->device_ptr;
+	TAILQ_FOREACH(relation, wherelist, link) {
+		list[count] = relation->device_ptr;
 		count++;
 	}
 
@@ -2430,6 +2517,16 @@
 	return (0);
 }
 
+int
+device_get_children(device_t dev, device_t **devlistp, int *devcountp){
+	return (device_get_relations(dev, devlistp, devcountp, CHILDREN));
+}
+
+int
+device_get_all_parents(device_t dev, device_t **devlistp, int *devcountp){
+	return (device_get_relations(dev, devlistp, devcountp, PARENTS));
+}
+
 /**
  * @brief Return the current driver for the device or @c NULL if there
  * is no driver currently attached


More information about the p4-projects mailing list