/* * __device_release_driver() must be called with @dev lock held. * When called for a USB interface, @dev->parent lock must be held as well. */ static void __device_release_driver(struct device *dev) { struct device_driver *drv; drv = dev->driver; if (drv) { pm_runtime_get_sync(dev); driver_sysfs_remove(dev); if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_UNBIND_DRIVER, dev); pm_runtime_put_sync(dev); if (dev->bus && dev->bus->remove) dev->bus->remove(dev); else if (drv->remove) drv->remove(dev); devres_release_all(dev); dev->driver = NULL; klist_remove(&dev->p->knode_driver); if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_UNBOUND_DRIVER, dev); } }
static int really_probe(struct device *dev, struct device_driver *drv) { int ret = 0; atomic_inc(&probe_count); pr_debug("bus: '%s': %s: probing driver %s with device %s\n", drv->bus->name, __func__, drv->name, dev_name(dev)); WARN_ON(!list_empty(&dev->devres_head)); dev->driver = drv; if (driver_sysfs_add(dev)) { printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n", __func__, dev_name(dev)); goto probe_failed; } if (dev->bus->probe) { ret = dev->bus->probe(dev); pr_debug("dev->bus->probe: '%s': %s(line:%d): probing driver %s \n",//add by hui drv->bus->name, __func__,__LINE__, drv->name); if (ret) goto probe_failed; } else if (drv->probe) { ret = drv->probe(dev); pr_debug("drv->probe: '%s': %s(line:%d): probing driver %s \n",//add by hui drv->bus->name, __func__,__LINE__, drv->name); if (ret) goto probe_failed; } driver_bound(dev); ret = 1; pr_debug("bus: '%s': %s: bound device %s to driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); goto done; probe_failed: devres_release_all(dev); driver_sysfs_remove(dev); dev->driver = NULL; if (ret != -ENODEV && ret != -ENXIO) { /* driver matched but the probe failed */ printk(KERN_WARNING "%s: probe of %s failed with error %d\n", drv->name, dev_name(dev), ret); } /* * Ignore errors returned by ->probe so that the next driver can try * its luck. */ ret = 0; done: atomic_dec(&probe_count); wake_up(&probe_waitqueue); return ret; }
/* 该函数用于真正的探测实际的设备 */ static int really_probe(struct device *dev, struct device_driver *drv) { int ret = 0; atomic_inc(&probe_count); pr_debug("bus: '%s': %s: probing driver %s with device %s\n", drv->bus->name, __func__, drv->name, dev_name(dev)); WARN_ON(!list_empty(&dev->devres_head)); dev->driver = drv; /* 将当前驱动程序对象drv赋值给dev->driver*/ if (driver_sysfs_add(dev)) { printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n", __func__, dev_name(dev)); goto probe_failed; } if (dev->bus->probe) { /* 如果定义了探测设备的方法dev->bus->probe,则调用该方法来探测设备 */ ret = dev->bus->probe(dev); /* 用来探测当前的设备是否适合当前的驱动 */ if (ret) goto probe_failed; } else if (drv->probe) { /* 否则如果定义了 探测设备的方法drv->probe(),则调用该方法来探测设备*/ ret = drv->probe(dev); /* 用来探测当前的设备是否适合当前的驱动以及当前设备是否处于工作状态等 */ if (ret) goto probe_failed; } driver_bound(dev); /* 如果探测成功则最后调用该函数来将驱动程序的一些数据信息加入到dev对象中 */ ret = 1; pr_debug("bus: '%s': %s: bound device %s to driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); goto done; probe_failed: devres_release_all(dev); driver_sysfs_remove(dev); dev->driver = NULL; if (ret != -ENODEV && ret != -ENXIO) { /* driver matched but the probe failed */ printk(KERN_WARNING "%s: probe of %s failed with error %d\n", drv->name, dev_name(dev), ret); } /* * Ignore errors returned by ->probe so that the next driver can try * its luck. */ ret = 0; done: atomic_dec(&probe_count); wake_up(&probe_waitqueue); return ret; }
/* * __device_release_driver() must be called with @dev->sem held. * When called for a USB interface, @dev->parent->sem must be held as well. */ static void __device_release_driver(struct device * dev) { struct device_driver * drv; drv = get_driver(dev->driver); if (drv) { driver_sysfs_remove(dev); sysfs_remove_link(&dev->kobj, "driver"); klist_remove(&dev->knode_driver); if (dev->bus) blocking_notifier_call_chain(&dev->bus->bus_notifier, BUS_NOTIFY_UNBIND_DRIVER, dev); if (dev->bus && dev->bus->remove) dev->bus->remove(dev); else if (drv->remove) drv->remove(dev); devres_release_all(dev); dev->driver = NULL; put_driver(drv); } }
static int really_probe(struct device *dev, struct device_driver *drv) { int ret = 0; atomic_inc(&probe_count); pr_debug("bus: '%s': %s: probing driver %s with device %s\n", drv->bus->name, __func__, drv->name, dev_name(dev)); WARN_ON(!list_empty(&dev->devres_head)); dev->driver = drv; if (driver_sysfs_add(dev)) { printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n", __func__, dev_name(dev)); goto probe_failed; } if (dev->bus->probe) { ret = dev->bus->probe(dev); if (ret) goto probe_failed; } else if (drv->probe) { ret = drv->probe(dev); if (ret) goto probe_failed; } driver_bound(dev); ret = 1; pr_debug("bus: '%s': %s: bound device %s to driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); goto done; probe_failed: devres_release_all(dev); driver_sysfs_remove(dev); dev->driver = NULL; if (ret != -ENODEV && ret != -ENXIO) { /* driver matched but the probe failed */ printk(KERN_WARNING "%s: probe of %s failed with error %d\n", drv->name, dev_name(dev), ret); } #ifdef CONFIG_MACH_LGE_MMC_REFRESH //FW KIMBYUNGCHUL 20110516 [START] if (ret == 0xbcbc) { /* driver matched but the probe failed */ printk(KERN_WARNING "[microSD]%s: probe of %s failed with error %d\n", drv->name, dev_name(dev), ret); }else ret = 0; #else /* * Ignore errors returned by ->probe so that the next driver can try * its luck. */ ret = 0; #endif //FW KIMBYUNGCHUL 20110516 [END] done: atomic_dec(&probe_count); wake_up(&probe_waitqueue); return ret; }