--- zzzz-none-000/linux-3.10.107/drivers/usb/wusbcore/wa-rpipe.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/usb/wusbcore/wa-rpipe.c 2021-02-04 17:41:59.000000000 +0000 @@ -57,7 +57,6 @@ * urb->dev->devnum, to make sure that we always have the right * destination address. */ -#include #include #include #include @@ -80,7 +79,7 @@ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_RPIPE, USB_DT_RPIPE<<8, index, descr, sizeof(*descr), - 1000 /* FIXME: arbitrary */); + USB_CTRL_GET_TIMEOUT); if (result < 0) { dev_err(dev, "rpipe %u: get descriptor failed: %d\n", index, (int)result); @@ -118,7 +117,7 @@ USB_REQ_SET_DESCRIPTOR, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE, USB_DT_RPIPE<<8, index, descr, sizeof(*descr), - HZ / 10); + USB_CTRL_SET_TIMEOUT); if (result < 0) { dev_err(dev, "rpipe %u: set descriptor failed: %d\n", index, (int)result); @@ -143,17 +142,18 @@ kref_init(&rpipe->refcnt); spin_lock_init(&rpipe->seg_lock); INIT_LIST_HEAD(&rpipe->seg_list); + INIT_LIST_HEAD(&rpipe->list_node); } static unsigned rpipe_get_idx(struct wahc *wa, unsigned rpipe_idx) { unsigned long flags; - spin_lock_irqsave(&wa->rpipe_bm_lock, flags); + spin_lock_irqsave(&wa->rpipe_lock, flags); rpipe_idx = find_next_zero_bit(wa->rpipe_bm, wa->rpipes, rpipe_idx); if (rpipe_idx < wa->rpipes) set_bit(rpipe_idx, wa->rpipe_bm); - spin_unlock_irqrestore(&wa->rpipe_bm_lock, flags); + spin_unlock_irqrestore(&wa->rpipe_lock, flags); return rpipe_idx; } @@ -162,9 +162,9 @@ { unsigned long flags; - spin_lock_irqsave(&wa->rpipe_bm_lock, flags); + spin_lock_irqsave(&wa->rpipe_lock, flags); clear_bit(rpipe_idx, wa->rpipe_bm); - spin_unlock_irqrestore(&wa->rpipe_bm_lock, flags); + spin_unlock_irqrestore(&wa->rpipe_lock, flags); } void rpipe_destroy(struct kref *_rpipe) @@ -183,7 +183,7 @@ /* * Locate an idle rpipe, create an structure for it and return it * - * @wa is referenced and unlocked + * @wa is referenced and unlocked * @crs enum rpipe_attr, required endpoint characteristics * * The rpipe can be used only sequentially (not in parallel). @@ -236,7 +236,7 @@ wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), USB_REQ_RPIPE_RESET, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE, - 0, index, NULL, 0, 1000 /* FIXME: arbitrary */); + 0, index, NULL, 0, USB_CTRL_SET_TIMEOUT); if (result < 0) dev_err(dev, "rpipe %u: reset failed: %d\n", index, result); @@ -251,8 +251,8 @@ static struct usb_wireless_ep_comp_descriptor epc0 = { .bLength = sizeof(epc0), .bDescriptorType = USB_DT_WIRELESS_ENDPOINT_COMP, -/* .bMaxBurst = 1, */ - .bMaxSequence = 31, + .bMaxBurst = 1, + .bMaxSequence = 2, }; /* @@ -298,7 +298,7 @@ break; } itr += hdr->bLength; - itr_size -= hdr->bDescriptorType; + itr_size -= hdr->bLength; } out: return epcd; @@ -307,7 +307,7 @@ /* * Aim an rpipe to its device & endpoint destination * - * Make sure we change the address to unauthenticathed if the device + * Make sure we change the address to unauthenticated if the device * is WUSB and it is not authenticated. */ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa, @@ -317,6 +317,7 @@ struct device *dev = &wa->usb_iface->dev; struct usb_device *usb_dev = urb->dev; struct usb_wireless_ep_comp_descriptor *epcd; + u32 ack_window, epcd_max_sequence; u8 unauth; epcd = rpipe_epc_find(dev, ep); @@ -327,14 +328,21 @@ } unauth = usb_dev->wusb && !usb_dev->authenticated ? 0x80 : 0; __rpipe_reset(wa, le16_to_cpu(rpipe->descr.wRPipeIndex)); - atomic_set(&rpipe->segs_available, le16_to_cpu(rpipe->descr.wRequests)); + atomic_set(&rpipe->segs_available, + le16_to_cpu(rpipe->descr.wRequests)); /* FIXME: block allocation system; request with queuing and timeout */ /* FIXME: compute so seg_size > ep->maxpktsize */ rpipe->descr.wBlocks = cpu_to_le16(16); /* given */ /* ep0 maxpktsize is 0x200 (WUSB1.0[4.8.1]) */ - rpipe->descr.wMaxPacketSize = cpu_to_le16(ep->desc.wMaxPacketSize); - rpipe->descr.bHSHubAddress = 0; /* reserved: zero */ - rpipe->descr.bHSHubPort = wusb_port_no_to_idx(urb->dev->portnum); + if (usb_endpoint_xfer_isoc(&ep->desc)) + rpipe->descr.wMaxPacketSize = epcd->wOverTheAirPacketSize; + else + rpipe->descr.wMaxPacketSize = ep->desc.wMaxPacketSize; + + rpipe->descr.hwa_bMaxBurst = max(min_t(unsigned int, + epcd->bMaxBurst, 16U), 1U); + rpipe->descr.hwa_bDeviceInfoIndex = + wusb_port_no_to_idx(urb->dev->portnum); /* FIXME: use maximum speed as supported or recommended by device */ rpipe->descr.bSpeed = usb_pipeendpoint(urb->pipe) == 0 ? UWB_PHY_RATE_53 : UWB_PHY_RATE_200; @@ -344,26 +352,28 @@ le16_to_cpu(rpipe->descr.wRPipeIndex), usb_pipeendpoint(urb->pipe), rpipe->descr.bSpeed); - /* see security.c:wusb_update_address() */ - if (unlikely(urb->dev->devnum == 0x80)) - rpipe->descr.bDeviceAddress = 0; - else - rpipe->descr.bDeviceAddress = urb->dev->devnum | unauth; + rpipe->descr.hwa_reserved = 0; + rpipe->descr.bEndpointAddress = ep->desc.bEndpointAddress; /* FIXME: bDataSequence */ rpipe->descr.bDataSequence = 0; - /* FIXME: dwCurrentWindow */ - rpipe->descr.dwCurrentWindow = cpu_to_le32(1); - /* FIXME: bMaxDataSequence */ - rpipe->descr.bMaxDataSequence = epcd->bMaxSequence - 1; + + /* start with base window of hwa_bMaxBurst bits starting at 0. */ + ack_window = 0xFFFFFFFF >> (32 - rpipe->descr.hwa_bMaxBurst); + rpipe->descr.dwCurrentWindow = cpu_to_le32(ack_window); + epcd_max_sequence = max(min_t(unsigned int, + epcd->bMaxSequence, 32U), 2U); + rpipe->descr.bMaxDataSequence = epcd_max_sequence - 1; rpipe->descr.bInterval = ep->desc.bInterval; - /* FIXME: bOverTheAirInterval */ - rpipe->descr.bOverTheAirInterval = 0; /* 0 if not isoc */ + if (usb_endpoint_xfer_isoc(&ep->desc)) + rpipe->descr.bOverTheAirInterval = epcd->bOverTheAirInterval; + else + rpipe->descr.bOverTheAirInterval = 0; /* 0 if not isoc */ /* FIXME: xmit power & preamble blah blah */ - rpipe->descr.bmAttribute = ep->desc.bmAttributes & 0x03; + rpipe->descr.bmAttribute = (ep->desc.bmAttributes & + USB_ENDPOINT_XFERTYPE_MASK); /* rpipe->descr.bmCharacteristics RO */ - /* FIXME: bmRetryOptions */ - rpipe->descr.bmRetryOptions = 15; + rpipe->descr.bmRetryOptions = (wa->wusb->retry_count & 0xF); /* FIXME: use for assessing link quality? */ rpipe->descr.wNumTransactionErrors = 0; result = __rpipe_set_descr(wa, &rpipe->descr, @@ -387,10 +397,8 @@ const struct usb_host_endpoint *ep, const struct urb *urb, gfp_t gfp) { - int result = 0; /* better code for lack of companion? */ + int result = 0; struct device *dev = &wa->usb_iface->dev; - struct usb_device *usb_dev = urb->dev; - u8 unauth = (usb_dev->wusb && !usb_dev->authenticated) ? 0x80 : 0; u8 portnum = wusb_port_no_to_idx(urb->dev->portnum); #define AIM_CHECK(rdf, val, text) \ @@ -403,13 +411,10 @@ WARN_ON(1); \ } \ } while (0) - AIM_CHECK(wMaxPacketSize, cpu_to_le16(ep->desc.wMaxPacketSize), - "(%u vs %u)"); - AIM_CHECK(bHSHubPort, portnum, "(%u vs %u)"); + AIM_CHECK(hwa_bDeviceInfoIndex, portnum, "(%u vs %u)"); AIM_CHECK(bSpeed, usb_pipeendpoint(urb->pipe) == 0 ? UWB_PHY_RATE_53 : UWB_PHY_RATE_200, "(%u vs %u)"); - AIM_CHECK(bDeviceAddress, urb->dev->devnum | unauth, "(%u vs %u)"); AIM_CHECK(bEndpointAddress, ep->desc.bEndpointAddress, "(%u vs %u)"); AIM_CHECK(bInterval, ep->desc.bInterval, "(%u vs %u)"); AIM_CHECK(bmAttribute, ep->desc.bmAttributes & 0x03, "(%u vs %u)"); @@ -478,7 +483,7 @@ */ int wa_rpipes_create(struct wahc *wa) { - wa->rpipes = wa->wa_descr->wNumRPipes; + wa->rpipes = le16_to_cpu(wa->wa_descr->wNumRPipes); wa->rpipe_bm = kzalloc(BITS_TO_LONGS(wa->rpipes)*sizeof(unsigned long), GFP_KERNEL); if (wa->rpipe_bm == NULL) @@ -491,10 +496,9 @@ struct device *dev = &wa->usb_iface->dev; if (!bitmap_empty(wa->rpipe_bm, wa->rpipes)) { - char buf[256]; WARN_ON(1); - bitmap_scnprintf(buf, sizeof(buf), wa->rpipe_bm, wa->rpipes); - dev_err(dev, "BUG: pipes not released on exit: %s\n", buf); + dev_err(dev, "BUG: pipes not released on exit: %*pb\n", + wa->rpipes, wa->rpipe_bm); } kfree(wa->rpipe_bm); } @@ -519,12 +523,32 @@ u16 index = le16_to_cpu(rpipe->descr.wRPipeIndex); usb_control_msg( - wa->usb_dev, usb_rcvctrlpipe(wa->usb_dev, 0), + wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), USB_REQ_RPIPE_ABORT, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE, - 0, index, NULL, 0, 1000 /* FIXME: arbitrary */); + 0, index, NULL, 0, USB_CTRL_SET_TIMEOUT); rpipe_put(rpipe); } mutex_unlock(&wa->rpipe_mutex); } EXPORT_SYMBOL_GPL(rpipe_ep_disable); + +/* Clear the stalled status of an RPIPE. */ +void rpipe_clear_feature_stalled(struct wahc *wa, struct usb_host_endpoint *ep) +{ + struct wa_rpipe *rpipe; + + mutex_lock(&wa->rpipe_mutex); + rpipe = ep->hcpriv; + if (rpipe != NULL) { + u16 index = le16_to_cpu(rpipe->descr.wRPipeIndex); + + usb_control_msg( + wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), + USB_REQ_CLEAR_FEATURE, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE, + RPIPE_STALL, index, NULL, 0, USB_CTRL_SET_TIMEOUT); + } + mutex_unlock(&wa->rpipe_mutex); +} +EXPORT_SYMBOL_GPL(rpipe_clear_feature_stalled);