* @brief Register that a device driver has been deleted from a devclass * * Register that a device driver has been removed from a devclass. * This is called by devclass_delete_driver to accomplish the * recursive notification of all the children classes of busclass, as * well as busclass. Each layer will attempt to detach the driver * from any devices that are children of the bus's devclass
| 1175 | * @param driver the driver being deleted |
| 1176 | */ |
| 1177 | static int |
| 1178 | devclass_driver_deleted(devclass_t busclass, devclass_t dc, driver_t *driver) |
| 1179 | { |
| 1180 | devclass_t parent; |
| 1181 | device_t dev; |
| 1182 | int error, i; |
| 1183 | |
| 1184 | /* |
| 1185 | * Disassociate from any devices. We iterate through all the |
| 1186 | * devices in the devclass of the driver and detach any which are |
| 1187 | * using the driver and which have a parent in the devclass which |
| 1188 | * we are deleting from. |
| 1189 | * |
| 1190 | * Note that since a driver can be in multiple devclasses, we |
| 1191 | * should not detach devices which are not children of devices in |
| 1192 | * the affected devclass. |
| 1193 | * |
| 1194 | * If we're frozen, we don't generate NOMATCH events. Mark to |
| 1195 | * generate later. |
| 1196 | */ |
| 1197 | for (i = 0; i < dc->maxunit; i++) { |
| 1198 | if (dc->devices[i]) { |
| 1199 | dev = dc->devices[i]; |
| 1200 | if (dev->driver == driver && dev->parent && |
| 1201 | dev->parent->devclass == busclass) { |
| 1202 | if ((error = device_detach(dev)) != 0) |
| 1203 | return (error); |
| 1204 | if (device_frozen) { |
| 1205 | dev->flags &= ~DF_DONENOMATCH; |
| 1206 | dev->flags |= DF_NEEDNOMATCH; |
| 1207 | } else { |
| 1208 | BUS_PROBE_NOMATCH(dev->parent, dev); |
| 1209 | devnomatch(dev); |
| 1210 | dev->flags |= DF_DONENOMATCH; |
| 1211 | } |
| 1212 | } |
| 1213 | } |
| 1214 | } |
| 1215 | |
| 1216 | /* |
| 1217 | * Walk through the children classes. Since we only keep a |
| 1218 | * single parent pointer around, we walk the entire list of |
| 1219 | * devclasses looking for children. We set the |
| 1220 | * DC_HAS_CHILDREN flag when a child devclass is created on |
| 1221 | * the parent, so we only walk the list for those devclasses |
| 1222 | * that have children. |
| 1223 | */ |
| 1224 | if (!(busclass->flags & DC_HAS_CHILDREN)) |
| 1225 | return (0); |
| 1226 | parent = busclass; |
| 1227 | TAILQ_FOREACH(busclass, &devclasses, link) { |
| 1228 | if (busclass->parent == parent) { |
| 1229 | error = devclass_driver_deleted(busclass, dc, driver); |
| 1230 | if (error) |
| 1231 | return (error); |
| 1232 | } |
| 1233 | } |
| 1234 | return (0); |
no test coverage detected