[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2/3] PVUSB update and bugfix: backend part
Signed-off-by: Noboru Iwamatsu <n_iwamatsu@xxxxxxxxxxxxxx> diff -r 4ac3e1d6605c -r 3be939975ad6 drivers/xen/usbback/interface.c --- a/drivers/xen/usbback/interface.c Tue Sep 29 11:23:06 2009 +0100 +++ b/drivers/xen/usbback/interface.c Tue Oct 06 15:18:27 2009 +0900 @@ -48,7 +48,7 @@ static LIST_HEAD(usbif_list); static DEFINE_SPINLOCK(usbif_list_lock); -usbif_t *find_usbif(int dom_id, int dev_id) +usbif_t *find_usbif(domid_t domid, unsigned int handle) { usbif_t *usbif; int found = 0; @@ -56,8 +56,8 @@ spin_lock_irqsave(&usbif_list_lock, flags); list_for_each_entry(usbif, &usbif_list, usbif_list) { - if (usbif->domid == dom_id - && usbif->handle == dev_id) { + if (usbif->domid == domid + && usbif->handle == handle) { found = 1; break; } @@ -82,16 +82,16 @@ usbif->domid = domid; usbif->handle = handle; - spin_lock_init(&usbif->ring_lock); + spin_lock_init(&usbif->urb_ring_lock); + spin_lock_init(&usbif->conn_ring_lock); atomic_set(&usbif->refcnt, 0); init_waitqueue_head(&usbif->wq); init_waitqueue_head(&usbif->waiting_to_free); - spin_lock_init(&usbif->plug_lock); - INIT_LIST_HEAD(&usbif->plugged_devices); + spin_lock_init(&usbif->stub_lock); + INIT_LIST_HEAD(&usbif->stub_list); spin_lock_init(&usbif->addr_lock); - for (i = 0; i < USB_DEV_ADDR_SIZE; i++) { + for (i = 0; i < USB_DEV_ADDR_SIZE; i++) usbif->addr_table[i] = NULL; - } spin_lock_irqsave(&usbif_list_lock, flags); list_add(&usbif->usbif_list, &usbif_list); @@ -100,70 +100,109 @@ return usbif; } -static int map_frontend_page(usbif_t *usbif, unsigned long shared_page) +static int map_frontend_pages(usbif_t *usbif, + grant_ref_t urb_ring_ref, + grant_ref_t conn_ring_ref) { struct gnttab_map_grant_ref op; - gnttab_set_map_op(&op, (unsigned long)usbif->ring_area->addr, - GNTMAP_host_map, shared_page, usbif->domid); + gnttab_set_map_op(&op, (unsigned long)usbif->urb_ring_area->addr, + GNTMAP_host_map, urb_ring_ref, usbif->domid); if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) BUG(); if (op.status) { - printk(KERN_ERR "grant table operation failure\n"); + printk(KERN_ERR "grant table failure mapping urb_ring_ref\n"); return op.status; } - usbif->shmem_ref = shared_page; - usbif->shmem_handle = op.handle; + usbif->urb_shmem_ref = urb_ring_ref; + usbif->urb_shmem_handle = op.handle; + + gnttab_set_map_op(&op, (unsigned long)usbif->conn_ring_area->addr, + GNTMAP_host_map, conn_ring_ref, usbif->domid); + + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); + + if (op.status) { + struct gnttab_unmap_grant_ref unop; + gnttab_set_unmap_op(&unop, + (unsigned long) usbif->urb_ring_area->addr, + GNTMAP_host_map, usbif->urb_shmem_handle); + VOID(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unop, + 1)); + printk(KERN_ERR "grant table failure mapping conn_ring_ref\n"); + return op.status; + } + + usbif->conn_shmem_ref = conn_ring_ref; + usbif->conn_shmem_handle = op.handle; return 0; } -static void unmap_frontend_page(usbif_t *usbif) +static void unmap_frontend_pages(usbif_t *usbif) { struct gnttab_unmap_grant_ref op; - gnttab_set_unmap_op(&op, (unsigned long)usbif->ring_area->addr, - GNTMAP_host_map, usbif->shmem_handle); + gnttab_set_unmap_op(&op, (unsigned long)usbif->urb_ring_area->addr, + GNTMAP_host_map, usbif->urb_shmem_handle); + + if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) + BUG(); + + gnttab_set_unmap_op(&op, (unsigned long)usbif->conn_ring_area->addr, + GNTMAP_host_map, usbif->conn_shmem_handle); if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) BUG(); } -int usbif_map(usbif_t *usbif, unsigned long shared_page, unsigned int evtchn) +int usbif_map(usbif_t *usbif, unsigned long urb_ring_ref, + unsigned long conn_ring_ref, unsigned int evtchn) { - int err; - usbif_sring_t *sring; + int err = -ENOMEM; + + usbif_urb_sring_t *urb_sring; + usbif_conn_sring_t *conn_sring; if (usbif->irq) return 0; - if ((usbif->ring_area = alloc_vm_area(PAGE_SIZE)) == NULL) - return -ENOMEM; + if ((usbif->urb_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL) + return err; + if ((usbif->conn_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL) + goto fail_alloc; - err = map_frontend_page(usbif, shared_page); - if (err) { - free_vm_area(usbif->ring_area); - return err; - } - - sring = (usbif_sring_t *) usbif->ring_area->addr; - BACK_RING_INIT(&usbif->ring, sring, PAGE_SIZE); + err = map_frontend_pages(usbif, urb_ring_ref, conn_ring_ref); + if (err) + goto fail_map; err = bind_interdomain_evtchn_to_irqhandler( - usbif->domid, evtchn, usbbk_be_int, 0, "usbif-backend", usbif); + usbif->domid, evtchn, usbbk_be_int, 0, + "usbif-backend", usbif); if (err < 0) - { - unmap_frontend_page(usbif); - free_vm_area(usbif->ring_area); - usbif->ring.sring = NULL; - return err; - } + goto fail_evtchn; usbif->irq = err; + urb_sring = (usbif_urb_sring_t *) usbif->urb_ring_area->addr; + BACK_RING_INIT(&usbif->urb_ring, urb_sring, PAGE_SIZE); + + conn_sring = (usbif_conn_sring_t *) usbif->conn_ring_area->addr; + BACK_RING_INIT(&usbif->conn_ring, conn_sring, PAGE_SIZE); + return 0; + +fail_evtchn: + unmap_frontend_pages(usbif); +fail_map: + free_vm_area(usbif->conn_ring_area); +fail_alloc: + free_vm_area(usbif->urb_ring_area); + + return err; } void usbif_disconnect(usbif_t *usbif) @@ -176,12 +215,12 @@ usbif->xenusbd = NULL; } - spin_lock_irqsave(&usbif->plug_lock, flags); - list_for_each_entry_safe(stub, tmp, &usbif->plugged_devices, plugged_list) { + spin_lock_irqsave(&usbif->stub_lock, flags); + list_for_each_entry_safe(stub, tmp, &usbif->stub_list, dev_list) { usbbk_unlink_urbs(stub); detach_device_without_lock(usbif, stub); } - spin_unlock_irqrestore(&usbif->plug_lock, flags); + spin_unlock_irqrestore(&usbif->stub_lock, flags); wait_event(usbif->waiting_to_free, atomic_read(&usbif->refcnt) == 0); @@ -190,10 +229,12 @@ usbif->irq = 0; } - if (usbif->ring.sring) { - unmap_frontend_page(usbif); - free_vm_area(usbif->ring_area); - usbif->ring.sring = NULL; + if (usbif->urb_ring.sring) { + unmap_frontend_pages(usbif); + free_vm_area(usbif->urb_ring_area); + free_vm_area(usbif->conn_ring_area); + usbif->urb_ring.sring = NULL; + usbif->conn_ring.sring = NULL; } } diff -r 4ac3e1d6605c -r 3be939975ad6 drivers/xen/usbback/usbback.c --- a/drivers/xen/usbback/usbback.c Tue Sep 29 11:23:06 2009 +0100 +++ b/drivers/xen/usbback/usbback.c Tue Oct 06 15:18:27 2009 +0900 @@ -107,7 +107,7 @@ #define pending_handle(_req, _seg) \ (pending_grant_handles[vaddr_pagenr(_req, _seg)]) -static pending_req_t* alloc_req(void) +static pending_req_t *alloc_req(void) { pending_req_t *req = NULL; unsigned long flags; @@ -222,7 +222,7 @@ } } -static int usbbk_alloc_urb(usbif_request_t *req, pending_req_t *pending_req) +static int usbbk_alloc_urb(usbif_urb_request_t *req, pending_req_t *pending_req) { int ret; @@ -298,21 +298,21 @@ int32_t actual_length, int32_t error_count, uint16_t start_frame) { usbif_t *usbif = pending_req->usbif; - usbif_response_t *ring_res; + usbif_urb_response_t *res; unsigned long flags; int notify; - spin_lock_irqsave(&usbif->ring_lock, flags); - ring_res = RING_GET_RESPONSE(&usbif->ring, usbif->ring.rsp_prod_pvt); - ring_res->id = pending_req->id; - ring_res->status = status; - ring_res->actual_length = actual_length; - ring_res->error_count = error_count; - ring_res->start_frame = start_frame; - usbif->ring.rsp_prod_pvt++; + spin_lock_irqsave(&usbif->urb_ring_lock, flags); + res = RING_GET_RESPONSE(&usbif->urb_ring, usbif->urb_ring.rsp_prod_pvt); + res->id = pending_req->id; + res->status = status; + res->actual_length = actual_length; + res->error_count = error_count; + res->start_frame = start_frame; + usbif->urb_ring.rsp_prod_pvt++; barrier(); - RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&usbif->ring, notify); - spin_unlock_irqrestore(&usbif->ring_lock, flags); + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&usbif->urb_ring, notify); + spin_unlock_irqrestore(&usbif->urb_ring_lock, flags); if (notify) notify_remote_via_irq(usbif->irq); @@ -346,7 +346,7 @@ } static int usbbk_gnttab_map(usbif_t *usbif, - usbif_request_t *req, pending_req_t *pending_req) + usbif_urb_request_t *req, pending_req_t *pending_req) { int i, ret; unsigned int nr_segs; @@ -434,7 +434,7 @@ return ret; } -static void usbbk_init_urb(usbif_request_t *req, pending_req_t *pending_req) +static void usbbk_init_urb(usbif_urb_request_t *req, pending_req_t *pending_req) { unsigned int pipe; struct usb_device *udev = pending_req->stub->udev; @@ -671,14 +671,14 @@ int found = 0; unsigned long flags; - spin_lock_irqsave(&usbif->plug_lock, flags); - list_for_each_entry(stub, &usbif->plugged_devices, plugged_list) { - if (stub->id->portnum == portnum) { + spin_lock_irqsave(&usbif->stub_lock, flags); + list_for_each_entry(stub, &usbif->stub_list, dev_list) { + if (stub->portid->portnum == portnum) { found = 1; break; } } - spin_unlock_irqrestore(&usbif->plug_lock, flags); + spin_unlock_irqrestore(&usbif->stub_lock, flags); if (found) return stub; @@ -686,7 +686,47 @@ return NULL; } -static int check_and_submit_special_ctrlreq(usbif_t *usbif, usbif_request_t *req, pending_req_t *pending_req) +static void process_unlink_req(usbif_t *usbif, + usbif_urb_request_t *req, pending_req_t *pending_req) +{ + pending_req_t *unlink_req = NULL; + int devnum; + int ret = 0; + unsigned long flags; + + devnum = usb_pipedevice(req->pipe); + if (unlikely(devnum == 0)) { + pending_req->stub = find_attached_device(usbif, usbif_pipeportnum(req->pipe)); + if (unlikely(!pending_req->stub)) { + ret = -ENODEV; + goto fail_response; + } + } else { + if (unlikely(!usbif->addr_table[devnum])) { + ret = -ENODEV; + goto fail_response; + } + pending_req->stub = usbif->addr_table[devnum]; + } + + spin_lock_irqsave(&pending_req->stub->submitting_lock, flags); + list_for_each_entry(unlink_req, &pending_req->stub->submitting_list, urb_list) { + if (unlink_req->id == req->u.unlink.unlink_id) { + ret = usb_unlink_urb(unlink_req->urb); + break; + } + } + spin_unlock_irqrestore(&pending_req->stub->submitting_lock, flags); + +fail_response: + usbbk_do_response(pending_req, ret, 0, 0, 0); + usbif_put(usbif); + free_req(pending_req); + return; +} + +static int check_and_submit_special_ctrlreq(usbif_t *usbif, + usbif_urb_request_t *req, pending_req_t *pending_req) { int devnum; struct usbstub *stub = NULL; @@ -824,7 +864,7 @@ } static void dispatch_request_to_pending_reqs(usbif_t *usbif, - usbif_request_t *req, + usbif_urb_request_t *req, pending_req_t *pending_req) { int ret; @@ -834,17 +874,13 @@ barrier(); - /* - * TODO: - * receive unlink request and cancel the urb in backend - */ -#if 0 - if (unlikely(usb_pipeunlink(req->pipe))) { + usbif_get(usbif); + /* unlink request */ + if (unlikely(usbif_pipeunlink(req->pipe))) { + process_unlink_req(usbif, req, pending_req); + return; } -#endif - - usbif_get(usbif); if (usb_pipecontrol(req->pipe)) { if (check_and_submit_special_ctrlreq(usbif, req, pending_req)) @@ -927,18 +963,18 @@ static int usbbk_start_submit_urb(usbif_t *usbif) { - usbif_back_ring_t *usb_ring = &usbif->ring; - usbif_request_t *ring_req; + usbif_urb_back_ring_t *urb_ring = &usbif->urb_ring; + usbif_urb_request_t *req; pending_req_t *pending_req; RING_IDX rc, rp; int more_to_do = 0; - rc = usb_ring->req_cons; - rp = usb_ring->sring->req_prod; + rc = urb_ring->req_cons; + rp = urb_ring->sring->req_prod; rmb(); while (rc != rp) { - if (RING_REQUEST_CONS_OVERFLOW(usb_ring, rc)) { + if (RING_REQUEST_CONS_OVERFLOW(urb_ring, rc)) { printk(KERN_WARNING "RING_REQUEST_CONS_OVERFLOW\n"); break; } @@ -949,73 +985,100 @@ break; } - ring_req = RING_GET_REQUEST(usb_ring, rc); - usb_ring->req_cons = ++rc; + req = RING_GET_REQUEST(urb_ring, rc); + urb_ring->req_cons = ++rc; - dispatch_request_to_pending_reqs(usbif, ring_req, + dispatch_request_to_pending_reqs(usbif, req, pending_req); } - RING_FINAL_CHECK_FOR_REQUESTS(&usbif->ring, more_to_do); + RING_FINAL_CHECK_FOR_REQUESTS(&usbif->urb_ring, more_to_do); cond_resched(); return more_to_do; } +void usbbk_hotplug_notify(usbif_t *usbif, int portnum, int speed) +{ + usbif_conn_back_ring_t *ring = &usbif->conn_ring; + usbif_conn_request_t *req; + usbif_conn_response_t *res; + unsigned long flags; + u16 id; + int notify; + + spin_lock_irqsave(&usbif->conn_ring_lock, flags); + + req = RING_GET_REQUEST(ring, ring->req_cons);; + id = req->id; + ring->req_cons++; + ring->sring->req_event = ring->req_cons + 1; + + res = RING_GET_RESPONSE(ring, ring->rsp_prod_pvt); + res->id = id; + res->portnum = portnum; + res->speed = speed; + ring->rsp_prod_pvt++; + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(ring, notify); + + spin_unlock_irqrestore(&usbif->conn_ring_lock, flags); + + if (notify) + notify_remote_via_irq(usbif->irq); +} + int usbbk_schedule(void *arg) { - usbif_t *usbif = (usbif_t *)arg; + usbif_t *usbif = (usbif_t *) arg; - usbif_get(usbif); + usbif_get(usbif); - while(!kthread_should_stop()) { - wait_event_interruptible( - usbif->wq, - usbif->waiting_reqs || kthread_should_stop()); - wait_event_interruptible( - pending_free_wq, - !list_empty(&pending_free) || kthread_should_stop()); - usbif->waiting_reqs = 0; - smp_mb(); + while (!kthread_should_stop()) { + wait_event_interruptible( + usbif->wq, + usbif->waiting_reqs || kthread_should_stop()); + wait_event_interruptible( + pending_free_wq, + !list_empty(&pending_free) || kthread_should_stop()); + usbif->waiting_reqs = 0; + smp_mb(); - if (usbbk_start_submit_urb(usbif)) - usbif->waiting_reqs = 1; - } + if (usbbk_start_submit_urb(usbif)) + usbif->waiting_reqs = 1; + } - usbif->xenusbd = NULL; - usbif_put(usbif); + usbif->xenusbd = NULL; + usbif_put(usbif); - return 0; + return 0; } /* - * attach the grabbed device to usbif. + * attach usbstub device to usbif. */ -void usbbk_plug_device(usbif_t *usbif, struct usbstub *stub) +void usbbk_attach_device(usbif_t *usbif, struct usbstub *stub) { unsigned long flags; - spin_lock_irqsave(&usbif->plug_lock, flags); - list_add(&stub->plugged_list, &usbif->plugged_devices); - spin_unlock_irqrestore(&usbif->plug_lock, flags); - stub->plugged = 1; + spin_lock_irqsave(&usbif->stub_lock, flags); + list_add(&stub->dev_list, &usbif->stub_list); + spin_unlock_irqrestore(&usbif->stub_lock, flags); stub->usbif = usbif; } /* - * detach the grabbed device from usbif. + * detach usbstub device from usbif. */ -void usbbk_unplug_device(usbif_t *usbif, struct usbstub *stub) +void usbbk_detach_device(usbif_t *usbif, struct usbstub *stub) { unsigned long flags; if (stub->addr) usbbk_set_address(usbif, stub, stub->addr, 0); - spin_lock_irqsave(&usbif->plug_lock, flags); - list_del(&stub->plugged_list); - spin_unlock_irqrestore(&usbif->plug_lock, flags); - stub->plugged = 0; + spin_lock_irqsave(&usbif->stub_lock, flags); + list_del(&stub->dev_list); + spin_unlock_irqrestore(&usbif->stub_lock, flags); stub->usbif = NULL; } @@ -1023,8 +1086,7 @@ { if (stub->addr) usbbk_set_address(usbif, stub, stub->addr, 0); - list_del(&stub->plugged_list); - stub->plugged = 0; + list_del(&stub->dev_list); stub->usbif = NULL; } @@ -1054,9 +1116,8 @@ memset(pending_reqs, 0, sizeof(pending_reqs)); INIT_LIST_HEAD(&pending_free); - for (i = 0; i < usbif_reqs; i++) { + for (i = 0; i < usbif_reqs; i++) list_add_tail(&pending_reqs[i].free_list, &pending_free); - } usbback_xenbus_init(); diff -r 4ac3e1d6605c -r 3be939975ad6 drivers/xen/usbback/usbback.h --- a/drivers/xen/usbback/usbback.h Tue Sep 29 11:23:06 2009 +0100 +++ b/drivers/xen/usbback/usbback.h Tue Oct 06 15:18:27 2009 +0900 @@ -59,6 +59,7 @@ #include <xen/gnttab.h> #include <xen/driver_util.h> #include <xen/interface/xen.h> +#include <xen/xenbus.h> #include <xen/interface/io/usbif.h> struct usbstub; @@ -66,89 +67,103 @@ #define USB_DEV_ADDR_SIZE 128 typedef struct usbif_st { - domid_t domid; - unsigned int handle; + domid_t domid; + unsigned int handle; + int num_ports; + enum usb_spec_version usb_ver; + struct xenbus_device *xbdev; struct list_head usbif_list; unsigned int irq; - usbif_back_ring_t ring; - struct vm_struct *ring_area; + usbif_urb_back_ring_t urb_ring; + usbif_conn_back_ring_t conn_ring; + struct vm_struct *urb_ring_area; + struct vm_struct *conn_ring_area; - spinlock_t ring_lock; + spinlock_t urb_ring_lock; + spinlock_t conn_ring_lock; atomic_t refcnt; - grant_handle_t shmem_handle; - grant_ref_t shmem_ref; + + grant_handle_t urb_shmem_handle; + grant_ref_t urb_shmem_ref; + grant_handle_t conn_shmem_handle; + grant_ref_t conn_shmem_ref; + + struct xenbus_watch backend_watch; /* device address lookup table */ + struct usbstub *addr_table[USB_DEV_ADDR_SIZE]; spinlock_t addr_lock; - struct usbstub *addr_table[USB_DEV_ADDR_SIZE]; - /* plugged device list */ - unsigned plaggable:1; - spinlock_t plug_lock; - struct list_head plugged_devices; + /* connected device list */ + struct list_head stub_list; + spinlock_t stub_lock; /* request schedule */ struct task_struct *xenusbd; unsigned int waiting_reqs; wait_queue_head_t waiting_to_free; wait_queue_head_t wq; - } usbif_t; -struct usbstub_id -{ +struct vusb_port_id { struct list_head id_list; - char bus_id[BUS_ID_SIZE]; - int dom_id; - int dev_id; + char phys_bus[BUS_ID_SIZE]; + domid_t domid; + unsigned int handle; int portnum; + unsigned is_connected:1; }; -struct usbstub -{ - struct usbstub_id *id; +struct usbstub { + struct kref kref; + struct list_head dev_list; + + struct vusb_port_id *portid; struct usb_device *udev; - struct usb_interface *interface; usbif_t *usbif; - - struct list_head grabbed_list; - - unsigned plugged:1; - struct list_head plugged_list; - int addr; + struct list_head submitting_list; spinlock_t submitting_lock; - struct list_head submitting_list; }; usbif_t *usbif_alloc(domid_t domid, unsigned int handle); void usbif_disconnect(usbif_t *usbif); void usbif_free(usbif_t *usbif); -int usbif_map(usbif_t *usbif, unsigned long shared_page, unsigned int evtchn); +int usbif_map(usbif_t *usbif, unsigned long urb_ring_ref, + unsigned long conn_ring_ref, unsigned int evtchn); #define usbif_get(_b) (atomic_inc(&(_b)->refcnt)) #define usbif_put(_b) \ do { \ if (atomic_dec_and_test(&(_b)->refcnt)) \ - wake_up(&(_b)->waiting_to_free); \ + wake_up(&(_b)->waiting_to_free); \ } while (0) +usbif_t *find_usbif(domid_t domid, unsigned int handle); void usbback_xenbus_init(void); void usbback_xenbus_exit(void); - +struct vusb_port_id *find_portid_by_busid(const char *busid); +struct vusb_port_id *find_portid(const domid_t domid, + const unsigned int handle, + const int portnum); +int portid_add(const char *busid, + const domid_t domid, + const unsigned int handle, + const int portnum); +int portid_remove(const domid_t domid, + const unsigned int handle, + const int portnum); irqreturn_t usbbk_be_int(int irq, void *dev_id, struct pt_regs *regs); int usbbk_schedule(void *arg); struct usbstub *find_attached_device(usbif_t *usbif, int port); -struct usbstub *find_grabbed_device(int dom_id, int dev_id, int port); -usbif_t *find_usbif(int dom_id, int dev_id); -void usbback_reconfigure(usbif_t *usbif); -void usbbk_plug_device(usbif_t *usbif, struct usbstub *stub); -void usbbk_unplug_device(usbif_t *usbif, struct usbstub *stub); +void usbbk_attach_device(usbif_t *usbif, struct usbstub *stub); +void usbbk_detach_device(usbif_t *usbif, struct usbstub *stub); +void usbbk_hotplug_notify(usbif_t *usbif, int portnum, int speed); void detach_device_without_lock(usbif_t *usbif, struct usbstub *stub); void usbbk_unlink_urbs(struct usbstub *stub); diff -r 4ac3e1d6605c -r 3be939975ad6 drivers/xen/usbback/usbstub.c --- a/drivers/xen/usbback/usbstub.c Tue Sep 29 11:23:06 2009 +0100 +++ b/drivers/xen/usbback/usbstub.c Tue Oct 06 15:18:27 2009 +0900 @@ -45,36 +45,106 @@ #include "usbback.h" -static LIST_HEAD(usbstub_ids); -static DEFINE_SPINLOCK(usbstub_ids_lock); -static LIST_HEAD(grabbed_devices); -static DEFINE_SPINLOCK(grabbed_devices_lock); +static LIST_HEAD(port_list); +static DEFINE_SPINLOCK(port_list_lock); -struct usbstub *find_grabbed_device(int dom_id, int dev_id, int portnum) +struct vusb_port_id *find_portid_by_busid(const char *busid) { - struct usbstub *stub; + struct vusb_port_id *portid; int found = 0; unsigned long flags; - spin_lock_irqsave(&grabbed_devices_lock, flags); - list_for_each_entry(stub, &grabbed_devices, grabbed_list) { - if (stub->id->dom_id == dom_id - && stub->id->dev_id == dev_id - && stub->id->portnum == portnum) { + spin_lock_irqsave(&port_list_lock, flags); + list_for_each_entry(portid, &port_list, id_list) { + if (!(strncmp(portid->phys_bus, busid, BUS_ID_SIZE))) { found = 1; break; } } - spin_unlock_irqrestore(&grabbed_devices_lock, flags); + spin_unlock_irqrestore(&port_list_lock, flags); if (found) - return stub; + return portid; return NULL; } -static struct usbstub *usbstub_alloc(struct usb_interface *interface, - struct usbstub_id *stub_id) +struct vusb_port_id *find_portid(const domid_t domid, + const unsigned int handle, + const int portnum) +{ + struct vusb_port_id *portid; + int found = 0; + unsigned long flags; + + spin_lock_irqsave(&port_list_lock, flags); + list_for_each_entry(portid, &port_list, id_list) { + if ((portid->domid == domid) + && (portid->handle == handle) + && (portid->portnum == portnum)) { + found = 1; + break; + } + } + spin_unlock_irqrestore(&port_list_lock, flags); + + if (found) + return portid; + + return NULL; +} + +int portid_add(const char *busid, + const domid_t domid, + const unsigned int handle, + const int portnum) +{ + struct vusb_port_id *portid; + unsigned long flags; + + portid = kzalloc(sizeof(*portid), GFP_KERNEL); + if (!portid) + return -ENOMEM; + + portid->domid = domid; + portid->handle = handle; + portid->portnum = portnum; + + strncpy(portid->phys_bus, busid, BUS_ID_SIZE); + + spin_lock_irqsave(&port_list_lock, flags); + list_add(&portid->id_list, &port_list); + spin_unlock_irqrestore(&port_list_lock, flags); + + return 0; +} + +int portid_remove(const domid_t domid, + const unsigned int handle, + const int portnum) +{ + struct vusb_port_id *portid, *tmp; + int err = -ENOENT; + unsigned long flags; + + spin_lock_irqsave(&port_list_lock, flags); + list_for_each_entry_safe(portid, tmp, &port_list, id_list) { + if (portid->domid == domid + && portid->handle == handle + && portid->portnum == portnum) { + list_del(&portid->id_list); + kfree(portid); + + err = 0; + } + } + spin_unlock_irqrestore(&port_list_lock, flags); + + return err; +} + +static struct usbstub *usbstub_alloc(struct usb_device *udev, + struct vusb_port_id *portid) { struct usbstub *stub; @@ -83,314 +153,135 @@ printk(KERN_ERR "no memory for alloc usbstub\n"); return NULL; } - - stub->udev = usb_get_dev(interface_to_usbdev(interface)); - stub->interface = interface; - stub->id = stub_id; + kref_init(&stub->kref); + stub->udev = usb_get_dev(udev); + stub->portid = portid; spin_lock_init(&stub->submitting_lock); INIT_LIST_HEAD(&stub->submitting_list); return stub; } -static int usbstub_free(struct usbstub *stub) +static void usbstub_release(struct kref *kref) { - if (!stub) - return -EINVAL; + struct usbstub *stub; + + stub = container_of(kref, struct usbstub, kref); usb_put_dev(stub->udev); - stub->interface = NULL; stub->udev = NULL; - stub->id = NULL; + stub->portid = NULL; kfree(stub); - - return 0; } -static int usbstub_match_one(struct usb_interface *interface, - struct usbstub_id *stub_id) +static inline void usbstub_get(struct usbstub *stub) { - char *udev_busid = interface->dev.parent->bus_id; - - if (!(strncmp(stub_id->bus_id, udev_busid, BUS_ID_SIZE))) { - return 1; - } - - return 0; + kref_get(&stub->kref); } -static struct usbstub_id *usbstub_match(struct usb_interface *interface) +static inline void usbstub_put(struct usbstub *stub) { - struct usb_device *udev = interface_to_usbdev(interface); - struct usbstub_id *stub_id; - unsigned long flags; - int found = 0; + kref_put(&stub->kref, usbstub_release); +} + +static int usbstub_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + char *busid = intf->dev.parent->bus_id; + struct vusb_port_id *portid = NULL; + struct usbstub *stub = NULL; + usbif_t *usbif = NULL; + int retval = -ENODEV; /* hub currently not supported, so skip. */ if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) - return NULL; + goto out; - spin_lock_irqsave(&usbstub_ids_lock, flags); - list_for_each_entry(stub_id, &usbstub_ids, id_list) { - if (usbstub_match_one(interface, stub_id)) { - found = 1; + portid = find_portid_by_busid(busid); + if (!portid) + goto out; + + usbif = find_usbif(portid->domid, portid->handle); + if (!usbif) + goto out; + + switch (udev->speed) { + case USB_SPEED_LOW: + case USB_SPEED_FULL: + break; + case USB_SPEED_HIGH: + if (usbif->usb_ver >= USB_VER_USB20) break; - } + /* fall through */ + default: + goto out; } - spin_unlock_irqrestore(&usbstub_ids_lock, flags); - if (found) - return stub_id; - - return NULL; -} - -static void add_to_grabbed_devices(struct usbstub *stub) -{ - unsigned long flags; - - spin_lock_irqsave(&grabbed_devices_lock, flags); - list_add(&stub->grabbed_list, &grabbed_devices); - spin_unlock_irqrestore(&grabbed_devices_lock, flags); -} - -static void remove_from_grabbed_devices(struct usbstub *stub) -{ - unsigned long flags; - - spin_lock_irqsave(&grabbed_devices_lock, flags); - list_del(&stub->grabbed_list); - spin_unlock_irqrestore(&grabbed_devices_lock, flags); -} - -static int usbstub_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usbstub_id *stub_id = NULL; - struct usbstub *stub = NULL; - usbif_t *usbif = NULL; - int retval = 0; - - if ((stub_id = usbstub_match(interface))) { - stub = usbstub_alloc(interface, stub_id); + stub = find_attached_device(usbif, portid->portnum); + if (!stub) { + /* new connection */ + stub = usbstub_alloc(udev, portid); if (!stub) return -ENOMEM; + usbbk_attach_device(usbif, stub); + usbbk_hotplug_notify(usbif, portid->portnum, udev->speed); + } else { + /* maybe already called and connected by other intf */ + if (strncmp(stub->portid->phys_bus, busid, BUS_ID_SIZE)) + goto out; /* invalid call */ + } - usb_set_intfdata(interface, stub); - add_to_grabbed_devices(stub); - usbif = find_usbif(stub_id->dom_id, stub_id->dev_id); - if (usbif) { - usbbk_plug_device(usbif, stub); - usbback_reconfigure(usbif); - } + usbstub_get(stub); + usb_set_intfdata(intf, stub); + retval = 0; - } else - retval = -ENODEV; - +out: return retval; } -static void usbstub_disconnect(struct usb_interface *interface) +static void usbstub_disconnect(struct usb_interface *intf) { struct usbstub *stub - = (struct usbstub *) usb_get_intfdata(interface); + = (struct usbstub *) usb_get_intfdata(intf); - usb_set_intfdata(interface, NULL); + usb_set_intfdata(intf, NULL); if (!stub) return; if (stub->usbif) { - usbback_reconfigure(stub->usbif); - usbbk_unplug_device(stub->usbif, stub); + usbbk_hotplug_notify(stub->usbif, stub->portid->portnum, 0); + usbbk_detach_device(stub->usbif, stub); } - usbbk_unlink_urbs(stub); - - remove_from_grabbed_devices(stub); - - usbstub_free(stub); - - return; + usbstub_put(stub); } -static inline int str_to_vport(const char *buf, - char *phys_bus, - int *dom_id, - int *dev_id, - int *port) -{ - char *p; - int len; - int err; - - /* no physical bus */ - if (!(p = strchr(buf, ':'))) - return -EINVAL; - - len = p - buf; - - /* bad physical bus */ - if (len + 1 > BUS_ID_SIZE) - return -EINVAL; - - strlcpy(phys_bus, buf, len + 1); - err = sscanf(p + 1, "%d:%d:%d", dom_id, dev_id, port); - if (err == 3) - return 0; - else - return -EINVAL; -} - -static int usbstub_id_add(const char *bus_id, - const int dom_id, - const int dev_id, - const int portnum) -{ - struct usbstub_id *stub_id; - unsigned long flags; - - stub_id = kzalloc(sizeof(*stub_id), GFP_KERNEL); - if (!stub_id) - return -ENOMEM; - - stub_id->dom_id = dom_id; - stub_id->dev_id = dev_id; - stub_id->portnum = portnum; - - strncpy(stub_id->bus_id, bus_id, BUS_ID_SIZE); - - spin_lock_irqsave(&usbstub_ids_lock, flags); - list_add(&stub_id->id_list, &usbstub_ids); - spin_unlock_irqrestore(&usbstub_ids_lock, flags); - - return 0; -} - -static int usbstub_id_remove(const char *phys_bus, - const int dom_id, - const int dev_id, - const int portnum) -{ - struct usbstub_id *stub_id, *tmp; - int err = -ENOENT; - unsigned long flags; - - spin_lock_irqsave(&usbstub_ids_lock, flags); - list_for_each_entry_safe(stub_id, tmp, &usbstub_ids, id_list) { - if (stub_id->dom_id == dom_id - && stub_id->dev_id == dev_id - && stub_id->portnum == portnum) { - list_del(&stub_id->id_list); - kfree(stub_id); - - err = 0; - } - } - spin_unlock_irqrestore(&usbstub_ids_lock, flags); - - return err; -} - -static ssize_t usbstub_vport_add(struct device_driver *driver, - const char *buf, size_t count) -{ - int err = 0; - - char bus_id[BUS_ID_SIZE]; - int dom_id; - int dev_id; - int portnum; - - err = str_to_vport(buf, &bus_id[0], &dom_id, &dev_id, &portnum); - if (err) - goto out; - - err = usbstub_id_add(&bus_id[0], dom_id, dev_id, portnum); - -out: - if (!err) - err = count; - return err; -} - -DRIVER_ATTR(new_vport, S_IWUSR, NULL, usbstub_vport_add); - -static ssize_t usbstub_vport_remove(struct device_driver *driver, - const char *buf, size_t count) -{ - int err = 0; - - char bus_id[BUS_ID_SIZE]; - int dom_id; - int dev_id; - int portnum; - - err = str_to_vport(buf, &bus_id[0], &dom_id, &dev_id, &portnum); - if (err) - goto out; - - err = usbstub_id_remove(&bus_id[0], dom_id, dev_id, portnum); - -out: - if (!err) - err = count; - return err; -} - -DRIVER_ATTR(remove_vport, S_IWUSR, NULL, usbstub_vport_remove); - -static ssize_t usbstub_vport_show(struct device_driver *driver, +static ssize_t usbstub_show_portids(struct device_driver *driver, char *buf) { - struct usbstub_id *stub_id; + struct vusb_port_id *portid; size_t count = 0; unsigned long flags; - spin_lock_irqsave(&usbstub_ids_lock, flags); - list_for_each_entry(stub_id, &usbstub_ids, id_list) { + spin_lock_irqsave(&port_list_lock, flags); + list_for_each_entry(portid, &port_list, id_list) { if (count >= PAGE_SIZE) break; count += scnprintf((char *)buf + count, PAGE_SIZE - count, "%s:%d:%d:%d\n", - &stub_id->bus_id[0], - stub_id->dom_id, - stub_id->dev_id, - stub_id->portnum); + &portid->phys_bus[0], + portid->domid, + portid->handle, + portid->portnum); } - spin_unlock_irqrestore(&usbstub_ids_lock, flags); + spin_unlock_irqrestore(&port_list_lock, flags); return count; } -DRIVER_ATTR(vports, S_IRUSR, usbstub_vport_show, NULL); - -static ssize_t usbstub_devices_show(struct device_driver *driver, - char *buf) -{ - struct usbstub *stub; - size_t count = 0; - unsigned long flags; - - spin_lock_irqsave(&grabbed_devices_lock, flags); - list_for_each_entry(stub, &grabbed_devices, grabbed_list) { - if (count >= PAGE_SIZE) - break; - - count += scnprintf((char *)buf + count, PAGE_SIZE - count, - "%u-%s:%u.%u\n", - stub->udev->bus->busnum, - stub->udev->devpath, - stub->udev->config->desc.bConfigurationValue, - stub->interface->cur_altsetting->desc.bInterfaceNumber); - - } - spin_unlock_irqrestore(&grabbed_devices_lock, flags); - - return count; -} - -DRIVER_ATTR(grabbed_devices, S_IRUSR, usbstub_devices_show, NULL); +DRIVER_ATTR(port_ids, S_IRUSR, usbstub_show_portids, NULL); /* table of devices that matches any usbdevice */ static struct usb_device_id usbstub_table[] = { @@ -404,44 +295,31 @@ .probe = usbstub_probe, .disconnect = usbstub_disconnect, .id_table = usbstub_table, + .no_dynamic_id = 1, }; int __init usbstub_init(void) { - int err; + int err; err = usb_register(&usbback_usb_driver); - if (err < 0) + if (err < 0) { + printk(KERN_ERR "usbback: usb_register failed (error %d)\n", err); goto out; - if (!err) - err = driver_create_file(&usbback_usb_driver.driver, - &driver_attr_new_vport); - if (!err) - err = driver_create_file(&usbback_usb_driver.driver, - &driver_attr_remove_vport); - if (!err) - err = driver_create_file(&usbback_usb_driver.driver, - &driver_attr_vports); - if (!err) - err = driver_create_file(&usbback_usb_driver.driver, - &driver_attr_grabbed_devices); + } + + err = driver_create_file(&usbback_usb_driver.driver, + &driver_attr_port_ids); if (err) - usbstub_exit(); + usb_deregister(&usbback_usb_driver); out: return err; } -void usbstub_exit(void) +void __exit usbstub_exit(void) { driver_remove_file(&usbback_usb_driver.driver, - &driver_attr_new_vport); - driver_remove_file(&usbback_usb_driver.driver, - &driver_attr_remove_vport); - driver_remove_file(&usbback_usb_driver.driver, - &driver_attr_vports); - driver_remove_file(&usbback_usb_driver.driver, - &driver_attr_grabbed_devices); - + &driver_attr_port_ids); usb_deregister(&usbback_usb_driver); } diff -r 4ac3e1d6605c -r 3be939975ad6 drivers/xen/usbback/xenbus.c --- a/drivers/xen/usbback/xenbus.c Tue Sep 29 11:23:06 2009 +0100 +++ b/drivers/xen/usbback/xenbus.c Tue Oct 06 15:18:27 2009 +0900 @@ -43,29 +43,118 @@ * DEALINGS IN THE SOFTWARE. */ -#include <xen/xenbus.h> #include "usbback.h" static int start_xenusbd(usbif_t *usbif) { - int err = 0; - char name[TASK_COMM_LEN]; + int err = 0; + char name[TASK_COMM_LEN]; - snprintf(name, TASK_COMM_LEN, "usbback.%d.%d", usbif->domid, usbif->handle); - usbif->xenusbd = kthread_run(usbbk_schedule, usbif, name); - if (IS_ERR(usbif->xenusbd)) { - err = PTR_ERR(usbif->xenusbd); - usbif->xenusbd = NULL; - xenbus_dev_error(usbif->xbdev, err, "start xenusbd"); - } - return err; + snprintf(name, TASK_COMM_LEN, "usbback.%d.%d", usbif->domid, + usbif->handle); + usbif->xenusbd = kthread_run(usbbk_schedule, usbif, name); + if (IS_ERR(usbif->xenusbd)) { + err = PTR_ERR(usbif->xenusbd); + usbif->xenusbd = NULL; + xenbus_dev_error(usbif->xbdev, err, "start xenusbd"); + } + + return err; +} + +static void backend_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + struct xenbus_transaction xbt; + int err; + int i; + char node[8]; + char *busid; + struct vusb_port_id *portid = NULL; + + usbif_t *usbif = container_of(watch, usbif_t, backend_watch); + struct xenbus_device *dev = usbif->xbdev; + +again: + err = xenbus_transaction_start(&xbt); + if (err) { + xenbus_dev_fatal(dev, err, "starting transaction"); + return; + } + + for (i = 1; i <= usbif->num_ports; i++) { + sprintf(node, "port/%d", i); + busid = xenbus_read(xbt, dev->nodename, node, NULL); + if (IS_ERR(busid)) { + err = PTR_ERR(busid); + xenbus_dev_fatal(dev, err, "reading port/%d", i); + goto abort; + } + + /* + * remove portid, if the port is not connected, + */ + if (strlen(busid) == 0) { + portid = find_portid(usbif->domid, usbif->handle, i); + if (portid) { + if (portid->is_connected) + xenbus_dev_fatal(dev, err, + "can't remove port/%d, unbind first", i); + else + portid_remove(usbif->domid, usbif->handle, i); + } + continue; /* never configured, ignore */ + } + + /* + * add portid, + * if the port is not configured and not used from other usbif. + */ + portid = find_portid(usbif->domid, usbif->handle, i); + if (portid) { + if ((strncmp(portid->phys_bus, busid, BUS_ID_SIZE))) + xenbus_dev_fatal(dev, err, + "can't add port/%d, remove first", i); + else + continue; /* already configured, ignore */ + } else { + if (find_portid_by_busid(busid)) + xenbus_dev_fatal(dev, err, + "can't add port/%d, busid already used", i); + else + portid_add(busid, usbif->domid, usbif->handle, i); + } + } + + err = xenbus_transaction_end(xbt, 0); + if (err == -EAGAIN) + goto again; + if (err) + xenbus_dev_fatal(dev, err, "completing transaction"); + + return; + +abort: + xenbus_transaction_end(xbt, 1); + + return; } static int usbback_remove(struct xenbus_device *dev) { usbif_t *usbif = dev->dev.driver_data; + int i; + + if (usbif->backend_watch.node) { + unregister_xenbus_watch(&usbif->backend_watch); + kfree(usbif->backend_watch.node); + usbif->backend_watch.node = NULL; + } if (usbif) { + /* remove all ports */ + for (i = 1; i <= usbif->num_ports; i++) + portid_remove(usbif->domid, usbif->handle, i); usbif_disconnect(usbif); usbif_free(usbif);; } @@ -79,12 +168,14 @@ { usbif_t *usbif; unsigned int handle; + int num_ports; + int usb_ver; int err; if (usb_disabled()) return -ENODEV; - handle = simple_strtoul(strrchr(dev->otherend,'/')+1, NULL, 0); + handle = simple_strtoul(strrchr(dev->otherend, '/') + 1, NULL, 0); usbif = usbif_alloc(dev->otherend_id, handle); if (!usbif) { xenbus_dev_fatal(dev, -ENOMEM, "allocating backend interface"); @@ -93,6 +184,34 @@ usbif->xbdev = dev; dev->dev.driver_data = usbif; + err = xenbus_scanf(XBT_NIL, dev->nodename, + "num-ports", "%d", &num_ports); + if (err != 1) { + xenbus_dev_fatal(dev, err, "reading num-ports"); + goto fail; + } + if (num_ports < 1 || num_ports > USB_MAXCHILDREN) { + xenbus_dev_fatal(dev, err, "invalid num-ports"); + goto fail; + } + usbif->num_ports = num_ports; + + err = xenbus_scanf(XBT_NIL, dev->nodename, + "usb-ver", "%d", &usb_ver); + if (err != 1) { + xenbus_dev_fatal(dev, err, "reading usb-ver"); + goto fail; + } + switch (usb_ver) { + case USB_VER_USB11: + case USB_VER_USB20: + usbif->usb_ver = usb_ver; + break; + default: + xenbus_dev_fatal(dev, err, "invalid usb-ver"); + goto fail; + } + err = xenbus_switch_state(dev, XenbusStateInitWait); if (err) goto fail; @@ -104,15 +223,17 @@ return err; } -static int connect_ring(usbif_t *usbif) +static int connect_rings(usbif_t *usbif) { struct xenbus_device *dev = usbif->xbdev; - unsigned long ring_ref; + unsigned long urb_ring_ref; + unsigned long conn_ring_ref; unsigned int evtchn; int err; err = xenbus_gather(XBT_NIL, dev->otherend, - "ring-ref", "%lu", &ring_ref, + "urb-ring-ref", "%lu", &urb_ring_ref, + "conn-ring-ref", "%lu", &conn_ring_ref, "event-channel", "%u", &evtchn, NULL); if (err) { xenbus_dev_fatal(dev, err, @@ -121,81 +242,32 @@ return err; } - printk("usbback: ring-ref %ld, event-channel %d\n", - ring_ref, evtchn); + printk("usbback: urb-ring-ref %ld, conn-ring-ref %ld, event-channel %d\n", + urb_ring_ref, conn_ring_ref, evtchn); - err = usbif_map(usbif, ring_ref, evtchn); + err = usbif_map(usbif, urb_ring_ref, conn_ring_ref, evtchn); if (err) { - xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u", - ring_ref, evtchn); + xenbus_dev_fatal(dev, err, + "mapping urb-ring-ref %lu conn-ring-ref %lu port %u", + urb_ring_ref, conn_ring_ref, evtchn); return err; } return 0; } -void usbback_do_hotplug(usbif_t *usbif) -{ - struct xenbus_transaction xbt; - struct xenbus_device *dev = usbif->xbdev; - struct usbstub *stub = NULL; - int err; - char port_str[8]; - int i; - int num_ports; - int state; - -again: - err = xenbus_transaction_start(&xbt); - if (err) { - xenbus_dev_fatal(dev, err, "starting transaction"); - return; - } - - err = xenbus_scanf(xbt, dev->nodename, - "num-ports", "%d", &num_ports); - - for (i = 1; i <= num_ports; i++) { - stub = find_attached_device(usbif, i); - if (stub) - state = stub->udev->speed; - else - state = 0; - sprintf(port_str, "port-%d", i); - err = xenbus_printf(xbt, dev->nodename, port_str, "%d", state); - if (err) { - xenbus_dev_fatal(dev, err, "writing port-%d state", i); - goto abort; - } - } - - err = xenbus_transaction_end(xbt, 0); - if (err == -EAGAIN) - goto again; - if (err) - xenbus_dev_fatal(dev, err, "completing transaction"); - - return; - -abort: - xenbus_transaction_end(xbt, 1); -} - -void usbback_reconfigure(usbif_t *usbif) -{ - struct xenbus_device *dev = usbif->xbdev; - - if (dev->state == XenbusStateConnected) - xenbus_switch_state(dev, XenbusStateReconfiguring); -} - -void frontend_changed(struct xenbus_device *dev, +static void frontend_changed(struct xenbus_device *dev, enum xenbus_state frontend_state) { usbif_t *usbif = dev->dev.driver_data; int err; switch (frontend_state) { + case XenbusStateInitialised: + case XenbusStateReconfiguring: + case XenbusStateReconfigured: + break; + case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { printk("%s: %s: prepare for reconnect\n", @@ -204,17 +276,18 @@ } break; - case XenbusStateInitialised: - err = connect_ring(usbif); + case XenbusStateConnected: + if (dev->state == XenbusStateConnected) + break; + err = connect_rings(usbif); if (err) break; - start_xenusbd(usbif); - usbback_do_hotplug(usbif); - xenbus_switch_state(dev, XenbusStateConnected); - break; - - case XenbusStateConnected: - if (dev->state == XenbusStateConnected) + err = start_xenusbd(usbif); + if (err) + break; + err = xenbus_watch_path2(dev, dev->nodename, "port", + &usbif->backend_watch, backend_changed); + if (err) break; xenbus_switch_state(dev, XenbusStateConnected); break; @@ -226,13 +299,9 @@ case XenbusStateClosed: xenbus_switch_state(dev, XenbusStateClosed); - break; - - case XenbusStateReconfiguring: - usbback_do_hotplug(usbif); - xenbus_switch_state(dev, XenbusStateReconfigured); - break; - + if (xenbus_dev_is_online(dev)) + break; + /* fall through if not online */ case XenbusStateUnknown: device_unregister(&dev->dev); break; _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |