?? u132-hcd.c
字號:
static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring, unsigned int delta){ kref_get(&u132->kref); u132_ring_requeue_work(u132, ring, delta); return;}static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring){ if (cancel_delayed_work(&ring->scheduler)) { kref_put(&u132->kref, u132_hcd_delete); }}static void u132_endp_delete(struct kref *kref){ struct u132_endp *endp = kref_to_u132_endp(kref); struct u132 *u132 = endp->u132; u8 usb_addr = endp->usb_addr; u8 usb_endp = endp->usb_endp; u8 address = u132->addr[usb_addr].address; struct u132_udev *udev = &u132->udev[address]; u8 endp_number = endp->endp_number; struct usb_host_endpoint *hep = endp->hep; struct u132_ring *ring = endp->ring; struct list_head *head = &endp->endp_ring; ring->length -= 1; if (endp == ring->curr_endp) { if (list_empty(head)) { ring->curr_endp = NULL; list_del(head); } else { struct u132_endp *next_endp = list_entry(head->next, struct u132_endp, endp_ring); ring->curr_endp = next_endp; list_del(head); }} else list_del(head); if (endp->input) { udev->endp_number_in[usb_endp] = 0; u132_udev_put_kref(u132, udev); } if (endp->output) { udev->endp_number_out[usb_endp] = 0; u132_udev_put_kref(u132, udev); } u132->endp[endp_number - 1] = NULL; hep->hcpriv = NULL; kfree(endp); u132_u132_put_kref(u132);}static inline void u132_endp_put_kref(struct u132 *u132, struct u132_endp *endp){ kref_put(&endp->kref, u132_endp_delete);}static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp){ kref_get(&endp->kref);}static inline void u132_endp_init_kref(struct u132 *u132, struct u132_endp *endp){ kref_init(&endp->kref); kref_get(&u132->kref);}static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp, unsigned int delta){ if (queue_delayed_work(workqueue, &endp->scheduler, delta)) kref_get(&endp->kref);}static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp){ if (cancel_delayed_work(&endp->scheduler)) kref_put(&endp->kref, u132_endp_delete);}static inline void u132_monitor_put_kref(struct u132 *u132){ kref_put(&u132->kref, u132_hcd_delete);}static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta){ if (queue_delayed_work(workqueue, &u132->monitor, delta)) kref_get(&u132->kref);}static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta){ if (!queue_delayed_work(workqueue, &u132->monitor, delta)) kref_put(&u132->kref, u132_hcd_delete);}static void u132_monitor_cancel_work(struct u132 *u132){ if (cancel_delayed_work(&u132->monitor)) kref_put(&u132->kref, u132_hcd_delete);}static int read_roothub_info(struct u132 *u132){ u32 revision; int retval; retval = u132_read_pcimem(u132, revision, &revision); if (retval) { dev_err(&u132->platform_dev->dev, "error %d accessing device co" "ntrol\n", retval); return retval; } else if ((revision & 0xFF) == 0x10) { } else if ((revision & 0xFF) == 0x11) { } else { dev_err(&u132->platform_dev->dev, "device revision is not valid" " %08X\n", revision); return -ENODEV; } retval = u132_read_pcimem(u132, control, &u132->hc_control); if (retval) { dev_err(&u132->platform_dev->dev, "error %d accessing device co" "ntrol\n", retval); return retval; } retval = u132_read_pcimem(u132, roothub.status, &u132->hc_roothub_status); if (retval) { dev_err(&u132->platform_dev->dev, "error %d accessing device re" "g roothub.status\n", retval); return retval; } retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a); if (retval) { dev_err(&u132->platform_dev->dev, "error %d accessing device re" "g roothub.a\n", retval); return retval; } { int I = u132->num_ports; int i = 0; while (I-- > 0) { retval = u132_read_pcimem(u132, roothub.portstatus[i], &u132->hc_roothub_portstatus[i]); if (retval) { dev_err(&u132->platform_dev->dev, "error %d acc" "essing device roothub.portstatus[%d]\n" , retval, i); return retval; } else i += 1; } } return 0;}static void u132_hcd_monitor_work(struct work_struct *work){ struct u132 *u132 = container_of(work, struct u132, monitor.work); if (u132->going > 1) { dev_err(&u132->platform_dev->dev, "device has been removed %d\n" , u132->going); u132_monitor_put_kref(u132); return; } else if (u132->going > 0) { dev_err(&u132->platform_dev->dev, "device is being removed\n"); u132_monitor_put_kref(u132); return; } else { int retval; down(&u132->sw_lock); retval = read_roothub_info(u132); if (retval) { struct usb_hcd *hcd = u132_to_hcd(u132); u132_disable(u132); u132->going = 1; up(&u132->sw_lock); usb_hc_died(hcd); ftdi_elan_gone_away(u132->platform_dev); u132_monitor_put_kref(u132); return; } else { u132_monitor_requeue_work(u132, 500); up(&u132->sw_lock); return; } }}static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp, struct urb *urb, int status){ struct u132_ring *ring; unsigned long irqs; struct usb_hcd *hcd = u132_to_hcd(u132); urb->error_count = 0; urb->status = status; urb->hcpriv = NULL; spin_lock_irqsave(&endp->queue_lock.slock, irqs); endp->queue_next += 1; if (ENDP_QUEUE_SIZE > --endp->queue_size) { endp->active = 0; spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); } else { struct list_head *next = endp->urb_more.next; struct u132_urbq *urbq = list_entry(next, struct u132_urbq, urb_more); list_del(next); endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urbq->urb; endp->active = 0; spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); kfree(urbq); } down(&u132->scheduler_lock); ring = endp->ring; ring->in_use = 0; u132_ring_cancel_work(u132, ring); u132_ring_queue_work(u132, ring, 0); up(&u132->scheduler_lock); u132_endp_put_kref(u132, endp); usb_hcd_giveback_urb(hcd, urb); return;}static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp, struct urb *urb, int status){ u132_endp_put_kref(u132, endp);}static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp, struct urb *urb, int status){ unsigned long irqs; struct usb_hcd *hcd = u132_to_hcd(u132); urb->error_count = 0; urb->status = status; urb->hcpriv = NULL; spin_lock_irqsave(&endp->queue_lock.slock, irqs); endp->queue_next += 1; if (ENDP_QUEUE_SIZE > --endp->queue_size) { endp->active = 0; spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); } else { struct list_head *next = endp->urb_more.next; struct u132_urbq *urbq = list_entry(next, struct u132_urbq, urb_more); list_del(next); endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urbq->urb; endp->active = 0; spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); kfree(urbq); } usb_hcd_giveback_urb(hcd, urb); return;}static inline int edset_input(struct u132 *u132, struct u132_ring *ring, struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits, void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, int toggle_bits, int error_count, int condition_code, int repeat_number, int halted, int skipped, int actual, int non_null)){ return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp, urb, address, endp->usb_endp, toggle_bits, callback);}static inline int edset_setup(struct u132 *u132, struct u132_ring *ring, struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits, void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, int toggle_bits, int error_count, int condition_code, int repeat_number, int halted, int skipped, int actual, int non_null)){ return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp, urb, address, endp->usb_endp, toggle_bits, callback);}static inline int edset_single(struct u132 *u132, struct u132_ring *ring, struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits, void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, int toggle_bits, int error_count, int condition_code, int repeat_number, int halted, int skipped, int actual, int non_null)){ return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number, endp, urb, address, endp->usb_endp, toggle_bits, callback);}static inline int edset_output(struct u132 *u132, struct u132_ring *ring, struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits, void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, int toggle_bits, int error_count, int condition_code, int repeat_number, int halted, int skipped, int actual, int non_null)){ return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number, endp, urb, address, endp->usb_endp, toggle_bits, callback);}/** must not LOCK sw_lock**/static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf, int len, int toggle_bits, int error_count, int condition_code, int repeat_number, int halted, int skipped, int actual, int non_null){ struct u132_endp *endp = data; struct u132 *u132 = endp->u132; u8 address = u132->addr[endp->usb_addr].address; struct u132_udev *udev = &u132->udev[address]; down(&u132->scheduler_lock); if (u132->going > 1) { dev_err(&u132->platform_dev->dev, "device has been removed %d\n" , u132->going); up(&u132->scheduler_lock);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -