Skip to content
Snippets Groups Projects
Commit 44dbc330 authored by Hans de Goede's avatar Hans de Goede Committed by Simon Glass
Browse files

usb: ohci: Do not reuse ed for interrupt endpoints of different devices


When submitting interrupt packets to an endpoint we only link in the ed
once to avoid some races surrounding unlinking of periodic endpoints,
but we share one ohci_device struct / one set of ed-s for all devices,
which means that if we have an interrupt endpoint at endpoint 1 with one
device, and a non interrupt endpoint 1 with another device we end up
with the same ed linked into both the periodic and async lists, which is
not good (tm).

This commit switches over to using separate ohci_device structs, and thus
separate ed-s for devices with interrupt endpoints, fixing this.

This fixes e.g. matching a usb storage device and keyboard on the same
usb-1 hub not working.

Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Reviewed-by: default avatarMarek Vasut <marex@denx.de>
parent 3a812e7c
No related branches found
No related tags found
No related merge requests found
...@@ -1478,6 +1478,31 @@ pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, ...@@ -1478,6 +1478,31 @@ pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len,
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static ohci_dev_t *ohci_get_ohci_dev(ohci_t *ohci, int devnum, int intr)
{
int i;
if (!intr)
return &ohci->ohci_dev;
/* First see if we already have an ohci_dev for this dev. */
for (i = 0; i < NUM_INT_DEVS; i++) {
if (ohci->int_dev[i].devnum == devnum)
return &ohci->int_dev[i];
}
/* If not then find a free one. */
for (i = 0; i < NUM_INT_DEVS; i++) {
if (ohci->int_dev[i].devnum == -1) {
ohci->int_dev[i].devnum = devnum;
return &ohci->int_dev[i];
}
}
printf("ohci: Error out of ohci_devs for interrupt endpoints\n");
return NULL;
}
/* common code for handling submit messages - used for all but root hub */ /* common code for handling submit messages - used for all but root hub */
/* accesses. */ /* accesses. */
static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, static int submit_common_msg(ohci_t *ohci, struct usb_device *dev,
...@@ -1488,6 +1513,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, ...@@ -1488,6 +1513,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev,
int maxsize = usb_maxpacket(dev, pipe); int maxsize = usb_maxpacket(dev, pipe);
int timeout; int timeout;
urb_priv_t *urb; urb_priv_t *urb;
ohci_dev_t *ohci_dev;
urb = malloc(sizeof(urb_priv_t)); urb = malloc(sizeof(urb_priv_t));
memset(urb, 0, sizeof(urb_priv_t)); memset(urb, 0, sizeof(urb_priv_t));
...@@ -1511,7 +1537,11 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, ...@@ -1511,7 +1537,11 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev,
return -1; return -1;
} }
if (sohci_submit_job(ohci, &ohci->ohci_dev, urb, setup) < 0) { ohci_dev = ohci_get_ohci_dev(ohci, dev->devnum, usb_pipeint(pipe));
if (!ohci_dev)
return -ENOMEM;
if (sohci_submit_job(ohci, ohci_dev, urb, setup) < 0) {
err("sohci_submit_job failed"); err("sohci_submit_job failed");
return -1; return -1;
} }
...@@ -1711,8 +1741,11 @@ static int hc_start(ohci_t *ohci) ...@@ -1711,8 +1741,11 @@ static int hc_start(ohci_t *ohci)
{ {
__u32 mask; __u32 mask;
unsigned int fminterval; unsigned int fminterval;
int i;
ohci->disabled = 1; ohci->disabled = 1;
for (i = 0; i < NUM_INT_DEVS; i++)
ohci->int_dev[i].devnum = -1;
/* Tell the controller where the control and bulk lists are /* Tell the controller where the control and bulk lists are
* The lists are empty now. */ * The lists are empty now. */
......
...@@ -367,10 +367,13 @@ typedef struct ...@@ -367,10 +367,13 @@ typedef struct
#define NUM_TD 64 /* we need more TDs than EDs */ #define NUM_TD 64 /* we need more TDs than EDs */
#define NUM_INT_DEVS 8 /* num of ohci_dev structs for int endpoints */
typedef struct ohci_device { typedef struct ohci_device {
ed_t ed[NUM_EDS] __aligned(ED_ALIGNMENT); ed_t ed[NUM_EDS] __aligned(ED_ALIGNMENT);
td_t tds[NUM_TD] __aligned(TD_ALIGNMENT); td_t tds[NUM_TD] __aligned(TD_ALIGNMENT);
int ed_cnt; int ed_cnt;
int devnum;
} ohci_dev_t; } ohci_dev_t;
/* /*
...@@ -384,6 +387,7 @@ typedef struct ohci_device { ...@@ -384,6 +387,7 @@ typedef struct ohci_device {
typedef struct ohci { typedef struct ohci {
/* this allocates EDs for all possible endpoints */ /* this allocates EDs for all possible endpoints */
struct ohci_device ohci_dev __aligned(TD_ALIGNMENT); struct ohci_device ohci_dev __aligned(TD_ALIGNMENT);
struct ohci_device int_dev[NUM_INT_DEVS] __aligned(TD_ALIGNMENT);
struct ohci_hcca *hcca; /* hcca */ struct ohci_hcca *hcca; /* hcca */
/*dma_addr_t hcca_dma;*/ /*dma_addr_t hcca_dma;*/
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment