Ejemplo n.º 1
0
/**
 * device_attach - try to attach device to a driver.
 * @dev: device.
 *
 * Walk the list of drivers that the bus has and call
 * driver_probe_device() for each pair. If a compatible
 * pair is found, break out and return.
 *
 * Returns 1 if the device was bound to a driver;
 * 0 if no matching driver was found;
 * -ENODEV if the device is not registered.
 *
 * When called for a USB interface, @dev->parent lock must be held.
 */
int device_attach(struct device *dev)
{
	int ret = 0;

	device_lock(dev);
	if (dev->driver) {
		if (klist_node_attached(&dev->p->knode_driver)) {
			ret = 1;
			goto out_unlock;
		}
		ret = device_bind_driver(dev);
		if (ret == 0)
			ret = 1;
		else {
			dev->driver = NULL;
			ret = 0;
		}
	} else {
		pm_runtime_get_noresume(dev);
		ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
		pm_runtime_put_sync(dev);
	}
out_unlock:
	device_unlock(dev);
	return ret;
}
Ejemplo n.º 2
0
/**
 * bus_remove_device - remove device from bus
 * @dev: device to be removed
 *
 * - Remove device from all interfaces.
 * - Remove symlink from bus' directory.
 * - Delete device from bus's list.
 * - Detach from its driver.
 * - Drop reference taken in bus_add_device().
 */
void bus_remove_device(struct device *dev)
{
    struct bus_type *bus = dev->bus;
    struct subsys_interface *sif;

    if (!bus)
        return;

    mutex_lock(&bus->p->mutex);
    list_for_each_entry(sif, &bus->p->interfaces, node)
    if (sif->remove_dev)
        sif->remove_dev(dev, sif);
    mutex_unlock(&bus->p->mutex);

    sysfs_remove_link(&dev->kobj, "subsystem");
    sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
                      dev_name(dev));
    device_remove_attrs(dev->bus, dev);
    if (klist_node_attached(&dev->p->knode_bus))
        klist_del(&dev->p->knode_bus);

    pr_debug("bus: '%s': remove device %s\n",
             dev->bus->name, dev_name(dev));
    device_release_driver(dev);
    bus_put(dev->bus);
}
/**
 * bus_remove_device - remove device from bus
 * @dev: device to be removed
 *
 * - Remove symlink from bus's directory.
 * - Delete device from bus's list.
 * - Detach from its driver.
 * - Drop reference taken in bus_add_device().
 */
void bus_remove_device(struct device *dev)
{
	if (dev->bus) {
		sysfs_remove_link(&dev->kobj, "subsystem");
		sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
				  dev_name(dev));
		device_remove_attrs(dev->bus, dev);
		if (klist_node_attached(&dev->p->knode_bus))
			klist_del(&dev->p->knode_bus);

		pr_debug("bus: '%s': remove device %s\n",
			 dev->bus->name, dev_name(dev));
		device_release_driver(dev);
		bus_put(dev->bus);
	}
}
Ejemplo n.º 4
0
static void driver_bound(struct device *dev)
{
	if (klist_node_attached(&dev->p->knode_driver)) {
		printk(KERN_WARNING "%s: device %s already bound\n",
			__func__, kobject_name(&dev->kobj));
		return;
	}

	pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),
		 __func__, dev->driver->name);

	klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);

	if (dev->bus)
		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
					     BUS_NOTIFY_BOUND_DRIVER, dev);
}
Ejemplo n.º 5
0
Archivo: dd.c Proyecto: cywzl/spice4xen
/**
 *	device_bind_driver - bind a driver to one device.
 *	@dev:	device.
 *
 *	Allow manual attachment of a driver to a device.
 *	Caller must have already set @dev->driver.
 *
 *	Note that this does not modify the bus reference count
 *	nor take the bus's rwsem. Please verify those are accounted
 *	for before calling this. (It is ok to call with no other effort
 *	from a driver's probe() method.)
 *
 *	This function must be called with @dev->sem held.
 */
void device_bind_driver(struct device * dev)
{
	if (klist_node_attached(&dev->knode_driver))
		return;

	pr_debug("bound device '%s' to driver '%s'\n",
		 dev->bus_id, dev->driver->name);

	if (dev->bus)
		blocking_notifier_call_chain(&dev->bus->bus_notifier,
					     BUS_NOTIFY_BOUND_DRIVER, dev);

	klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
	sysfs_create_link(&dev->driver->kobj, &dev->kobj,
			  kobject_name(&dev->kobj));
	sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
}
Ejemplo n.º 6
0
/*
 * usb_disable_device - Disable all the endpoints for a USB device
 * @dev: the device whose endpoints are being disabled
 * @skip_ep0: 0 to disable endpoint 0, 1 to skip it.
 *
 * Disables all the device's endpoints, potentially including endpoint 0.
 * Deallocates hcd/hardware state for the endpoints (nuking all or most
 * pending urbs) and usbcore state for the interfaces, so that usbcore
 * must usb_set_configuration() before any interfaces could be used.
 */
void usb_disable_device(struct usb_device *dev, int skip_ep0)
{
	int i;

	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __FUNCTION__,
			skip_ep0 ? "non-ep0" : "all");
	for (i = skip_ep0; i < 16; ++i) {
		usb_disable_endpoint(dev, i);
		usb_disable_endpoint(dev, i + USB_DIR_IN);
	}
	dev->toggle[0] = dev->toggle[1] = 0;

	/* getting rid of interfaces will disconnect
	 * any drivers bound to them (a key side effect)
	 */
	if (dev->actconfig) {
		for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
			struct usb_interface	*interface;

			/* remove this interface if it has been registered */
			interface = dev->actconfig->interface[i];
			if (!klist_node_attached(&interface->dev.knode_bus))
				continue;
			dev_dbg (&dev->dev, "unregistering interface %s\n",
				interface->dev.bus_id);
			usb_remove_sysfs_intf_files(interface);
			kfree(interface->cur_altsetting->string);
			interface->cur_altsetting->string = NULL;
			device_del (&interface->dev);
		}

		/* Now that the interfaces are unbound, nobody should
		 * try to access them.
		 */
		for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
			put_device (&dev->actconfig->interface[i]->dev);
			dev->actconfig->interface[i] = NULL;
		}
		dev->actconfig = NULL;
		if (dev->state == USB_STATE_CONFIGURED)
			usb_set_device_state(dev, USB_STATE_ADDRESS);
	}
}