static void deferred_probe_work_func(struct work_struct *work) { struct device *dev; struct device_private *private; mutex_lock(&deferred_probe_mutex); while (!list_empty(&deferred_probe_active_list)) { private = list_first_entry(&deferred_probe_active_list, typeof(*dev->p), deferred_probe); dev = private->device; list_del_init(&private->deferred_probe); get_device(dev); mutex_unlock(&deferred_probe_mutex); dev_dbg(dev, "Retrying from deferred list\n"); bus_probe_device(dev); mutex_lock(&deferred_probe_mutex); put_device(dev); }
static int cleanup_dev(struct device *dev, void *data) { struct xenbus_device *xendev = to_xenbus_device(dev); struct xb_find_info *info = data; int len = strlen(info->nodename); DPRINTK("%s", info->nodename); /* Match the info->nodename path, or any subdirectory of that path. */ if (strncmp(xendev->nodename, info->nodename, len)) return 0; /* If the node name is longer, ensure it really is a subdirectory. */ if ((strlen(xendev->nodename) > len) && (xendev->nodename[len] != '/')) return 0; info->dev = xendev; get_device(dev); return 1; }
/* * Called from CUSE IOCTL: VHOST_SET_VRING_KICK * The virtio device sends an eventfd that it can use to notify us. * This fd gets copied into our process space. */ static int set_vring_kick(struct vhost_device_ctx ctx, struct vhost_vring_file *file) { struct virtio_net *dev; struct vhost_virtqueue *vq; dev = get_device(ctx); if (dev == NULL) return -1; /* file->index refers to the queue index. The txq is 1, rxq is 0. */ vq = dev->virtqueue[file->index]; if (vq->kickfd >= 0) close(vq->kickfd); vq->kickfd = file->fd; return 0; }
/** * Disconnect HealthDevice signals */ static gboolean disconnect_device_signals(const char *device_path) { channel_object *c; DBusGProxy *proxy = get_device(device_path); gboolean dirty; if (!device_path) return FALSE; dbus_g_proxy_disconnect_signal(proxy, "ChannelConnected", G_CALLBACK(channel_connected), NULL); dbus_g_proxy_disconnect_signal(proxy, "ChannelDeleted", G_CALLBACK(channel_deleted), NULL); DEBUG("Disconnected device %s", device_path); // Disconnect channels related to this device do { dirty = FALSE; LinkedNode *i = channels()->first; while (i) { c = i->element; if (strcmp(c->device, device_path) == 0) { disconnect_channel(c->handle, 0); dirty = TRUE; break; } i = i->next; } } while (dirty); remove_device(device_path); return TRUE; }
void _ArpControllerRangeList::GenerateItems(const BMessage* settings) { BListItem* item; while ( (item = RemoveItem((int32)0)) ) delete item; if (!mTarget) return; ArpCRef<AmDeviceI> device = get_device(mTarget->Target()); uint32 count = ARP_CONTROLLER_SIZE, k; if (device) count = device->CountControls(); /* Fill in a cache of the map supplied by settings. */ uint8 lowCache[ARP_CONTROLLER_SIZE], highCache[ARP_CONTROLLER_SIZE]; for (k = 0; k < ARP_CONTROLLER_SIZE; k++) { lowCache[k] = 0; highCache[k] = 127; } if (settings) { BMessage msg; int32 cc, low, high; for (k = 0; settings->FindMessage(_RANGE_MSG, k, &msg) == B_OK; k++) { if (msg.FindInt32(_CC_STR, &cc) == B_OK && msg.FindInt32(_LOW_VALUE, &low) == B_OK && msg.FindInt32(_HIGH_VALUE, &high) == B_OK) { ArpASSERT(cc >= 0 && cc < ARP_CONTROLLER_SIZE); if (cc >= 0 && cc < ARP_CONTROLLER_SIZE) { lowCache[cc] = low; highCache[cc] = high; } } msg.MakeEmpty(); } } for (k = 0; k < count; k++) { BString str; _build_label(str, k, lowCache[k], highCache[k], device); _ArpControllerRangeItem* ccItem = new _ArpControllerRangeItem(str.String(), lowCache[k], highCache[k]); if (ccItem) AddItem(ccItem); } }
struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf) { struct dma_buf_attachment *attach; struct sg_table *sg; struct udl_gem_object *uobj; int ret; /* need to attach */ get_device(dev->dev); attach = dma_buf_attach(dma_buf, dev->dev); if (IS_ERR(attach)) { put_device(dev->dev); return ERR_CAST(attach); } get_dma_buf(dma_buf); sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); if (IS_ERR(sg)) { ret = PTR_ERR(sg); goto fail_detach; } ret = udl_prime_create(dev, dma_buf->size, sg, &uobj); if (ret) goto fail_unmap; uobj->base.import_attach = attach; uobj->flags = UDL_BO_WC; return &uobj->base; fail_unmap: dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL); fail_detach: dma_buf_detach(dma_buf, attach); dma_buf_put(dma_buf); put_device(dev->dev); return ERR_PTR(ret); }
static ssize_t blkdev_generic_io(dev_t rdev, char *iobuf, size_t len, unsigned long *pos, int rw) { struct block_device *dev = get_device(rdev); len = MIN(len, dev->sectors*SECTOR_SIZE - *pos); blkcnt_t count = io_block_count(dev->blksize, *pos, len); blkcnt_t first = io_off_to_block(dev->blksize, *pos); unsigned long io_off = io_block_off(dev->blksize, *pos); // populate bio_vec with sequential blocks struct bio_vec *bio = alloc_bio_vec(rdev, count, dev->blksize); for (blkcnt_t i = 0; i < count; i++) bio->block[i] = first + i; ssize_t r = bio_do_io(bio, iobuf, len, io_off, rw); if (r > 0) *pos += r; free_bio_vec(bio); return r; }
/** * bus_for_each_dev - device iterator. * @bus: bus type. * @start: device to start iterating from. * @data: data for the callback. * @fn: function to be called for each device. * * Iterate over @bus's list of devices, and call @fn for each, * passing it @data. If @start is not NULL, we use that device to * begin iterating from. * * We check the return of @fn each time. If it returns anything * other than 0, we break out and return that value. * * NOTE: The device that returns a non-zero value is not retained * in any way, nor is its refcount incremented. If the caller needs * to retain this data, it should do, and increment the reference * count in the supplied callback. */ int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, int (*fn)(struct device *, void *)) { struct device *dev; struct list_head * head; int error = 0; if (!(bus = get_bus(bus))) return -EINVAL; head = &bus->devices.list; dev = list_prepare_entry(start, head, bus_list); down_read(&bus->subsys.rwsem); list_for_each_entry_continue(dev, head, bus_list) { get_device(dev); error = fn(dev,data); put_device(dev); if (error) break; }
/* * when virtio queues are ready to work, qemu will send us to * enable the virtio queue pair. */ int user_set_vring_enable(int vid, struct vhost_vring_state *state) { struct virtio_net *dev; int enable = (int)state->num; dev = get_device(vid); if (dev == NULL) return -1; RTE_LOG(INFO, VHOST_CONFIG, "set queue enable: %d to qp idx: %d\n", enable, state->index); if (notify_ops->vring_state_changed) notify_ops->vring_state_changed(vid, state->index, enable); dev->virtqueue[state->index]->enabled = enable; return 0; }
void Y_usb_get_string(int argc) { char str[STRING_DESCRIPTOR_SIZE]; ydev_instance_t* obj; int index; int ret; if (argc != 2) { y_error("expecting exactly 2 arguments"); } obj = get_device(1); index = ygets_i(0); ret = get_string_descriptor(obj->handle, index, str, sizeof(str)); if (ret < 0) { ypush_int(ret); } else { str[sizeof(str)/sizeof(str[0]) - 1] = 0; push_string(str); } }
static int alarmtimer_rtc_add_device(struct device *dev, struct class_interface *class_intf) { unsigned long flags; struct rtc_device *rtc = to_rtc_device(dev); if (rtcdev) return -EBUSY; if (!rtc->ops->set_alarm) return -1; spin_lock_irqsave(&rtcdev_lock, flags); if (!rtcdev) { rtcdev = rtc; /* hold a reference so it doesn't go away */ get_device(dev); } spin_unlock_irqrestore(&rtcdev_lock, flags); return 0; }
/* _VMKLNX_CODECHECK_: driver_find_device */ struct device * driver_find_device(struct device_driver *drv, struct device * start, void * data, int (*match)(struct device *, void *)) { struct klist_iter i; struct device *dev; #if defined(__VMKLNX__) VMK_ASSERT(vmk_PreemptionIsEnabled() == VMK_FALSE); #endif if (!drv) return NULL; klist_iter_init_node(&drv->klist_devices, &i, (start ? &start->knode_driver : NULL)); while ((dev = next_device(&i))) if (match(dev, data) && get_device(dev)) break; klist_iter_exit(&i); return dev; }
/** * disk_get_part - get partition * @disk: disk to look partition from * @partno: partition number * * Look for partition @partno from @disk. If found, increment * reference count and return it. * * CONTEXT: * Don't care. * * RETURNS: * Pointer to the found partition on success, NULL if not found. */ struct hd_struct *disk_get_part(struct gendisk *disk, int partno) { struct hd_struct *part = NULL; struct disk_part_tbl *ptbl; if (unlikely(partno < 0)) return NULL; rcu_read_lock(); ptbl = rcu_dereference(disk->part_tbl); if (likely(partno < ptbl->len)) { part = rcu_dereference(ptbl->part[partno]); if (part) get_device(part_to_dev(part)); } rcu_read_unlock(); return part; }
void xenbus_dev_shutdown(struct device *_dev) { struct xenbus_device *dev = to_xenbus_device(_dev); unsigned long timeout = 5*HZ; DPRINTK("%s", dev->nodename); get_device(&dev->dev); if (dev->state != XenbusStateConnected) { pr_info("%s: %s: %s != Connected, skipping\n", __func__, dev->nodename, xenbus_strstate(dev->state)); goto out; } xenbus_switch_state(dev, XenbusStateClosing); timeout = wait_for_completion_timeout(&dev->down, timeout); if (!timeout) pr_info("%s: %s timeout closing device\n", __func__, dev->nodename); out: put_device(&dev->dev); }
int gpio_set_func(enum device_id gpio_devid, unsigned int start, unsigned int nr_pins, enum gpio_func func) { const struct device *gpio; struct pio_state *state; u32 mask; state = &pio_state[gpio_devid - DEVICE_PIOA]; gpio = get_device(gpio_devid); if (!gpio) return -EBUSY; state->dev = gpio; mask = ((1 << nr_pins) - 1) << start; if (mask & state->alloc_mask) { put_device(gpio); return -EBUSY; } state->alloc_mask |= mask; switch (func) { case GPIO_FUNC_GPIO: /* TODO */ return -EINVAL; case GPIO_FUNC_A: pio2_writel(gpio, ASR, mask); pio2_writel(gpio, PDR, mask); pio2_writel(gpio, PUDR, mask); break; case GPIO_FUNC_B: pio2_writel(gpio, BSR, mask); pio2_writel(gpio, PDR, mask); pio2_writel(gpio, PUDR, mask); break; } return 0; }
int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem) { struct virtio_net *dev; struct rte_vhost_memory *m; size_t size; dev = get_device(vid); if (!dev) return -1; size = dev->mem->nregions * sizeof(struct rte_vhost_mem_region); m = malloc(sizeof(struct rte_vhost_memory) + size); if (!m) return -1; m->nregions = dev->mem->nregions; memcpy(m->regions, dev->mem->regions, size); *mem = m; return 0; }
std::string StorageDevice::get_device_options() const { if (is_virtual_) { debug_out_warn("app", DBG_FUNC_MSG << "Cannot get device options of a virtual device.\n"); return std::string(); } std::string config_options = app_get_device_option(get_device()); // If we have some special type, specify it on the command line (like "-d scsi"). // Note that the latter "-d" option overrides the former, so we're ok with multiple ones. std::string type_arg = get_type_arg_name(this->get_type()); if (!type_arg.empty()) { if (!config_options.empty()) { config_options += " "; } config_options += "-d " + type_arg; } return config_options; }
static void apple525_disk_set_lines(device_t *device,device_t *image, UINT8 new_state) { apple525_floppy_image_device *cur_disk; UINT8 old_state; unsigned int phase; cur_disk = get_device(image); old_state = cur_disk->state; cur_disk->state = new_state; if ((new_state & 0x0F) > (old_state & 0x0F)) { phase = 0; switch((old_state ^ new_state) & 0x0F) { case 1: phase = 0; break; case 2: phase = 1; break; case 4: phase = 2; break; case 8: phase = 3; break; } phase -= floppy_drive_get_current_track(image) * 2; if (cur_disk->tween_tracks) phase--; phase %= 4; switch(phase) { case 1: apple525_seek_disk(image, +1); break; case 3: apple525_seek_disk(image, -1); break; } } }
/* * Called from CUSE IOCTL: VHOST_SET_VRING_ADDR * The virtio device sends us the desc, used and avail ring addresses. This function * then converts these to our address space. */ static int set_vring_addr(struct vhost_device_ctx ctx, struct vhost_vring_addr *addr) { struct virtio_net *dev; struct vhost_virtqueue *vq; dev = get_device(ctx); if (dev == NULL) return -1; /* addr->index refers to the queue index. The TX queue is 1, RX queue is 0. */ vq = dev->virtqueue[addr->index]; /* The addresses are converted from QEMU virtual to Vhost virtual. */ vq->desc = (struct vring_desc *)(uintptr_t)qva_to_vva(dev, addr->desc_user_addr); if (vq->desc == 0) { RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find descriptor ring address.\n", dev->device_fh); return -1; } vq->avail = (struct vring_avail *)(uintptr_t)qva_to_vva(dev, addr->avail_user_addr); if (vq->avail == 0) { RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find available ring address.\n", dev->device_fh); return -1; } vq->used = (struct vring_used *)(uintptr_t)qva_to_vva(dev, addr->used_user_addr); if (vq->used == 0) { RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find used ring address.\n", dev->device_fh); return -1; } LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") mapped address desc: %p\n", dev->device_fh, vq->desc); LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") mapped address avail: %p\n", dev->device_fh, vq->avail); LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") mapped address used: %p\n", dev->device_fh, vq->used); return 0; }
void audio_protocol::setup_tree(int inputs, int outputs) { auto& dev = get_device(); auto& root = dev.get_root_node(); audio_ins.clear(); audio_outs.clear(); main_audio_in = ossia::net::find_or_create_parameter<ossia::audio_parameter>( root, "/in/main"); main_audio_out = ossia::net::find_or_create_parameter<ossia::audio_parameter>( root, "/out/main"); for (int i = 0; i < inputs; i++) { audio_ins.push_back( ossia::net::find_or_create_parameter<ossia::audio_parameter>( root, "/in/" + std::to_string(i))); } for (int i = 0; i < outputs; i++) { audio_outs.push_back( ossia::net::find_or_create_parameter<ossia::audio_parameter>( root, "/out/" + std::to_string(i))); } main_audio_in->audio.resize(inputs); for (int i = 0; i < inputs; i++) { audio_ins[i]->audio.resize(1); } main_audio_out->audio.resize(outputs); for (int i = 0; i < outputs; i++) { audio_outs[i]->audio.resize(1); } }
void test_platforms() { int i, j; char desc[256]; struct cl_exec exec = { 0, 0, 1 }; //Initialize the runtime cl_runtime rt = new_cl_runtime(false); printf("Testing %d platforms\n\n", get_num_platforms()); for(i = 0; i < get_num_platforms(); i++) { exec.platform = i; clGetPlatformInfo(get_platform(rt, i), CL_PLATFORM_NAME, sizeof(desc), desc, NULL); printf("Testing devices for %s platform\n", desc); for(j = 0; j < get_num_devices(i); j++) { exec.device = j; test_device(rt, exec, get_device(rt, i, j)); } printf("\n"); } delete_cl_runtime(rt); }
/* * Called from CUSE IOCTL: VHOST_NET_SET_BACKEND * To complete device initialisation when the virtio driver is loaded we are provided with a * valid fd for a tap device (not used by us). If this happens then we can add the device to a * data core. When the virtio driver is removed we get fd=-1. At that point we remove the device * from the data core. The device will still exist in the device configuration linked list. */ static int set_backend(struct vhost_device_ctx ctx, struct vhost_vring_file *file) { struct virtio_net *dev; dev = get_device(ctx); if (dev == NULL) return -1; /* file->index refers to the queue index. The TX queue is 1, RX queue is 0. */ dev->virtqueue[file->index]->backend = file->fd; /* If the device isn't already running and both backend fds are set we add the device. */ if (!(dev->flags & VIRTIO_DEV_RUNNING)) { if (((int)dev->virtqueue[VIRTIO_TXQ]->backend != VIRTIO_DEV_STOPPED) && ((int)dev->virtqueue[VIRTIO_RXQ]->backend != VIRTIO_DEV_STOPPED)) return notify_ops->new_device(dev); /* Otherwise we remove it. */ } else if (file->fd == VIRTIO_DEV_STOPPED) notify_ops->destroy_device(dev); return 0; }
/* * In vhost-user, when we receive kick message, will test whether virtio * device is ready for packet processing. */ void user_set_vring_kick(int vid, struct VhostUserMsg *pmsg) { struct vhost_vring_file file; struct virtio_net *dev = get_device(vid); if (!dev) return; file.index = pmsg->payload.u64 & VHOST_USER_VRING_IDX_MASK; if (pmsg->payload.u64 & VHOST_USER_VRING_NOFD_MASK) file.fd = VIRTIO_INVALID_EVENTFD; else file.fd = pmsg->fds[0]; RTE_LOG(INFO, VHOST_CONFIG, "vring kick idx:%d file:%d\n", file.index, file.fd); vhost_set_vring_kick(vid, &file); if (virtio_is_ready(dev) && !(dev->flags & VIRTIO_DEV_RUNNING)) { if (notify_ops->new_device(vid) == 0) dev->flags |= VIRTIO_DEV_RUNNING; } }
Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const { Vector2 g = p_xform.xform(get_global_position()); Vector2 l = p_xform.xform(get_position() + p_local_ofs); Vector2 r = p_xform.basis_xform(get_relative()); Vector2 s = p_xform.basis_xform(get_speed()); Ref<InputEventMouseMotion> mm; mm.instance(); mm->set_device(get_device()); mm->set_modifiers_from_event(this); mm->set_position(l); mm->set_global_position(g); mm->set_button_mask(get_button_mask()); mm->set_relative(r); mm->set_speed(s); return mm; }
Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const { Vector2 g = p_xform.xform(get_global_position()); Vector2 l = p_xform.xform(get_position() + p_local_ofs); Ref<InputEventMouseButton> mb; mb.instance(); mb->set_device(get_device()); mb->set_modifiers_from_event(this); mb->set_position(l); mb->set_global_position(g); mb->set_button_mask(get_button_mask()); mb->set_pressed(pressed); mb->set_doubleclick(doubleclick); mb->set_factor(factor); mb->set_button_index(button_index); return mb; }
void hardware::code::Real::set_real_to_difference_device(const hardware::buffers::Plain<hmc_float>* a, const hardware::buffers::Plain<hmc_float>* b, const hardware::buffers::Plain<hmc_float>* out) const { // query work-sizes for kernel size_t ls2, gs2; cl_uint num_groups; this->get_work_sizes(difference, &ls2, &gs2, &num_groups); // set arguments int clerr = clSetKernelArg(difference, 0, sizeof(cl_mem), a->get_cl_buffer()); if (clerr != CL_SUCCESS) throw Opencl_Error(clerr, "clSetKernelArg", __FILE__, __LINE__); clerr = clSetKernelArg(difference, 1, sizeof(cl_mem), b->get_cl_buffer()); if (clerr != CL_SUCCESS) throw Opencl_Error(clerr, "clSetKernelArg", __FILE__, __LINE__); clerr = clSetKernelArg(difference, 2, sizeof(cl_mem), out->get_cl_buffer()); if (clerr != CL_SUCCESS) throw Opencl_Error(clerr, "clSetKernelArg", __FILE__, __LINE__); get_device()->enqueue_kernel(difference, gs2, ls2); }
void hardware::code::Real::set_vector_element_to_real_device(const hardware::buffers::Plain<hmc_float>* in, const int index, const hardware::buffers::Plain<hmc_float>* out) const { // query work-sizes for kernel size_t ls2, gs2; cl_uint num_groups; this->get_work_sizes(set_elem_vec, &ls2, &gs2, &num_groups); // set arguments int clerr = clSetKernelArg(set_elem_vec, 0, sizeof(cl_mem), in->get_cl_buffer()); if (clerr != CL_SUCCESS) throw Opencl_Error(clerr, "clSetKernelArg", __FILE__, __LINE__); clerr = clSetKernelArg(set_elem_vec, 1, sizeof(cl_int), &index); if (clerr != CL_SUCCESS) throw Opencl_Error(clerr, "clSetKernelArg", __FILE__, __LINE__); clerr = clSetKernelArg(set_elem_vec, 2, sizeof(cl_mem), out->get_cl_buffer()); if (clerr != CL_SUCCESS) throw Opencl_Error(clerr, "clSetKernelArg", __FILE__, __LINE__); get_device()->enqueue_kernel(set_elem_vec, gs2, ls2); }
int cec_get_device(struct cec_devnode *devnode) { /* * Check if the cec device is available. This needs to be done with * the devnode->lock held to prevent an open/unregister race: * without the lock, the device could be unregistered and freed between * the devnode->registered check and get_device() calls, leading to * a crash. */ mutex_lock(&devnode->lock); /* * return ENXIO if the cec device has been removed * already or if it is not registered anymore. */ if (!devnode->registered) { mutex_unlock(&devnode->lock); return -ENXIO; } /* and increase the device refcount */ get_device(&devnode->dev); mutex_unlock(&devnode->lock); return 0; }
/** * bus_find_device - device iterator for locating a particular device. * @bus: bus type * @start: Device to begin with * @data: Data to pass to match function * @match: Callback function to check device * * This is similar to the bus_for_each_dev() function above, but it * returns a reference to a device that is 'found' for later use, as * determined by the @match callback. * * The callback should return 0 if the device doesn't match and non-zero * if it does. If the callback returns non-zero, this function will * return to the caller and not iterate over any more devices. */ struct device * bus_find_device(struct bus_type *bus, struct device *start, void *data, int (*match)(struct device *, void *)) { struct klist_iter i; struct device *dev; printk(KERN_ERR "%s: == mydebug 000 data:%s\n", __FUNCTION__,data); if (!bus) return NULL; printk(KERN_ERR "%s: == mydebug 001\n", __FUNCTION__); klist_iter_init_node(&bus->klist_devices, &i, (start ? &start->knode_bus : NULL)); printk(KERN_ERR "%s: == mydebug 002\n", __FUNCTION__); while ((dev = next_device(&i))) if (match(dev, data) && get_device(dev)){ printk(KERN_ERR "%s: == mydebug 003\n", __FUNCTION__); break; } klist_iter_exit(&i); return dev; }
/** * deferred_probe_work_func() - Retry probing devices in the active list. */ static void deferred_probe_work_func(struct work_struct *work) { struct device *dev; struct device_private *private; /* * This block processes every device in the deferred 'active' list. * Each device is removed from the active list and passed to * bus_probe_device() to re-attempt the probe. The loop continues * until every device in the active list is removed and retried. * * Note: Once the device is removed from the list and the mutex is * released, it is possible for the device get freed by another thread * and cause a illegal pointer dereference. This code uses * get/put_device() to ensure the device structure cannot disappear * from under our feet. */ mutex_lock(&deferred_probe_mutex); while (!list_empty(&deferred_probe_active_list)) { private = list_first_entry(&deferred_probe_active_list, typeof(*dev->p), deferred_probe); dev = private->device; list_del_init(&private->deferred_probe); get_device(dev); /* * Drop the mutex while probing each device; the probe path may * manipulate the deferred list */ mutex_unlock(&deferred_probe_mutex); dev_dbg(dev, "Retrying from deferred list\n"); bus_probe_device(dev); mutex_lock(&deferred_probe_mutex); put_device(dev); }