Lines Matching +full:lock +full:- +full:status

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * xen-hcd.c
25 /* Private per-URB data */
31 int status; member
35 /* virtual roothub port status */
37 __u32 status; member
43 /* status of attached device */
46 enum usb_device_state status; member
64 spinlock_t lock; member
102 return (struct xenhcd_info *)hcd->hcd_priv; in xenhcd_hcd_to_info()
112 info->error = true; in xenhcd_set_error()
114 pr_alert("xen-hcd: protocol error: %s!\n", msg); in xenhcd_set_error()
120 clear_bit(action, &info->actions); in xenhcd_timer_action_done()
126 if (timer_pending(&info->watchdog) && in xenhcd_timer_action()
127 test_bit(TIMER_SCAN_PENDING_URBS, &info->actions)) in xenhcd_timer_action()
130 if (!test_and_set_bit(action, &info->actions)) { in xenhcd_timer_action()
141 mod_timer(&info->watchdog, t + jiffies); in xenhcd_timer_action()
146 * set virtual port connection status
152 port = portnum - 1; in xenhcd_set_connect_state()
153 if (info->ports[port].status & USB_PORT_STAT_POWER) { in xenhcd_set_connect_state()
154 switch (info->devices[port].speed) { in xenhcd_set_connect_state()
156 info->ports[port].status &= in xenhcd_set_connect_state()
164 info->ports[port].status |= USB_PORT_STAT_CONNECTION; in xenhcd_set_connect_state()
165 info->ports[port].status |= USB_PORT_STAT_LOW_SPEED; in xenhcd_set_connect_state()
168 info->ports[port].status |= USB_PORT_STAT_CONNECTION; in xenhcd_set_connect_state()
171 info->ports[port].status |= USB_PORT_STAT_CONNECTION; in xenhcd_set_connect_state()
172 info->ports[port].status |= USB_PORT_STAT_HIGH_SPEED; in xenhcd_set_connect_state()
177 info->ports[port].status |= (USB_PORT_STAT_C_CONNECTION << 16); in xenhcd_set_connect_state()
182 * set virtual device connection status
189 if (portnum < 1 || portnum > info->rh_numports) in xenhcd_rhport_connect()
190 return -EINVAL; /* invalid port number */ in xenhcd_rhport_connect()
192 port = portnum - 1; in xenhcd_rhport_connect()
193 if (info->devices[port].speed != speed) { in xenhcd_rhport_connect()
196 info->devices[port].status = USB_STATE_NOTATTACHED; in xenhcd_rhport_connect()
201 info->devices[port].status = USB_STATE_ATTACHED; in xenhcd_rhport_connect()
204 return -EINVAL; in xenhcd_rhport_connect()
206 info->devices[port].speed = speed; in xenhcd_rhport_connect()
207 info->ports[port].c_connection = true; in xenhcd_rhport_connect()
222 port = portnum - 1; in xenhcd_rhport_suspend()
223 info->ports[port].status |= USB_PORT_STAT_SUSPEND; in xenhcd_rhport_suspend()
224 info->devices[port].status = USB_STATE_SUSPENDED; in xenhcd_rhport_suspend()
234 port = portnum - 1; in xenhcd_rhport_resume()
235 if (info->ports[port].status & USB_PORT_STAT_SUSPEND) { in xenhcd_rhport_resume()
236 info->ports[port].resuming = true; in xenhcd_rhport_resume()
237 info->ports[port].timeout = jiffies + msecs_to_jiffies(20); in xenhcd_rhport_resume()
248 port = portnum - 1; in xenhcd_rhport_power_on()
249 if ((info->ports[port].status & USB_PORT_STAT_POWER) == 0) { in xenhcd_rhport_power_on()
250 info->ports[port].status |= USB_PORT_STAT_POWER; in xenhcd_rhport_power_on()
251 if (info->devices[port].status != USB_STATE_NOTATTACHED) in xenhcd_rhport_power_on()
252 info->devices[port].status = USB_STATE_POWERED; in xenhcd_rhport_power_on()
253 if (info->ports[port].c_connection) in xenhcd_rhport_power_on()
260 * SetConfiguration(non-zero)
262 * Over-current
268 port = portnum - 1; in xenhcd_rhport_power_off()
269 if (info->ports[port].status & USB_PORT_STAT_POWER) { in xenhcd_rhport_power_off()
270 info->ports[port].status = 0; in xenhcd_rhport_power_off()
271 if (info->devices[port].status != USB_STATE_NOTATTACHED) in xenhcd_rhport_power_off()
272 info->devices[port].status = USB_STATE_ATTACHED; in xenhcd_rhport_power_off()
283 port = portnum - 1; in xenhcd_rhport_disable()
284 info->ports[port].status &= ~USB_PORT_STAT_ENABLE; in xenhcd_rhport_disable()
285 info->ports[port].status &= ~USB_PORT_STAT_SUSPEND; in xenhcd_rhport_disable()
286 info->ports[port].resuming = false; in xenhcd_rhport_disable()
287 if (info->devices[port].status != USB_STATE_NOTATTACHED) in xenhcd_rhport_disable()
288 info->devices[port].status = USB_STATE_POWERED; in xenhcd_rhport_disable()
298 port = portnum - 1; in xenhcd_rhport_reset()
299 info->ports[port].status &= ~(USB_PORT_STAT_ENABLE | in xenhcd_rhport_reset()
302 info->ports[port].status |= USB_PORT_STAT_RESET; in xenhcd_rhport_reset()
304 if (info->devices[port].status != USB_STATE_NOTATTACHED) in xenhcd_rhport_reset()
305 info->devices[port].status = USB_STATE_ATTACHED; in xenhcd_rhport_reset()
308 info->ports[port].timeout = jiffies + msecs_to_jiffies(10); in xenhcd_rhport_reset()
318 ports = info->rh_numports; in xenhcd_bus_suspend()
320 spin_lock_irq(&info->lock); in xenhcd_bus_suspend()
321 if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { in xenhcd_bus_suspend()
322 ret = -ESHUTDOWN; in xenhcd_bus_suspend()
328 spin_unlock_irq(&info->lock); in xenhcd_bus_suspend()
330 timer_delete_sync(&info->watchdog); in xenhcd_bus_suspend()
341 ports = info->rh_numports; in xenhcd_bus_resume()
343 spin_lock_irq(&info->lock); in xenhcd_bus_resume()
344 if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { in xenhcd_bus_resume()
345 ret = -ESHUTDOWN; in xenhcd_bus_resume()
351 spin_unlock_irq(&info->lock); in xenhcd_bus_resume()
361 int ports = info->rh_numports; in xenhcd_hub_descriptor()
363 desc->bDescriptorType = 0x29; in xenhcd_hub_descriptor()
364 desc->bPwrOn2PwrGood = 10; /* EHCI says 20ms max */ in xenhcd_hub_descriptor()
365 desc->bHubContrCurrent = 0; in xenhcd_hub_descriptor()
366 desc->bNbrPorts = ports; in xenhcd_hub_descriptor()
370 desc->bDescLength = 7 + 2 * temp; in xenhcd_hub_descriptor()
373 memset(&desc->u.hs.DeviceRemovable[0], 0, temp); in xenhcd_hub_descriptor()
374 memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); in xenhcd_hub_descriptor()
376 /* per-port over current reporting and no power switching */ in xenhcd_hub_descriptor()
378 desc->wHubCharacteristics = cpu_to_le16(temp); in xenhcd_hub_descriptor()
381 /* port status change mask for hub_status_data */
389 * See USB 2.0 Spec, 11.12.4 Hub and Port Status Change Bitmap.
390 * If port status changed, writes the bitmap to buf and return
403 /* initialize the status to no-changes */ in xenhcd_hub_status_data()
404 ports = info->rh_numports; in xenhcd_hub_status_data()
408 spin_lock_irqsave(&info->lock, flags); in xenhcd_hub_status_data()
411 /* check status for each port */ in xenhcd_hub_status_data()
412 if (info->ports[i].status & PORT_C_MASK) { in xenhcd_hub_status_data()
418 if ((hcd->state == HC_STATE_SUSPENDED) && (changed == 1)) in xenhcd_hub_status_data()
421 spin_unlock_irqrestore(&info->lock, flags); in xenhcd_hub_status_data()
430 int ports = info->rh_numports; in xenhcd_hub_control()
436 spin_lock_irqsave(&info->lock, flags); in xenhcd_hub_control()
456 info->ports[wIndex - 1].c_connection = false; in xenhcd_hub_control()
459 info->ports[wIndex - 1].status &= ~(1 << wValue); in xenhcd_hub_control()
467 /* always local power supply good and no over-current exists. */ in xenhcd_hub_control()
474 wIndex--; in xenhcd_hub_control()
477 if (info->ports[wIndex].resuming && in xenhcd_hub_control()
478 time_after_eq(jiffies, info->ports[wIndex].timeout)) { in xenhcd_hub_control()
479 info->ports[wIndex].status |= in xenhcd_hub_control()
481 info->ports[wIndex].status &= ~USB_PORT_STAT_SUSPEND; in xenhcd_hub_control()
485 if ((info->ports[wIndex].status & USB_PORT_STAT_RESET) != 0 && in xenhcd_hub_control()
486 time_after_eq(jiffies, info->ports[wIndex].timeout)) { in xenhcd_hub_control()
487 info->ports[wIndex].status |= in xenhcd_hub_control()
489 info->ports[wIndex].status &= ~USB_PORT_STAT_RESET; in xenhcd_hub_control()
491 if (info->devices[wIndex].status != in xenhcd_hub_control()
493 info->ports[wIndex].status |= in xenhcd_hub_control()
495 info->devices[wIndex].status = in xenhcd_hub_control()
499 switch (info->devices[wIndex].speed) { in xenhcd_hub_control()
501 info->ports[wIndex].status |= in xenhcd_hub_control()
505 info->ports[wIndex].status |= in xenhcd_hub_control()
513 *(__le32 *)buf = cpu_to_le32(info->ports[wIndex].status); in xenhcd_hub_control()
530 if (info->ports[wIndex-1].status & USB_PORT_STAT_POWER) in xenhcd_hub_control()
531 info->ports[wIndex-1].status |= (1 << wValue); in xenhcd_hub_control()
539 ret = -EPIPE; in xenhcd_hub_control()
541 spin_unlock_irqrestore(&info->lock, flags); in xenhcd_hub_control()
543 /* check status for each port */ in xenhcd_hub_control()
545 if (info->ports[i].status & PORT_C_MASK) in xenhcd_hub_control()
556 urbp->urb->hcpriv = NULL; in xenhcd_free_urb_priv()
564 free = info->shadow_free; in xenhcd_get_id_from_freelist()
565 info->shadow_free = info->shadow[free].req.id; in xenhcd_get_id_from_freelist()
566 info->shadow[free].req.id = 0x0fff; /* debug */ in xenhcd_get_id_from_freelist()
573 info->shadow[id].req.id = info->shadow_free; in xenhcd_add_id_to_freelist()
574 info->shadow[id].urb = NULL; in xenhcd_add_id_to_freelist()
575 info->shadow_free = id; in xenhcd_add_id_to_freelist()
582 return PFN_UP(vaddr + length) - PFN_DOWN(vaddr); in xenhcd_count_pages()
599 bytes = PAGE_SIZE - offset; in xenhcd_gnttab_map()
604 gnttab_grant_foreign_access_ref(ref, info->xbdev->otherend_id, in xenhcd_gnttab_map()
611 len -= bytes; in xenhcd_gnttab_map()
650 if (urb->transfer_buffer_length) { in xenhcd_map_urb_for_request()
651 nr_buff_pages = xenhcd_count_pages(urb->transfer_buffer, in xenhcd_map_urb_for_request()
652 urb->transfer_buffer_length); in xenhcd_map_urb_for_request()
654 if (usb_pipeisoc(urb->pipe)) in xenhcd_map_urb_for_request()
656 &urb->iso_frame_desc[0], in xenhcd_map_urb_for_request()
658 urb->number_of_packets); in xenhcd_map_urb_for_request()
663 return -E2BIG; in xenhcd_map_urb_for_request()
668 return -ENOMEM; in xenhcd_map_urb_for_request()
671 xenhcd_gnttab_map(info, urb->transfer_buffer, in xenhcd_map_urb_for_request()
672 urb->transfer_buffer_length, &gref_head, in xenhcd_map_urb_for_request()
673 &req->seg[0], nr_buff_pages, in xenhcd_map_urb_for_request()
674 usb_pipein(urb->pipe) ? 0 : GTF_readonly); in xenhcd_map_urb_for_request()
677 req->pipe = xenhcd_pipe_urb_to_xenusb(urb->pipe, urb->dev->portnum); in xenhcd_map_urb_for_request()
678 req->transfer_flags = 0; in xenhcd_map_urb_for_request()
679 if (urb->transfer_flags & URB_SHORT_NOT_OK) in xenhcd_map_urb_for_request()
680 req->transfer_flags |= XENUSB_SHORT_NOT_OK; in xenhcd_map_urb_for_request()
681 req->buffer_length = urb->transfer_buffer_length; in xenhcd_map_urb_for_request()
682 req->nr_buffer_segs = nr_buff_pages; in xenhcd_map_urb_for_request()
684 switch (usb_pipetype(urb->pipe)) { in xenhcd_map_urb_for_request()
686 req->u.isoc.interval = urb->interval; in xenhcd_map_urb_for_request()
687 req->u.isoc.start_frame = urb->start_frame; in xenhcd_map_urb_for_request()
688 req->u.isoc.number_of_packets = urb->number_of_packets; in xenhcd_map_urb_for_request()
689 req->u.isoc.nr_frame_desc_segs = nr_isodesc_pages; in xenhcd_map_urb_for_request()
691 xenhcd_gnttab_map(info, &urb->iso_frame_desc[0], in xenhcd_map_urb_for_request()
693 urb->number_of_packets, in xenhcd_map_urb_for_request()
694 &gref_head, &req->seg[nr_buff_pages], in xenhcd_map_urb_for_request()
698 req->u.intr.interval = urb->interval; in xenhcd_map_urb_for_request()
701 if (urb->setup_packet) in xenhcd_map_urb_for_request()
702 memcpy(req->u.ctrl, urb->setup_packet, 8); in xenhcd_map_urb_for_request()
718 struct usb_shadow *shadow = info->shadow + id; in xenhcd_gnttab_done()
722 if (!shadow->in_flight) { in xenhcd_gnttab_done()
726 shadow->in_flight = false; in xenhcd_gnttab_done()
728 nr_segs = shadow->req.nr_buffer_segs; in xenhcd_gnttab_done()
730 if (xenusb_pipeisoc(shadow->req.pipe)) in xenhcd_gnttab_done()
731 nr_segs += shadow->req.u.isoc.nr_frame_desc_segs; in xenhcd_gnttab_done()
734 if (!gnttab_try_end_foreign_access(shadow->req.seg[i].gref)) in xenhcd_gnttab_done()
738 shadow->req.nr_buffer_segs = 0; in xenhcd_gnttab_done()
739 shadow->req.u.isoc.nr_frame_desc_segs = 0; in xenhcd_gnttab_done()
742 static int xenhcd_translate_status(int status) in xenhcd_translate_status() argument
744 switch (status) { in xenhcd_translate_status()
748 return -ENODEV; in xenhcd_translate_status()
750 return -EINVAL; in xenhcd_translate_status()
752 return -EPIPE; in xenhcd_translate_status()
754 return -EPROTO; in xenhcd_translate_status()
756 return -EOVERFLOW; in xenhcd_translate_status()
758 return -ESHUTDOWN; in xenhcd_translate_status()
763 int status) in xenhcd_giveback_urb() argument
765 struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; in xenhcd_giveback_urb()
766 int priv_status = urbp->status; in xenhcd_giveback_urb()
768 list_del_init(&urbp->list); in xenhcd_giveback_urb()
771 if (urb->status == -EINPROGRESS) in xenhcd_giveback_urb()
772 urb->status = xenhcd_translate_status(status); in xenhcd_giveback_urb()
774 spin_unlock(&info->lock); in xenhcd_giveback_urb()
776 priv_status <= 0 ? priv_status : urb->status); in xenhcd_giveback_urb()
777 spin_lock(&info->lock); in xenhcd_giveback_urb()
783 struct urb *urb = urbp->urb; in xenhcd_do_request()
789 req = &info->shadow[id].req; in xenhcd_do_request()
790 req->id = id; in xenhcd_do_request()
792 if (unlikely(urbp->unlinked)) { in xenhcd_do_request()
793 req->u.unlink.unlink_id = urbp->req_id; in xenhcd_do_request()
794 req->pipe = xenusb_setunlink_pipe(xenhcd_pipe_urb_to_xenusb( in xenhcd_do_request()
795 urb->pipe, urb->dev->portnum)); in xenhcd_do_request()
796 urbp->unlink_req_id = id; in xenhcd_do_request()
803 urbp->req_id = id; in xenhcd_do_request()
806 req = RING_GET_REQUEST(&info->urb_ring, info->urb_ring.req_prod_pvt); in xenhcd_do_request()
807 *req = info->shadow[id].req; in xenhcd_do_request()
809 info->urb_ring.req_prod_pvt++; in xenhcd_do_request()
810 info->shadow[id].urb = urb; in xenhcd_do_request()
811 info->shadow[id].in_flight = true; in xenhcd_do_request()
813 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->urb_ring, notify); in xenhcd_do_request()
815 notify_remote_via_irq(info->irq); in xenhcd_do_request()
824 while (!list_empty(&info->pending_submit_list)) { in xenhcd_kick_pending_urbs()
825 if (RING_FULL(&info->urb_ring)) { in xenhcd_kick_pending_urbs()
830 urbp = list_entry(info->pending_submit_list.next, in xenhcd_kick_pending_urbs()
833 list_move_tail(&urbp->list, &info->in_progress_list); in xenhcd_kick_pending_urbs()
835 xenhcd_giveback_urb(info, urbp->urb, -ESHUTDOWN); in xenhcd_kick_pending_urbs()
841 * caller must lock info->lock
848 list_for_each_entry_safe(urbp, tmp, &info->in_progress_list, list) { in xenhcd_cancel_all_enqueued_urbs()
849 req_id = urbp->req_id; in xenhcd_cancel_all_enqueued_urbs()
850 if (!urbp->unlinked) { in xenhcd_cancel_all_enqueued_urbs()
852 if (info->error) in xenhcd_cancel_all_enqueued_urbs()
854 if (urbp->urb->status == -EINPROGRESS) in xenhcd_cancel_all_enqueued_urbs()
856 xenhcd_giveback_urb(info, urbp->urb, in xenhcd_cancel_all_enqueued_urbs()
857 -ESHUTDOWN); in xenhcd_cancel_all_enqueued_urbs()
859 xenhcd_giveback_urb(info, urbp->urb, in xenhcd_cancel_all_enqueued_urbs()
860 urbp->urb->status); in xenhcd_cancel_all_enqueued_urbs()
862 info->shadow[req_id].urb = NULL; in xenhcd_cancel_all_enqueued_urbs()
865 list_for_each_entry_safe(urbp, tmp, &info->pending_submit_list, list) in xenhcd_cancel_all_enqueued_urbs()
866 xenhcd_giveback_urb(info, urbp->urb, -ESHUTDOWN); in xenhcd_cancel_all_enqueued_urbs()
870 * caller must lock info->lock
876 list_for_each_entry_safe(urbp, tmp, &info->giveback_waiting_list, list) in xenhcd_giveback_unlinked_urbs()
877 xenhcd_giveback_urb(info, urbp->urb, urbp->urb->status); in xenhcd_giveback_unlinked_urbs()
884 if (RING_FULL(&info->urb_ring)) { in xenhcd_submit_urb()
885 list_add_tail(&urbp->list, &info->pending_submit_list); in xenhcd_submit_urb()
890 if (!list_empty(&info->pending_submit_list)) { in xenhcd_submit_urb()
891 list_add_tail(&urbp->list, &info->pending_submit_list); in xenhcd_submit_urb()
898 list_add_tail(&urbp->list, &info->in_progress_list); in xenhcd_submit_urb()
908 if (urbp->unlinked) in xenhcd_unlink_urb()
909 return -EBUSY; in xenhcd_unlink_urb()
911 urbp->unlinked = true; in xenhcd_unlink_urb()
914 if (urbp->req_id == ~0) { in xenhcd_unlink_urb()
915 list_move_tail(&urbp->list, &info->giveback_waiting_list); in xenhcd_unlink_urb()
921 if (RING_FULL(&info->urb_ring)) { in xenhcd_unlink_urb()
922 list_move_tail(&urbp->list, &info->pending_unlink_list); in xenhcd_unlink_urb()
927 if (!list_empty(&info->pending_unlink_list)) { in xenhcd_unlink_urb()
928 list_move_tail(&urbp->list, &info->pending_unlink_list); in xenhcd_unlink_urb()
935 list_move_tail(&urbp->list, &info->in_progress_list); in xenhcd_unlink_urb()
946 if (res->actual_length > urb->transfer_buffer_length) in xenhcd_res_to_urb()
947 urb->actual_length = urb->transfer_buffer_length; in xenhcd_res_to_urb()
948 else if (res->actual_length < 0) in xenhcd_res_to_urb()
949 urb->actual_length = 0; in xenhcd_res_to_urb()
951 urb->actual_length = res->actual_length; in xenhcd_res_to_urb()
952 urb->error_count = res->error_count; in xenhcd_res_to_urb()
953 urb->start_frame = res->start_frame; in xenhcd_res_to_urb()
954 xenhcd_giveback_urb(info, urb, res->status); in xenhcd_res_to_urb()
966 spin_lock_irqsave(&info->lock, flags); in xenhcd_urb_request_done()
968 rp = info->urb_ring.sring->rsp_prod; in xenhcd_urb_request_done()
969 if (RING_RESPONSE_PROD_OVERFLOW(&info->urb_ring, rp)) { in xenhcd_urb_request_done()
970 xenhcd_set_error(info, "Illegal index on urb-ring"); in xenhcd_urb_request_done()
975 for (i = info->urb_ring.rsp_cons; i != rp; i++) { in xenhcd_urb_request_done()
976 RING_COPY_RESPONSE(&info->urb_ring, i, &res); in xenhcd_urb_request_done()
979 xenhcd_set_error(info, "Illegal data on urb-ring"); in xenhcd_urb_request_done()
983 if (likely(xenusb_pipesubmit(info->shadow[id].req.pipe))) { in xenhcd_urb_request_done()
985 if (info->error) in xenhcd_urb_request_done()
987 xenhcd_res_to_urb(info, &res, info->shadow[id].urb); in xenhcd_urb_request_done()
994 info->urb_ring.rsp_cons = i; in xenhcd_urb_request_done()
996 if (i != info->urb_ring.req_prod_pvt) in xenhcd_urb_request_done()
997 RING_FINAL_CHECK_FOR_RESPONSES(&info->urb_ring, more_to_do); in xenhcd_urb_request_done()
999 info->urb_ring.sring->rsp_event = i + 1; in xenhcd_urb_request_done()
1001 spin_unlock_irqrestore(&info->lock, flags); in xenhcd_urb_request_done()
1006 spin_unlock_irqrestore(&info->lock, flags); in xenhcd_urb_request_done()
1022 spin_lock_irqsave(&info->lock, flags); in xenhcd_conn_notify()
1024 rc = info->conn_ring.rsp_cons; in xenhcd_conn_notify()
1025 rp = info->conn_ring.sring->rsp_prod; in xenhcd_conn_notify()
1026 if (RING_RESPONSE_PROD_OVERFLOW(&info->conn_ring, rp)) { in xenhcd_conn_notify()
1027 xenhcd_set_error(info, "Illegal index on conn-ring"); in xenhcd_conn_notify()
1028 spin_unlock_irqrestore(&info->lock, flags); in xenhcd_conn_notify()
1034 RING_COPY_RESPONSE(&info->conn_ring, rc, &res); in xenhcd_conn_notify()
1038 info->conn_ring.rsp_cons = ++rc; in xenhcd_conn_notify()
1041 xenhcd_set_error(info, "Illegal data on conn-ring"); in xenhcd_conn_notify()
1042 spin_unlock_irqrestore(&info->lock, flags); in xenhcd_conn_notify()
1046 if (info->ports[portnum - 1].c_connection) in xenhcd_conn_notify()
1051 req = RING_GET_REQUEST(&info->conn_ring, in xenhcd_conn_notify()
1052 info->conn_ring.req_prod_pvt); in xenhcd_conn_notify()
1053 req->id = id; in xenhcd_conn_notify()
1054 info->conn_ring.req_prod_pvt++; in xenhcd_conn_notify()
1059 if (rc != info->conn_ring.req_prod_pvt) in xenhcd_conn_notify()
1060 RING_FINAL_CHECK_FOR_RESPONSES(&info->conn_ring, more_to_do); in xenhcd_conn_notify()
1062 info->conn_ring.sring->rsp_event = rc + 1; in xenhcd_conn_notify()
1064 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->conn_ring, notify); in xenhcd_conn_notify()
1066 notify_remote_via_irq(info->irq); in xenhcd_conn_notify()
1068 spin_unlock_irqrestore(&info->lock, flags); in xenhcd_conn_notify()
1081 if (unlikely(info->error)) { in xenhcd_int()
1097 if (info->irq) in xenhcd_destroy_rings()
1098 unbind_from_irqhandler(info->irq, info); in xenhcd_destroy_rings()
1099 info->irq = 0; in xenhcd_destroy_rings()
1101 xenbus_teardown_ring((void **)&info->urb_ring.sring, 1, in xenhcd_destroy_rings()
1102 &info->urb_ring_ref); in xenhcd_destroy_rings()
1103 xenbus_teardown_ring((void **)&info->conn_ring.sring, 1, in xenhcd_destroy_rings()
1104 &info->conn_ring_ref); in xenhcd_destroy_rings()
1114 info->conn_ring_ref = INVALID_GRANT_REF; in xenhcd_setup_rings()
1116 (void **)&urb_sring, 1, &info->urb_ring_ref); in xenhcd_setup_rings()
1121 XEN_FRONT_RING_INIT(&info->urb_ring, urb_sring, PAGE_SIZE); in xenhcd_setup_rings()
1124 (void **)&conn_sring, 1, &info->conn_ring_ref); in xenhcd_setup_rings()
1129 XEN_FRONT_RING_INIT(&info->conn_ring, conn_sring, PAGE_SIZE); in xenhcd_setup_rings()
1131 err = xenbus_alloc_evtchn(dev, &info->evtchn); in xenhcd_setup_rings()
1137 err = bind_evtchn_to_irq_lateeoi(info->evtchn); in xenhcd_setup_rings()
1143 info->irq = err; in xenhcd_setup_rings()
1145 err = request_threaded_irq(info->irq, NULL, xenhcd_int, in xenhcd_setup_rings()
1155 unbind_from_irqhandler(info->irq, info); in xenhcd_setup_rings()
1179 err = xenbus_printf(xbt, dev->nodename, "urb-ring-ref", "%u", in xenhcd_talk_to_backend()
1180 info->urb_ring_ref); in xenhcd_talk_to_backend()
1182 message = "writing urb-ring-ref"; in xenhcd_talk_to_backend()
1186 err = xenbus_printf(xbt, dev->nodename, "conn-ring-ref", "%u", in xenhcd_talk_to_backend()
1187 info->conn_ring_ref); in xenhcd_talk_to_backend()
1189 message = "writing conn-ring-ref"; in xenhcd_talk_to_backend()
1193 err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", in xenhcd_talk_to_backend()
1194 info->evtchn); in xenhcd_talk_to_backend()
1196 message = "writing event-channel"; in xenhcd_talk_to_backend()
1202 if (err == -EAGAIN) in xenhcd_talk_to_backend()
1222 struct xenhcd_info *info = dev_get_drvdata(&dev->dev); in xenhcd_connect()
1230 snprintf(name, TASK_COMM_LEN, "xenhcd.%d", hcd->self.busnum); in xenhcd_connect()
1238 req = RING_GET_REQUEST(&info->conn_ring, idx); in xenhcd_connect()
1239 req->id = idx; in xenhcd_connect()
1241 info->conn_ring.req_prod_pvt = idx; in xenhcd_connect()
1243 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->conn_ring, notify); in xenhcd_connect()
1245 notify_remote_via_irq(info->irq); in xenhcd_connect()
1252 struct xenhcd_info *info = dev_get_drvdata(&dev->dev); in xenhcd_disconnect()
1264 spin_lock_irqsave(&info->lock, flags); in xenhcd_watchdog()
1265 if (likely(HC_IS_RUNNING(xenhcd_info_to_hcd(info)->state))) { in xenhcd_watchdog()
1270 spin_unlock_irqrestore(&info->lock, flags); in xenhcd_watchdog()
1274 * one-time HC init
1280 spin_lock_init(&info->lock); in xenhcd_setup()
1281 INIT_LIST_HEAD(&info->pending_submit_list); in xenhcd_setup()
1282 INIT_LIST_HEAD(&info->pending_unlink_list); in xenhcd_setup()
1283 INIT_LIST_HEAD(&info->in_progress_list); in xenhcd_setup()
1284 INIT_LIST_HEAD(&info->giveback_waiting_list); in xenhcd_setup()
1285 timer_setup(&info->watchdog, xenhcd_watchdog, 0); in xenhcd_setup()
1287 hcd->has_tt = (hcd->driver->flags & HCD_MASK) != HCD_USB11; in xenhcd_setup()
1297 hcd->uses_new_polling = 1; in xenhcd_run()
1298 clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); in xenhcd_run()
1299 hcd->state = HC_STATE_RUNNING; in xenhcd_run()
1310 timer_delete_sync(&info->watchdog); in xenhcd_stop()
1311 spin_lock_irq(&info->lock); in xenhcd_stop()
1313 hcd->state = HC_STATE_HALT; in xenhcd_stop()
1316 spin_unlock_irq(&info->lock); in xenhcd_stop()
1321 * non-error returns are promise to giveback the urb later
1331 if (unlikely(info->error)) in xenhcd_urb_enqueue()
1332 return -ESHUTDOWN; in xenhcd_urb_enqueue()
1336 return -ENOMEM; in xenhcd_urb_enqueue()
1338 spin_lock_irqsave(&info->lock, flags); in xenhcd_urb_enqueue()
1340 urbp->urb = urb; in xenhcd_urb_enqueue()
1341 urb->hcpriv = urbp; in xenhcd_urb_enqueue()
1342 urbp->req_id = ~0; in xenhcd_urb_enqueue()
1343 urbp->unlink_req_id = ~0; in xenhcd_urb_enqueue()
1344 INIT_LIST_HEAD(&urbp->list); in xenhcd_urb_enqueue()
1345 urbp->status = 1; in xenhcd_urb_enqueue()
1346 urb->unlinked = false; in xenhcd_urb_enqueue()
1353 spin_unlock_irqrestore(&info->lock, flags); in xenhcd_urb_enqueue()
1361 static int xenhcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) in xenhcd_urb_dequeue() argument
1368 spin_lock_irqsave(&info->lock, flags); in xenhcd_urb_dequeue()
1370 urbp = urb->hcpriv; in xenhcd_urb_dequeue()
1372 urbp->status = status; in xenhcd_urb_dequeue()
1376 spin_unlock_irqrestore(&info->lock, flags); in xenhcd_urb_dequeue()
1387 /* it means error, but probably no problem :-) */ in xenhcd_get_frame()
1392 .description = "xen-hcd",
1417 .description = "xen-hcd",
1450 err = xenbus_scanf(XBT_NIL, dev->otherend, "num-ports", "%d", in xenhcd_create_hcd()
1453 xenbus_dev_fatal(dev, err, "reading num-ports"); in xenhcd_create_hcd()
1454 return ERR_PTR(-EINVAL); in xenhcd_create_hcd()
1457 xenbus_dev_fatal(dev, err, "invalid num-ports"); in xenhcd_create_hcd()
1458 return ERR_PTR(-EINVAL); in xenhcd_create_hcd()
1461 err = xenbus_scanf(XBT_NIL, dev->otherend, "usb-ver", "%d", &usb_ver); in xenhcd_create_hcd()
1463 xenbus_dev_fatal(dev, err, "reading usb-ver"); in xenhcd_create_hcd()
1464 return ERR_PTR(-EINVAL); in xenhcd_create_hcd()
1468 hcd = usb_create_hcd(&xenhcd_usb11_hc_driver, &dev->dev, in xenhcd_create_hcd()
1469 dev_name(&dev->dev)); in xenhcd_create_hcd()
1472 hcd = usb_create_hcd(&xenhcd_usb20_hc_driver, &dev->dev, in xenhcd_create_hcd()
1473 dev_name(&dev->dev)); in xenhcd_create_hcd()
1476 xenbus_dev_fatal(dev, err, "invalid usb-ver"); in xenhcd_create_hcd()
1477 return ERR_PTR(-EINVAL); in xenhcd_create_hcd()
1482 return ERR_PTR(-ENOMEM); in xenhcd_create_hcd()
1486 info->xbdev = dev; in xenhcd_create_hcd()
1487 info->rh_numports = num_ports; in xenhcd_create_hcd()
1490 info->shadow[i].req.id = i + 1; in xenhcd_create_hcd()
1491 info->shadow[i].urb = NULL; in xenhcd_create_hcd()
1492 info->shadow[i].in_flight = false; in xenhcd_create_hcd()
1494 info->shadow[XENUSB_URB_RING_SIZE - 1].req.id = 0x0fff; in xenhcd_create_hcd()
1512 if (dev->state != XenbusStateInitialising) in xenhcd_backend_changed()
1519 if (dev->state == XenbusStateClosed) in xenhcd_backend_changed()
1527 xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend", in xenhcd_backend_changed()
1535 struct xenhcd_info *info = dev_get_drvdata(&dev->dev); in xenhcd_remove()
1550 return -ENODEV; in xenhcd_probe()
1561 dev_set_drvdata(&dev->dev, info); in xenhcd_probe()
1567 dev_set_drvdata(&dev->dev, NULL); in xenhcd_probe()
1588 return -ENODEV; in xenhcd_init()
1594 return -ENOMEM; in xenhcd_init()
1610 MODULE_DESCRIPTION("Xen USB Virtual Host Controller driver (xen-hcd)");