Commit ceb675a9 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge usb-linus branch into usb-next

This pulls in a bunch of fixes that are in Linus's tree because we need them
here for testing and development.
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parents 9662ced3 200e0d99
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/pm_runtime.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb/hcd.h> #include <linux/usb/hcd.h>
...@@ -1029,6 +1030,49 @@ static int register_root_hub(struct usb_hcd *hcd) ...@@ -1029,6 +1030,49 @@ static int register_root_hub(struct usb_hcd *hcd)
return retval; return retval;
} }
/*
* usb_hcd_start_port_resume - a root-hub port is sending a resume signal
* @bus: the bus which the root hub belongs to
* @portnum: the port which is being resumed
*
* HCDs should call this function when they know that a resume signal is
* being sent to a root-hub port. The root hub will be prevented from
* going into autosuspend until usb_hcd_end_port_resume() is called.
*
* The bus's private lock must be held by the caller.
*/
void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum)
{
unsigned bit = 1 << portnum;
if (!(bus->resuming_ports & bit)) {
bus->resuming_ports |= bit;
pm_runtime_get_noresume(&bus->root_hub->dev);
}
}
EXPORT_SYMBOL_GPL(usb_hcd_start_port_resume);
/*
* usb_hcd_end_port_resume - a root-hub port has stopped sending a resume signal
* @bus: the bus which the root hub belongs to
* @portnum: the port which is being resumed
*
* HCDs should call this function when they know that a resume signal has
* stopped being sent to a root-hub port. The root hub will be allowed to
* autosuspend again.
*
* The bus's private lock must be held by the caller.
*/
void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum)
{
unsigned bit = 1 << portnum;
if (bus->resuming_ports & bit) {
bus->resuming_ports &= ~bit;
pm_runtime_put_noidle(&bus->root_hub->dev);
}
}
EXPORT_SYMBOL_GPL(usb_hcd_end_port_resume);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
...@@ -2822,6 +2822,23 @@ void usb_enable_ltm(struct usb_device *udev) ...@@ -2822,6 +2822,23 @@ void usb_enable_ltm(struct usb_device *udev)
EXPORT_SYMBOL_GPL(usb_enable_ltm); EXPORT_SYMBOL_GPL(usb_enable_ltm);
#ifdef CONFIG_USB_SUSPEND #ifdef CONFIG_USB_SUSPEND
/*
* usb_disable_function_remotewakeup - disable usb3.0
* device's function remote wakeup
* @udev: target device
*
* Assume there's only one function on the USB 3.0
* device and disable remote wake for the first
* interface. FIXME if the interface association
* descriptor shows there's more than one function.
*/
static int usb_disable_function_remotewakeup(struct usb_device *udev)
{
return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE,
USB_INTRF_FUNC_SUSPEND, 0, NULL, 0,
USB_CTRL_SET_TIMEOUT);
}
/* /*
* usb_port_suspend - suspend a usb device's upstream port * usb_port_suspend - suspend a usb device's upstream port
...@@ -2939,12 +2956,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) ...@@ -2939,12 +2956,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
port1, status); port1, status);
/* paranoia: "should not happen" */ /* paranoia: "should not happen" */
if (udev->do_remote_wakeup) if (udev->do_remote_wakeup) {
(void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), if (!hub_is_superspeed(hub->hdev)) {
USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, (void) usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
USB_REQ_CLEAR_FEATURE,
USB_RECIP_DEVICE,
USB_DEVICE_REMOTE_WAKEUP, 0, USB_DEVICE_REMOTE_WAKEUP, 0,
NULL, 0, NULL, 0,
USB_CTRL_SET_TIMEOUT); USB_CTRL_SET_TIMEOUT);
} else
(void) usb_disable_function_remotewakeup(udev);
}
/* Try to enable USB2 hardware LPM again */ /* Try to enable USB2 hardware LPM again */
if (udev->usb2_hw_lpm_capable == 1) if (udev->usb2_hw_lpm_capable == 1)
...@@ -3051,8 +3075,9 @@ static int finish_port_resume(struct usb_device *udev) ...@@ -3051,8 +3075,9 @@ static int finish_port_resume(struct usb_device *udev)
* udev->reset_resume * udev->reset_resume
*/ */
} else if (udev->actconfig && !udev->reset_resume) { } else if (udev->actconfig && !udev->reset_resume) {
if (!hub_is_superspeed(udev->parent)) {
le16_to_cpus(&devstatus); le16_to_cpus(&devstatus);
if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
status = usb_control_msg(udev, status = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0), usb_sndctrlpipe(udev, 0),
USB_REQ_CLEAR_FEATURE, USB_REQ_CLEAR_FEATURE,
...@@ -3060,11 +3085,20 @@ static int finish_port_resume(struct usb_device *udev) ...@@ -3060,11 +3085,20 @@ static int finish_port_resume(struct usb_device *udev)
USB_DEVICE_REMOTE_WAKEUP, 0, USB_DEVICE_REMOTE_WAKEUP, 0,
NULL, 0, NULL, 0,
USB_CTRL_SET_TIMEOUT); USB_CTRL_SET_TIMEOUT);
} else {
status = usb_get_status(udev, USB_RECIP_INTERFACE, 0,
&devstatus);
le16_to_cpus(&devstatus);
if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP
| USB_INTRF_STAT_FUNC_RW))
status =
usb_disable_function_remotewakeup(udev);
}
if (status) if (status)
dev_dbg(&udev->dev, dev_dbg(&udev->dev,
"disable remote wakeup, status %d\n", "disable remote wakeup, status %d\n",
status); status);
}
status = 0; status = 0;
} }
return status; return status;
......
...@@ -797,6 +797,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) ...@@ -797,6 +797,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
set_bit(i, &ehci->resuming_ports); set_bit(i, &ehci->resuming_ports);
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
usb_hcd_start_port_resume(&hcd->self, i);
mod_timer(&hcd->rh_timer, ehci->reset_done[i]); mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
} }
} }
......
...@@ -649,7 +649,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) ...@@ -649,7 +649,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
status = STS_PCD; status = STS_PCD;
} }
} }
/* FIXME autosuspend idle root hubs */
/* If a resume is in progress, make sure it can finish */
if (ehci->resuming_ports)
mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25));
spin_unlock_irqrestore (&ehci->lock, flags); spin_unlock_irqrestore (&ehci->lock, flags);
return status ? retval : 0; return status ? retval : 0;
} }
...@@ -851,6 +855,7 @@ static int ehci_hub_control ( ...@@ -851,6 +855,7 @@ static int ehci_hub_control (
/* resume signaling for 20 msec */ /* resume signaling for 20 msec */
ehci->reset_done[wIndex] = jiffies ehci->reset_done[wIndex] = jiffies
+ msecs_to_jiffies(20); + msecs_to_jiffies(20);
usb_hcd_start_port_resume(&hcd->self, wIndex);
/* check the port again */ /* check the port again */
mod_timer(&ehci_to_hcd(ehci)->rh_timer, mod_timer(&ehci_to_hcd(ehci)->rh_timer,
ehci->reset_done[wIndex]); ehci->reset_done[wIndex]);
...@@ -862,6 +867,7 @@ static int ehci_hub_control ( ...@@ -862,6 +867,7 @@ static int ehci_hub_control (
clear_bit(wIndex, &ehci->suspended_ports); clear_bit(wIndex, &ehci->suspended_ports);
set_bit(wIndex, &ehci->port_c_suspend); set_bit(wIndex, &ehci->port_c_suspend);
ehci->reset_done[wIndex] = 0; ehci->reset_done[wIndex] = 0;
usb_hcd_end_port_resume(&hcd->self, wIndex);
/* stop resume signaling */ /* stop resume signaling */
temp = ehci_readl(ehci, status_reg); temp = ehci_readl(ehci, status_reg);
...@@ -950,6 +956,7 @@ static int ehci_hub_control ( ...@@ -950,6 +956,7 @@ static int ehci_hub_control (
ehci->reset_done[wIndex] = 0; ehci->reset_done[wIndex] = 0;
if (temp & PORT_PE) if (temp & PORT_PE)
set_bit(wIndex, &ehci->port_c_suspend); set_bit(wIndex, &ehci->port_c_suspend);
usb_hcd_end_port_resume(&hcd->self, wIndex);
} }
if (temp & PORT_OC) if (temp & PORT_OC)
......
...@@ -1197,17 +1197,26 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested) ...@@ -1197,17 +1197,26 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
if (ehci->async_iaa || ehci->async_unlinking) if (ehci->async_iaa || ehci->async_unlinking)
return; return;
/* Do all the waiting QHs at once */ /* If the controller isn't running, we don't have to wait for it */
if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
/* Do all the waiting QHs */
ehci->async_iaa = ehci->async_unlink; ehci->async_iaa = ehci->async_unlink;
ehci->async_unlink = NULL; ehci->async_unlink = NULL;
/* If the controller isn't running, we don't have to wait for it */
if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
if (!nested) /* Avoid recursion */ if (!nested) /* Avoid recursion */
end_unlink_async(ehci); end_unlink_async(ehci);
/* Otherwise start a new IAA cycle */ /* Otherwise start a new IAA cycle */
} else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { } else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) {
struct ehci_qh *qh;
/* Do only the first waiting QH (nVidia bug?) */
qh = ehci->async_unlink;
ehci->async_iaa = qh;
ehci->async_unlink = qh->unlink_next;
qh->unlink_next = NULL;
/* Make sure the unlinks are all visible to the hardware */ /* Make sure the unlinks are all visible to the hardware */
wmb(); wmb();
...@@ -1255,34 +1264,35 @@ static void end_unlink_async(struct ehci_hcd *ehci) ...@@ -1255,34 +1264,35 @@ static void end_unlink_async(struct ehci_hcd *ehci)
} }
} }
static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
static void unlink_empty_async(struct ehci_hcd *ehci) static void unlink_empty_async(struct ehci_hcd *ehci)
{ {
struct ehci_qh *qh, *next; struct ehci_qh *qh;
bool stopped = (ehci->rh_state < EHCI_RH_RUNNING); struct ehci_qh *qh_to_unlink = NULL;
bool check_unlinks_later = false; bool check_unlinks_later = false;
int count = 0;
/* Unlink all the async QHs that have been empty for a timer cycle */ /* Find the last async QH which has been empty for a timer cycle */
next = ehci->async->qh_next.qh; for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh) {
while (next) {
qh = next;
next = qh->qh_next.qh;
if (list_empty(&qh->qtd_list) && if (list_empty(&qh->qtd_list) &&
qh->qh_state == QH_STATE_LINKED) { qh->qh_state == QH_STATE_LINKED) {
if (!stopped && qh->unlink_cycle == ++count;
ehci->async_unlink_cycle) if (qh->unlink_cycle == ehci->async_unlink_cycle)
check_unlinks_later = true; check_unlinks_later = true;
else else
single_unlink_async(ehci, qh); qh_to_unlink = qh;
} }
} }
/* Start a new IAA cycle if any QHs are waiting for it */ /* If nothing else is being unlinked, unlink the last empty QH */
if (ehci->async_unlink) if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) {
start_iaa_cycle(ehci, false); start_unlink_async(ehci, qh_to_unlink);
--count;
}
/* QHs that haven't been empty for long enough will be handled later */ /* Other QHs will be handled later */
if (check_unlinks_later) { if (count > 0) {
ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true); ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true);
++ehci->async_unlink_cycle; ++ehci->async_unlink_cycle;
} }
......
...@@ -213,7 +213,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) ...@@ -213,7 +213,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask)
} }
static const unsigned char static const unsigned char
max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 };
/* carryover low/fullspeed bandwidth that crosses uframe boundries */ /* carryover low/fullspeed bandwidth that crosses uframe boundries */
static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8])
...@@ -2212,11 +2212,11 @@ static void scan_isoc(struct ehci_hcd *ehci) ...@@ -2212,11 +2212,11 @@ static void scan_isoc(struct ehci_hcd *ehci)
} }
ehci->now_frame = now_frame; ehci->now_frame = now_frame;
frame = ehci->last_iso_frame;
for (;;) { for (;;) {
union ehci_shadow q, *q_p; union ehci_shadow q, *q_p;
__hc32 type, *hw_p; __hc32 type, *hw_p;
frame = ehci->last_iso_frame;
restart: restart:
/* scan each element in frame's queue for completions */ /* scan each element in frame's queue for completions */
q_p = &ehci->pshadow [frame]; q_p = &ehci->pshadow [frame];
...@@ -2321,6 +2321,9 @@ static void scan_isoc(struct ehci_hcd *ehci) ...@@ -2321,6 +2321,9 @@ static void scan_isoc(struct ehci_hcd *ehci)
/* Stop when we have reached the current frame */ /* Stop when we have reached the current frame */
if (frame == now_frame) if (frame == now_frame)
break; break;
ehci->last_iso_frame = (frame + 1) & fmask;
/* The last frame may still have active siTDs */
ehci->last_iso_frame = frame;
frame = (frame + 1) & fmask;
} }
} }
...@@ -113,14 +113,15 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci) ...@@ -113,14 +113,15 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)
if (want != actual) { if (want != actual) {
/* Poll again later, but give up after about 20 ms */ /* Poll again later */
if (ehci->ASS_poll_count++ < 20) {
ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
++ehci->ASS_poll_count;
return; return;
} }
ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n",
want, actual); if (ehci->ASS_poll_count > 20)
} ehci_dbg(ehci, "ASS poll count reached %d\n",
ehci->ASS_poll_count);
ehci->ASS_poll_count = 0; ehci->ASS_poll_count = 0;
/* The status is up-to-date; restart or stop the schedule as needed */ /* The status is up-to-date; restart or stop the schedule as needed */
...@@ -159,14 +160,14 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci) ...@@ -159,14 +160,14 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
if (want != actual) { if (want != actual) {
/* Poll again later, but give up after about 20 ms */ /* Poll again later */
if (ehci->PSS_poll_count++ < 20) {
ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
return; return;
} }
ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
want, actual); if (ehci->PSS_poll_count > 20)
} ehci_dbg(ehci, "PSS poll count reached %d\n",
ehci->PSS_poll_count);
ehci->PSS_poll_count = 0; ehci->PSS_poll_count = 0;
/* The status is up-to-date; restart or stop the schedule as needed */ /* The status is up-to-date; restart or stop the schedule as needed */
......
...@@ -780,6 +780,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) ...@@ -780,6 +780,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
"defaulting to EHCI.\n"); "defaulting to EHCI.\n");
dev_warn(&xhci_pdev->dev, dev_warn(&xhci_pdev->dev,
"USB 3.0 devices will work at USB 2.0 speeds.\n"); "USB 3.0 devices will work at USB 2.0 speeds.\n");
usb_disable_xhci_ports(xhci_pdev);
return; return;
} }
......
...@@ -116,6 +116,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, ...@@ -116,6 +116,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
} }
} }
clear_bit(port, &uhci->resuming_ports); clear_bit(port, &uhci->resuming_ports);
usb_hcd_end_port_resume(&uhci_to_hcd(uhci)->self, port);
} }
/* Wait for the UHCI controller in HP's iLO2 server management chip. /* Wait for the UHCI controller in HP's iLO2 server management chip.
...@@ -167,6 +168,8 @@ static void uhci_check_ports(struct uhci_hcd *uhci) ...@@ -167,6 +168,8 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
set_bit(port, &uhci->resuming_ports); set_bit(port, &uhci->resuming_ports);
uhci->ports_timeout = jiffies + uhci->ports_timeout = jiffies +
msecs_to_jiffies(25); msecs_to_jiffies(25);
usb_hcd_start_port_resume(
&uhci_to_hcd(uhci)->self, port);
/* Make sure we see the port again /* Make sure we see the port again
* after the resuming period is over. */ * after the resuming period is over. */
......
...@@ -1698,7 +1698,7 @@ static void handle_port_status(struct xhci_hcd *xhci, ...@@ -1698,7 +1698,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
faked_port_index + 1); faked_port_index + 1);
if (slot_id && xhci->devs[slot_id]) if (slot_id && xhci->devs[slot_id])
xhci_ring_device(xhci, slot_id); xhci_ring_device(xhci, slot_id);
if (bus_state->port_remote_wakeup && (1 << faked_port_index)) { if (bus_state->port_remote_wakeup & (1 << faked_port_index)) {
bus_state->port_remote_wakeup &= bus_state->port_remote_wakeup &=
~(1 << faked_port_index); ~(1 << faked_port_index);
xhci_test_and_clear_bit(xhci, port_array, xhci_test_and_clear_bit(xhci, port_array,
...@@ -2589,6 +2589,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -2589,6 +2589,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
(trb_comp_code != COMP_STALL && (trb_comp_code != COMP_STALL &&
trb_comp_code != COMP_BABBLE)) trb_comp_code != COMP_BABBLE))
xhci_urb_free_priv(xhci, urb_priv); xhci_urb_free_priv(xhci, urb_priv);
else
kfree(urb_priv);
usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb); usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
if ((urb->actual_length != urb->transfer_buffer_length && if ((urb->actual_length != urb->transfer_buffer_length &&
...@@ -3106,7 +3108,7 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len, ...@@ -3106,7 +3108,7 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
* running_total. * running_total.
*/ */
packets_transferred = (running_total + trb_buff_len) / packets_transferred = (running_total + trb_buff_len) /
usb_endpoint_maxp(&urb->ep->desc); GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
if ((total_packet_count - packets_transferred) > 31) if ((total_packet_count - packets_transferred) > 31)
return 31 << 17; return 31 << 17;
...@@ -3640,7 +3642,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, ...@@ -3640,7 +3642,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
td_len = urb->iso_frame_desc[i].length; td_len = urb->iso_frame_desc[i].length;
td_remain_len = td_len; td_remain_len = td_len;
total_packet_count = DIV_ROUND_UP(td_len, total_packet_count = DIV_ROUND_UP(td_len,
usb_endpoint_maxp(&urb->ep->desc)); GET_MAX_PACKET(
usb_endpoint_maxp(&urb->ep->desc)));
/* A zero-length transfer still involves at least one packet. */ /* A zero-length transfer still involves at least one packet. */
if (total_packet_count == 0) if (total_packet_count == 0)
total_packet_count++; total_packet_count++;
...@@ -3662,9 +3665,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, ...@@ -3662,9 +3665,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
td = urb_priv->td[i]; td = urb_priv->td[i];
for (j = 0; j < trbs_per_td; j++) { for (j = 0; j < trbs_per_td; j++) {
u32 remainder = 0; u32 remainder = 0;
field = TRB_TBC(burst_count) | TRB_TLBPC(residue); field = 0;
if (first_trb) { if (first_trb) {
field = TRB_TBC(burst_count) |
TRB_TLBPC(residue);
/* Queue the isoc TRB */ /* Queue the isoc TRB */
field |= TRB_TYPE(TRB_ISOC); field |= TRB_TYPE(TRB_ISOC);
/* Assume URB_ISO_ASAP is set */ /* Assume URB_ISO_ASAP is set */
......
...@@ -60,6 +60,7 @@ static const struct usb_device_id id_table[] = { ...@@ -60,6 +60,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
{ USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */
{ USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */
{ USB_DEVICE(0x0FDE, 0xCA05) }, /* OWL Wireless Electricity Monitor CM-160 */
{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
......
...@@ -584,6 +584,7 @@ static struct usb_device_id id_table_combined [] = { ...@@ -584,6 +584,7 @@ static struct usb_device_id id_table_combined [] = {
/* /*
* ELV devices: * ELV devices:
*/ */
{ USB_DEVICE(FTDI_ELV_VID, FTDI_ELV_WS300_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) },
...@@ -670,6 +671,7 @@ static struct usb_device_id id_table_combined [] = { ...@@ -670,6 +671,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) },
......
...@@ -147,6 +147,11 @@ ...@@ -147,6 +147,11 @@
#define XSENS_CONVERTER_6_PID 0xD38E #define XSENS_CONVERTER_6_PID 0xD38E
#define XSENS_CONVERTER_7_PID 0xD38F #define XSENS_CONVERTER_7_PID 0xD38F
/**
* Zolix (www.zolix.com.cb) product ids
*/
#define FTDI_OMNI1509 0xD491 /* Omni1509 embedded USB-serial */
/* /*
* NDI (www.ndigital.com) product ids * NDI (www.ndigital.com) product ids
*/ */
...@@ -204,7 +209,7 @@ ...@@ -204,7 +209,7 @@
/* /*
* ELV USB devices submitted by Christian Abt of ELV (www.elv.de). * ELV USB devices submitted by Christian Abt of ELV (www.elv.de).
* All of these devices use FTDI's vendor ID (0x0403). * Almost all of these devices use FTDI's vendor ID (0x0403).
* Further IDs taken from ELV Windows .inf file. * Further IDs taken from ELV Windows .inf file.
* *
* The previously included PID for the UO 100 module was incorrect. * The previously included PID for the UO 100 module was incorrect.
...@@ -212,6 +217,8 @@ ...@@ -212,6 +217,8 @@
* *
* Armin Laeuger originally sent the PID for the UM 100 module. * Armin Laeuger originally sent the PID for the UM 100 module.
*/ */
#define FTDI_ELV_VID 0x1B1F /* ELV AG */
#define FTDI_ELV_WS300_PID 0xC006 /* eQ3 WS 300 PC II */
#define FTDI_ELV_USR_PID 0xE000 /* ELV Universal-Sound-Recorder */ #define FTDI_ELV_USR_PID 0xE000 /* ELV Universal-Sound-Recorder */
#define FTDI_ELV_MSM1_PID 0xE001 /* ELV Mini-Sound-Modul */ #define FTDI_ELV_MSM1_PID 0xE001 /* ELV Mini-Sound-Modul */
#define FTDI_ELV_KL100_PID 0xE002 /* ELV Kfz-Leistungsmesser KL 100 */ #define FTDI_ELV_KL100_PID 0xE002 /* ELV Kfz-Leistungsmesser KL 100 */
......
...@@ -242,6 +242,7 @@ static void option_instat_callback(struct urb *urb); ...@@ -242,6 +242,7 @@ static void option_instat_callback(struct urb *urb);
#define TELIT_PRODUCT_CC864_DUAL 0x1005 #define TELIT_PRODUCT_CC864_DUAL 0x1005
#define TELIT_PRODUCT_CC864_SINGLE 0x1006 #define TELIT_PRODUCT_CC864_SINGLE 0x1006
#define TELIT_PRODUCT_DE910_DUAL 0x1010 #define TELIT_PRODUCT_DE910_DUAL 0x1010
#define TELIT_PRODUCT_LE920 0x1200
/* ZTE PRODUCTS */ /* ZTE PRODUCTS */
#define ZTE_VENDOR_ID 0x19d2 #define ZTE_VENDOR_ID 0x19d2
...@@ -453,6 +454,10 @@ static void option_instat_callback(struct urb *urb); ...@@ -453,6 +454,10 @@ static void option_instat_callback(struct urb *urb);
#define TPLINK_VENDOR_ID 0x2357 #define TPLINK_VENDOR_ID 0x2357
#define TPLINK_PRODUCT_MA180 0x0201 #define TPLINK_PRODUCT_MA180 0x0201
/* Changhong products */
#define CHANGHONG_VENDOR_ID 0x2077
#define CHANGHONG_PRODUCT_CH690 0x7001
/* some devices interfaces need special handling due to a number of reasons */ /* some devices interfaces need special handling due to a number of reasons */
enum option_blacklist_reason { enum option_blacklist_reason {
OPTION_BLACKLIST_NONE = 0, OPTION_BLACKLIST_NONE = 0,
...@@ -535,6 +540,11 @@ static const struct option_blacklist_info zte_1255_blacklist = { ...@@ -535,6 +540,11 @@ static const struct option_blacklist_info zte_1255_blacklist = {
.reserved = BIT(3) | BIT(4), .reserved = BIT(3) | BIT(4),
}; };
static const struct option_blacklist_info telit_le920_blacklist = {
.sendsetup = BIT(0),
.reserved = BIT(1) | BIT(5),
};
static const struct usb_device_id option_ids[] = { static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
...@@ -785,6 +795,8 @@ static const struct usb_device_id option_ids[] = { ...@@ -785,6 +795,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
.driver_info = (kernel_ulong_t)&telit_le920_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff), { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf1_blacklist }, .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
...@@ -1326,6 +1338,7 @@ static const struct usb_device_id option_ids[] = { ...@@ -1326,6 +1338,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) },
{ USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist }, .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(usb, option_ids); MODULE_DEVICE_TABLE(usb, option_ids);
......
...@@ -53,6 +53,7 @@ static const struct usb_device_id id_table[] = { ...@@ -53,6 +53,7 @@ static const struct usb_device_id id_table[] = {
{DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
{DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
{DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
{DEVICE_G1K(0x1bc7, 0x900e)}, /* Telit Gobi QDL device */
/* Gobi 2000 devices */ /* Gobi 2000 devices */
{USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */ {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */
......
...@@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us) ...@@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
return 0; return 0;
} }
/* This places the HUAWEI E220 devices in multi-port mode */ /* This places the HUAWEI usb dongles in multi-port mode */
int usb_stor_huawei_e220_init(struct us_data *us) static int usb_stor_huawei_feature_init(struct us_data *us)
{ {
int result; int result;
...@@ -104,3 +104,75 @@ int usb_stor_huawei_e220_init(struct us_data *us) ...@@ -104,3 +104,75 @@ int usb_stor_huawei_e220_init(struct us_data *us)
US_DEBUGP("Huawei mode set result is %d\n", result); US_DEBUGP("Huawei mode set result is %d\n", result);
return 0; return 0;
} }
/*
* It will send a scsi switch command called rewind' to huawei dongle.
* When the dongle receives this command at the first time,
* it will reboot immediately. After rebooted, it will ignore this command.
* So it is unnecessary to read its response.
*/
static int usb_stor_huawei_scsi_init(struct us_data *us)
{
int result = 0;
int act_len = 0;
struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf;
char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcbw->Tag = 0;
bcbw->DataTransferLength = 0;
bcbw->Flags = bcbw->Lun = 0;
bcbw->Length = sizeof(rewind_cmd);
memset(bcbw->CDB, 0, sizeof(bcbw->CDB));
memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd));
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw,
US_BULK_CB_WRAP_LEN, &act_len);
US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result);
return result;
}
/*
* It tries to find the supported Huawei USB dongles.
* In Huawei, they assign the following product IDs
* for all of their mobile broadband dongles,
* including the new dongles in the future.
* So if the product ID is not included in this list,
* it means it is not Huawei's mobile broadband dongles.
*/
static int usb_stor_huawei_dongles_pid(struct us_data *us)
{
struct usb_interface_descriptor *idesc;
int idProduct;
idesc = &us->pusb_intf->cur_altsetting->desc;
idProduct = us->pusb_dev->descriptor.idProduct;
/* The first port is CDROM,
* means the dongle in the single port mode,
* and a switch command is required to be sent. */
if (idesc && idesc->bInterfaceNumber == 0) {
if ((idProduct == 0x1001)
|| (idProduct == 0x1003)
|| (idProduct == 0x1004)
|| (idProduct >= 0x1401 && idProduct <= 0x1500)
|| (idProduct >= 0x1505 && idProduct <= 0x1600)
|| (idProduct >= 0x1c02 && idProduct <= 0x2202)) {
return 1;
}
}
return 0;
}
int usb_stor_huawei_init(struct us_data *us)
{
int result = 0;
if (usb_stor_huawei_dongles_pid(us)) {
if (us->pusb_dev->descriptor.idProduct >= 0x1446)
result = usb_stor_huawei_scsi_init(us);
else
result = usb_stor_huawei_feature_init(us);
}
return result;
}
...@@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us); ...@@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us);
* flash reader */ * flash reader */
int usb_stor_ucr61s2b_init(struct us_data *us); int usb_stor_ucr61s2b_init(struct us_data *us);
/* This places the HUAWEI E220 devices in multi-port mode */ /* This places the HUAWEI usb dongles in multi-port mode */
int usb_stor_huawei_e220_init(struct us_data *us); int usb_stor_huawei_init(struct us_data *us);
This diff is collapsed.
...@@ -120,6 +120,17 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks"); ...@@ -120,6 +120,17 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");
.useTransport = use_transport, \ .useTransport = use_transport, \
} }
#define UNUSUAL_VENDOR_INTF(idVendor, cl, sc, pr, \
vendor_name, product_name, use_protocol, use_transport, \
init_function, Flags) \
{ \
.vendorName = vendor_name, \
.productName = product_name, \
.useProtocol = use_protocol, \
.useTransport = use_transport, \
.initFunction = init_function, \
}
static struct us_unusual_dev us_unusual_dev_list[] = { static struct us_unusual_dev us_unusual_dev_list[] = {
# include "unusual_devs.h" # include "unusual_devs.h"
{ } /* Terminating entry */ { } /* Terminating entry */
...@@ -131,6 +142,7 @@ static struct us_unusual_dev for_dynamic_ids = ...@@ -131,6 +142,7 @@ static struct us_unusual_dev for_dynamic_ids =
#undef UNUSUAL_DEV #undef UNUSUAL_DEV
#undef COMPLIANT_DEV #undef COMPLIANT_DEV
#undef USUAL_DEV #undef USUAL_DEV
#undef UNUSUAL_VENDOR_INTF
#ifdef CONFIG_LOCKDEP #ifdef CONFIG_LOCKDEP
......
...@@ -41,6 +41,20 @@ ...@@ -41,6 +41,20 @@
#define USUAL_DEV(useProto, useTrans) \ #define USUAL_DEV(useProto, useTrans) \
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans) } { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans) }
/* Define the device is matched with Vendor ID and interface descriptors */
#define UNUSUAL_VENDOR_INTF(id_vendor, cl, sc, pr, \
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ \
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
| USB_DEVICE_ID_MATCH_VENDOR, \
.idVendor = (id_vendor), \
.bInterfaceClass = (cl), \
.bInterfaceSubClass = (sc), \
.bInterfaceProtocol = (pr), \
.driver_info = (flags) \
}
struct usb_device_id usb_storage_usb_ids[] = { struct usb_device_id usb_storage_usb_ids[] = {
# include "unusual_devs.h" # include "unusual_devs.h"
{ } /* Terminating entry */ { } /* Terminating entry */
...@@ -50,6 +64,7 @@ MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids); ...@@ -50,6 +64,7 @@ MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids);
#undef UNUSUAL_DEV #undef UNUSUAL_DEV
#undef COMPLIANT_DEV #undef COMPLIANT_DEV
#undef USUAL_DEV #undef USUAL_DEV
#undef UNUSUAL_VENDOR_INTF
/* /*
* The table of devices to ignore * The table of devices to ignore
......
...@@ -357,6 +357,8 @@ struct usb_bus { ...@@ -357,6 +357,8 @@ struct usb_bus {
int bandwidth_int_reqs; /* number of Interrupt requests */ int bandwidth_int_reqs; /* number of Interrupt requests */
int bandwidth_isoc_reqs; /* number of Isoc. requests */ int bandwidth_isoc_reqs; /* number of Isoc. requests */
unsigned resuming_ports; /* bit array: resuming root-hub ports */
#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE) #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
struct mon_bus *mon_bus; /* non-null when associated */ struct mon_bus *mon_bus; /* non-null when associated */
int monitored; /* non-zero when monitored */ int monitored; /* non-zero when monitored */
......
...@@ -430,6 +430,9 @@ extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd); ...@@ -430,6 +430,9 @@ extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
extern void usb_wakeup_notification(struct usb_device *hdev, extern void usb_wakeup_notification(struct usb_device *hdev,
unsigned int portnum); unsigned int portnum);
extern void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum);
extern void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum);
/* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */ /* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1) #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep))) #define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep)))
......
...@@ -152,6 +152,12 @@ ...@@ -152,6 +152,12 @@
#define USB_INTRF_FUNC_SUSPEND_LP (1 << (8 + 0)) #define USB_INTRF_FUNC_SUSPEND_LP (1 << (8 + 0))
#define USB_INTRF_FUNC_SUSPEND_RW (1 << (8 + 1)) #define USB_INTRF_FUNC_SUSPEND_RW (1 << (8 + 1))
/*
* Interface status, Figure 9-5 USB 3.0 spec
*/
#define USB_INTRF_STAT_FUNC_RW_CAP 1
#define USB_INTRF_STAT_FUNC_RW 2
#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ #define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */
/* Bit array elements as returned by the USB_REQ_GET_STATUS request. */ /* Bit array elements as returned by the USB_REQ_GET_STATUS request. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment