USB fixes for 3.9-rc4
Here are some USB fixes to resolve issues reported recently, as well as a new device id for the ftdi_sio driver. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iEYEABECAAYFAlFUaA0ACgkQMUfUDdst+yk0AACfe9iitBiGERSO4NsyIvypoJ1q vOgAoKek8fiPmTKrZl18n79oX28qU9x2 =Oee3 -----END PGP SIGNATURE----- Merge tag 'usb-3.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB fixes from Greg Kroah-Hartman: "Here are some USB fixes to resolve issues reported recently, as well as a new device id for the ftdi_sio driver." * tag 'usb-3.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: usb: ftdi_sio: Add support for Mitsubishi FX-USB-AW/-BD usb: Fix compile error by selecting USB_OTG_UTILS USB: serial: fix hang when opening port USB: EHCI: fix bug in iTD/siTD DMA pool allocation xhci: Don't warn on empty ring for suspended devices. usb: xhci: Fix TRB transfer length macro used for Event TRB. usb/acpi: binding xhci root hub usb port with ACPI usb: add find_raw_port_number callback to struct hc_driver() usb: xhci: fix build warning
This commit is contained in:
Коммит
0776ce03b1
|
@ -2412,6 +2412,14 @@ int usb_hcd_is_primary_hcd(struct usb_hcd *hcd)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd);
|
||||
|
||||
int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1)
|
||||
{
|
||||
if (!hcd->driver->find_raw_port_number)
|
||||
return port1;
|
||||
|
||||
return hcd->driver->find_raw_port_number(hcd, port1);
|
||||
}
|
||||
|
||||
static int usb_hcd_request_irqs(struct usb_hcd *hcd,
|
||||
unsigned int irqnum, unsigned long irqflags)
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/usb/hcd.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
|
||||
#include "usb.h"
|
||||
|
@ -188,8 +189,13 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
|
|||
* connected to.
|
||||
*/
|
||||
if (!udev->parent) {
|
||||
*handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev),
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
int raw_port_num;
|
||||
|
||||
raw_port_num = usb_hcd_find_raw_port_number(hcd,
|
||||
port_num);
|
||||
*handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev),
|
||||
raw_port_num);
|
||||
if (!*handle)
|
||||
return -ENODEV;
|
||||
} else {
|
||||
|
|
|
@ -145,6 +145,7 @@ config USB_LPC32XX
|
|||
tristate "LPC32XX USB Peripheral Controller"
|
||||
depends on ARCH_LPC32XX
|
||||
select USB_ISP1301
|
||||
select USB_OTG_UTILS
|
||||
help
|
||||
This option selects the USB device controller in the LPC32xx SoC.
|
||||
|
||||
|
|
|
@ -1214,6 +1214,7 @@ itd_urb_transaction (
|
|||
|
||||
memset (itd, 0, sizeof *itd);
|
||||
itd->itd_dma = itd_dma;
|
||||
itd->frame = 9999; /* an invalid value */
|
||||
list_add (&itd->itd_list, &sched->td_list);
|
||||
}
|
||||
spin_unlock_irqrestore (&ehci->lock, flags);
|
||||
|
@ -1915,6 +1916,7 @@ sitd_urb_transaction (
|
|||
|
||||
memset (sitd, 0, sizeof *sitd);
|
||||
sitd->sitd_dma = sitd_dma;
|
||||
sitd->frame = 9999; /* an invalid value */
|
||||
list_add (&sitd->sitd_list, &iso_sched->td_list);
|
||||
}
|
||||
|
||||
|
|
|
@ -1022,44 +1022,24 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
|
|||
* is attached to (or the roothub port its ancestor hub is attached to). All we
|
||||
* know is the index of that port under either the USB 2.0 or the USB 3.0
|
||||
* roothub, but that doesn't give us the real index into the HW port status
|
||||
* registers. Scan through the xHCI roothub port array, looking for the Nth
|
||||
* entry of the correct port speed. Return the port number of that entry.
|
||||
* registers. Call xhci_find_raw_port_number() to get real index.
|
||||
*/
|
||||
static u32 xhci_find_real_port_number(struct xhci_hcd *xhci,
|
||||
struct usb_device *udev)
|
||||
{
|
||||
struct usb_device *top_dev;
|
||||
unsigned int num_similar_speed_ports;
|
||||
unsigned int faked_port_num;
|
||||
int i;
|
||||
struct usb_hcd *hcd;
|
||||
|
||||
if (udev->speed == USB_SPEED_SUPER)
|
||||
hcd = xhci->shared_hcd;
|
||||
else
|
||||
hcd = xhci->main_hcd;
|
||||
|
||||
for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
|
||||
top_dev = top_dev->parent)
|
||||
/* Found device below root hub */;
|
||||
faked_port_num = top_dev->portnum;
|
||||
for (i = 0, num_similar_speed_ports = 0;
|
||||
i < HCS_MAX_PORTS(xhci->hcs_params1); i++) {
|
||||
u8 port_speed = xhci->port_array[i];
|
||||
|
||||
/*
|
||||
* Skip ports that don't have known speeds, or have duplicate
|
||||
* Extended Capabilities port speed entries.
|
||||
*/
|
||||
if (port_speed == 0 || port_speed == DUPLICATE_ENTRY)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* USB 3.0 ports are always under a USB 3.0 hub. USB 2.0 and
|
||||
* 1.1 ports are under the USB 2.0 hub. If the port speed
|
||||
* matches the device speed, it's a similar speed port.
|
||||
*/
|
||||
if ((port_speed == 0x03) == (udev->speed == USB_SPEED_SUPER))
|
||||
num_similar_speed_ports++;
|
||||
if (num_similar_speed_ports == faked_port_num)
|
||||
/* Roothub ports are numbered from 1 to N */
|
||||
return i+1;
|
||||
}
|
||||
return 0;
|
||||
return xhci_find_raw_port_number(hcd, top_dev->portnum);
|
||||
}
|
||||
|
||||
/* Setup an xHCI virtual device for a Set Address command */
|
||||
|
|
|
@ -313,6 +313,7 @@ static const struct hc_driver xhci_pci_hc_driver = {
|
|||
.set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm,
|
||||
.enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout,
|
||||
.disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
|
||||
.find_raw_port_number = xhci_find_raw_port_number,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
|
|
@ -1599,14 +1599,20 @@ static void handle_port_status(struct xhci_hcd *xhci,
|
|||
max_ports = HCS_MAX_PORTS(xhci->hcs_params1);
|
||||
if ((port_id <= 0) || (port_id > max_ports)) {
|
||||
xhci_warn(xhci, "Invalid port id %d\n", port_id);
|
||||
bogus_port_status = true;
|
||||
goto cleanup;
|
||||
inc_deq(xhci, xhci->event_ring);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Figure out which usb_hcd this port is attached to:
|
||||
* is it a USB 3.0 port or a USB 2.0/1.1 port?
|
||||
*/
|
||||
major_revision = xhci->port_array[port_id - 1];
|
||||
|
||||
/* Find the right roothub. */
|
||||
hcd = xhci_to_hcd(xhci);
|
||||
if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
|
||||
hcd = xhci->shared_hcd;
|
||||
|
||||
if (major_revision == 0) {
|
||||
xhci_warn(xhci, "Event for port %u not in "
|
||||
"Extended Capabilities, ignoring.\n",
|
||||
|
@ -1629,10 +1635,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
|
|||
* into the index into the ports on the correct split roothub, and the
|
||||
* correct bus_state structure.
|
||||
*/
|
||||
/* Find the right roothub. */
|
||||
hcd = xhci_to_hcd(xhci);
|
||||
if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
|
||||
hcd = xhci->shared_hcd;
|
||||
bus_state = &xhci->bus_state[hcd_index(hcd)];
|
||||
if (hcd->speed == HCD_USB3)
|
||||
port_array = xhci->usb3_ports;
|
||||
|
@ -2027,8 +2029,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|||
if (event_trb != ep_ring->dequeue &&
|
||||
event_trb != td->last_trb)
|
||||
td->urb->actual_length =
|
||||
td->urb->transfer_buffer_length
|
||||
- TRB_LEN(le32_to_cpu(event->transfer_len));
|
||||
td->urb->transfer_buffer_length -
|
||||
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
||||
else
|
||||
td->urb->actual_length = 0;
|
||||
|
||||
|
@ -2060,7 +2062,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|||
/* Maybe the event was for the data stage? */
|
||||
td->urb->actual_length =
|
||||
td->urb->transfer_buffer_length -
|
||||
TRB_LEN(le32_to_cpu(event->transfer_len));
|
||||
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
||||
xhci_dbg(xhci, "Waiting for status "
|
||||
"stage event\n");
|
||||
return 0;
|
||||
|
@ -2096,7 +2098,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|||
/* handle completion code */
|
||||
switch (trb_comp_code) {
|
||||
case COMP_SUCCESS:
|
||||
if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
|
||||
if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
|
||||
frame->status = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -2141,7 +2143,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|||
len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
|
||||
}
|
||||
len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
|
||||
TRB_LEN(le32_to_cpu(event->transfer_len));
|
||||
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
||||
|
||||
if (trb_comp_code != COMP_STOP_INVAL) {
|
||||
frame->actual_length = len;
|
||||
|
@ -2199,7 +2201,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|||
case COMP_SUCCESS:
|
||||
/* Double check that the HW transferred everything. */
|
||||
if (event_trb != td->last_trb ||
|
||||
TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
|
||||
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
|
||||
xhci_warn(xhci, "WARN Successful completion "
|
||||
"on short TX\n");
|
||||
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
|
||||
|
@ -2227,18 +2229,18 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|||
"%d bytes untransferred\n",
|
||||
td->urb->ep->desc.bEndpointAddress,
|
||||
td->urb->transfer_buffer_length,
|
||||
TRB_LEN(le32_to_cpu(event->transfer_len)));
|
||||
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
|
||||
/* Fast path - was this the last TRB in the TD for this URB? */
|
||||
if (event_trb == td->last_trb) {
|
||||
if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
|
||||
if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
|
||||
td->urb->actual_length =
|
||||
td->urb->transfer_buffer_length -
|
||||
TRB_LEN(le32_to_cpu(event->transfer_len));
|
||||
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
||||
if (td->urb->transfer_buffer_length <
|
||||
td->urb->actual_length) {
|
||||
xhci_warn(xhci, "HC gave bad length "
|
||||
"of %d bytes left\n",
|
||||
TRB_LEN(le32_to_cpu(event->transfer_len)));
|
||||
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
|
||||
td->urb->actual_length = 0;
|
||||
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
|
||||
*status = -EREMOTEIO;
|
||||
|
@ -2280,7 +2282,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|||
if (trb_comp_code != COMP_STOP_INVAL)
|
||||
td->urb->actual_length +=
|
||||
TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
|
||||
TRB_LEN(le32_to_cpu(event->transfer_len));
|
||||
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
||||
}
|
||||
|
||||
return finish_td(xhci, td, event_trb, event, ep, status, false);
|
||||
|
@ -2368,7 +2370,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|||
* transfer type
|
||||
*/
|
||||
case COMP_SUCCESS:
|
||||
if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
|
||||
if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
|
||||
break;
|
||||
if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
|
||||
trb_comp_code = COMP_SHORT_TX;
|
||||
|
@ -2461,14 +2463,21 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|||
* TD list.
|
||||
*/
|
||||
if (list_empty(&ep_ring->td_list)) {
|
||||
xhci_warn(xhci, "WARN Event TRB for slot %d ep %d "
|
||||
"with no TDs queued?\n",
|
||||
TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
|
||||
ep_index);
|
||||
xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
|
||||
(le32_to_cpu(event->flags) &
|
||||
TRB_TYPE_BITMASK)>>10);
|
||||
xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
|
||||
/*
|
||||
* A stopped endpoint may generate an extra completion
|
||||
* event if the device was suspended. Don't print
|
||||
* warnings.
|
||||
*/
|
||||
if (!(trb_comp_code == COMP_STOP ||
|
||||
trb_comp_code == COMP_STOP_INVAL)) {
|
||||
xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
|
||||
TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
|
||||
ep_index);
|
||||
xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
|
||||
(le32_to_cpu(event->flags) &
|
||||
TRB_TYPE_BITMASK)>>10);
|
||||
xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
|
||||
}
|
||||
if (ep->skip) {
|
||||
ep->skip = false;
|
||||
xhci_dbg(xhci, "td_list is empty while skip "
|
||||
|
|
|
@ -3779,6 +3779,28 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transfer the port index into real index in the HW port status
|
||||
* registers. Caculate offset between the port's PORTSC register
|
||||
* and port status base. Divide the number of per port register
|
||||
* to get the real index. The raw port number bases 1.
|
||||
*/
|
||||
int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1)
|
||||
{
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
__le32 __iomem *base_addr = &xhci->op_regs->port_status_base;
|
||||
__le32 __iomem *addr;
|
||||
int raw_port;
|
||||
|
||||
if (hcd->speed != HCD_USB3)
|
||||
addr = xhci->usb2_ports[port1 - 1];
|
||||
else
|
||||
addr = xhci->usb3_ports[port1 - 1];
|
||||
|
||||
raw_port = (addr - base_addr)/NUM_PORT_REGS + 1;
|
||||
return raw_port;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_SUSPEND
|
||||
|
||||
/* BESL to HIRD Encoding array for USB2 LPM */
|
||||
|
|
|
@ -972,6 +972,10 @@ struct xhci_transfer_event {
|
|||
__le32 flags;
|
||||
};
|
||||
|
||||
/* Transfer event TRB length bit mask */
|
||||
/* bits 0:23 */
|
||||
#define EVENT_TRB_LEN(p) ((p) & 0xffffff)
|
||||
|
||||
/** Transfer Event bit fields **/
|
||||
#define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f)
|
||||
|
||||
|
@ -1829,6 +1833,7 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
|
|||
int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
|
||||
char *buf, u16 wLength);
|
||||
int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
|
||||
int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int xhci_bus_suspend(struct usb_hcd *hcd);
|
||||
|
|
|
@ -38,6 +38,7 @@ config USB_ISP1301
|
|||
tristate "NXP ISP1301 USB transceiver support"
|
||||
depends on USB || USB_GADGET
|
||||
depends on I2C
|
||||
select USB_OTG_UTILS
|
||||
help
|
||||
Say Y here to add support for the NXP ISP1301 USB transceiver driver.
|
||||
This chip is typically used as USB transceiver for USB host, gadget
|
||||
|
|
|
@ -640,6 +640,7 @@ static struct usb_device_id id_table_combined [] = {
|
|||
{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
|
||||
{ USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) },
|
||||
{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
|
||||
{ USB_DEVICE(MITSUBISHI_VID, MITSUBISHI_FXUSB_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
|
||||
|
|
|
@ -583,6 +583,13 @@
|
|||
#define CONTEC_VID 0x06CE /* Vendor ID */
|
||||
#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
|
||||
|
||||
/*
|
||||
* Mitsubishi Electric Corp. (http://www.meau.com)
|
||||
* Submitted by Konstantin Holoborodko
|
||||
*/
|
||||
#define MITSUBISHI_VID 0x06D3
|
||||
#define MITSUBISHI_FXUSB_PID 0x0284 /* USB/RS422 converters: FX-USB-AW/-BD */
|
||||
|
||||
/*
|
||||
* Definitions for B&B Electronics products.
|
||||
*/
|
||||
|
|
|
@ -903,6 +903,7 @@ static int usb_serial_probe(struct usb_interface *interface,
|
|||
port->port.ops = &serial_port_ops;
|
||||
port->serial = serial;
|
||||
spin_lock_init(&port->lock);
|
||||
init_waitqueue_head(&port->delta_msr_wait);
|
||||
/* Keep this for private driver use for the moment but
|
||||
should probably go away */
|
||||
INIT_WORK(&port->work, usb_serial_port_work);
|
||||
|
|
|
@ -357,6 +357,7 @@ struct hc_driver {
|
|||
*/
|
||||
int (*disable_usb3_lpm_timeout)(struct usb_hcd *,
|
||||
struct usb_device *, enum usb3_link_state state);
|
||||
int (*find_raw_port_number)(struct usb_hcd *, int);
|
||||
};
|
||||
|
||||
extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
|
||||
|
@ -396,6 +397,7 @@ extern int usb_hcd_is_primary_hcd(struct usb_hcd *hcd);
|
|||
extern int usb_add_hcd(struct usb_hcd *hcd,
|
||||
unsigned int irqnum, unsigned long irqflags);
|
||||
extern void usb_remove_hcd(struct usb_hcd *hcd);
|
||||
extern int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1);
|
||||
|
||||
struct platform_device;
|
||||
extern void usb_hcd_platform_shutdown(struct platform_device *dev);
|
||||
|
|
Загрузка…
Ссылка в новой задаче