From patchwork Wed May 13 12:42:15 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 471853 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 20323140663 for ; Wed, 13 May 2015 22:42:52 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id EA0B04B6EF; Wed, 13 May 2015 14:42:46 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id hPcDerKruK-l; Wed, 13 May 2015 14:42:46 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B120C4B6FC; Wed, 13 May 2015 14:42:37 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id AB11F4B6D1 for ; Wed, 13 May 2015 14:42:30 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id yiNN5EZLIKWl for ; Wed, 13 May 2015 14:42:30 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by theia.denx.de (Postfix) with ESMTPS id 3013F4B6C6 for ; Wed, 13 May 2015 14:42:28 +0200 (CEST) Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t4DCgL4t024076 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 13 May 2015 08:42:21 -0400 Received: from shalem.localdomain.com (vpn1-6-133.ams2.redhat.com [10.36.6.133]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t4DCgJwb011550; Wed, 13 May 2015 08:42:19 -0400 From: Hans de Goede To: Simon Glass , Marek Vasut Date: Wed, 13 May 2015 14:42:15 +0200 Message-Id: <1431520938-29950-1-git-send-email-hdegoede@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 Cc: u-boot@lists.denx.de Subject: [U-Boot] [PATCH v2 1/4] usb: ohci: Do not reuse ed for interrupt endpoints of different devices X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" 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: Hans de Goede Reviewed-by: Marek Vasut --- drivers/usb/host/ohci-hcd.c | 35 ++++++++++++++++++++++++++++++++++- drivers/usb/host/ohci.h | 4 ++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 2f976d2..5364ced 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -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 */ /* accesses. */ 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 timeout; urb_priv_t *urb; + ohci_dev_t *ohci_dev; urb = malloc(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, 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"); return -1; } @@ -1711,8 +1741,11 @@ static int hc_start(ohci_t *ohci) { __u32 mask; unsigned int fminterval; + int i; 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 * The lists are empty now. */ diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 3f9869b..f1526d4 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -367,10 +367,13 @@ typedef struct #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 { ed_t ed[NUM_EDS] __aligned(ED_ALIGNMENT); td_t tds[NUM_TD] __aligned(TD_ALIGNMENT); int ed_cnt; + int devnum; } ohci_dev_t; /* @@ -384,6 +387,7 @@ typedef struct ohci_device { typedef struct ohci { /* this allocates EDs for all possible endpoints */ struct ohci_device ohci_dev __aligned(TD_ALIGNMENT); + struct ohci_device int_dev[NUM_INT_DEVS] __aligned(TD_ALIGNMENT); struct ohci_hcca *hcca; /* hcca */ /*dma_addr_t hcca_dma;*/