From: Craig W. Nadler <[EMAIL PROTECTED]>
EHCI_HUB_CTRL: Fixes a bug with setting the value of the port number.
The ehci_hub_control() function in driver/usb/host/ehci-hub.c takes a u16 parameter
called wIndex. The least significant byte of this parameter holds the port number
relevant to the function call. The other byte in wIndex is sometimes used to hold
another value. A pointer to the port_status register for the relevant port was
being set using wIndex as a subscript to an array without masking off the other
byte. This patch adds a local unsigned variable called port_num which is set to
((wIndex & 0xFF) - 1). The pointer for the port_status register is then set
using port_num as the subscript. Port_num is also used anywhere in
ehci_hub_control() where wIndex contains the port number.
Signed-off-by: Craig W. Nadler <[EMAIL PROTECTED]>
---
diff -uprN a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
--- a/drivers/usb/host/ehci-hub.c 2007-06-07 17:27:31.000000000 -0400
+++ b/drivers/usb/host/ehci-hub.c 2007-06-11 18:28:30.000000000 -0400
@@ -444,11 +444,12 @@ static int ehci_hub_control (
) {
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
int ports = HCS_N_PORTS (ehci->hcs_params);
- u32 __iomem *status_reg = &ehci->regs->port_status[wIndex - 1];
+ unsigned port_num = (wIndex & 0xFF) - 1;
+ unsigned selector = (wIndex >> 8) & 0xFF;
+ u32 __iomem *status_reg = &ehci->regs->port_status[port_num];
u32 temp, status;
unsigned long flags;
int retval = 0;
- unsigned selector;
/*
* FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR.
@@ -470,9 +471,8 @@ static int ehci_hub_control (
}
break;
case ClearPortFeature:
- if (!wIndex || wIndex > ports)
+ if (port_num >= ports)
goto error;
- wIndex--;
temp = ehci_readl(ehci, status_reg);
/*
@@ -502,7 +502,7 @@ static int ehci_hub_control (
temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
ehci_writel(ehci, temp | PORT_RESUME,
status_reg);
- ehci->reset_done [wIndex] = jiffies
+ ehci->reset_done[port_num] = jiffies
+ msecs_to_jiffies (20);
}
break;
@@ -541,9 +541,8 @@ static int ehci_hub_control (
//cpu_to_le32s ((u32 *) buf);
break;
case GetPortStatus:
- if (!wIndex || wIndex > ports)
+ if (port_num >= ports)
goto error;
- wIndex--;
status = 0;
temp = ehci_readl(ehci, status_reg);
@@ -559,20 +558,20 @@ static int ehci_hub_control (
if (temp & PORT_RESUME) {
/* Remote Wakeup received? */
- if (!ehci->reset_done[wIndex]) {
+ if (!ehci->reset_done[port_num]) {
/* resume signaling for 20 msec */
- ehci->reset_done[wIndex] = jiffies
+ ehci->reset_done[port_num] = jiffies
+ msecs_to_jiffies(20);
/* check the port again */
mod_timer(&ehci_to_hcd(ehci)->rh_timer,
- ehci->reset_done[wIndex]);
+ ehci->reset_done[port_num]);
}
/* resume completed? */
else if (time_after_eq(jiffies,
- ehci->reset_done[wIndex])) {
+ ehci->reset_done[port_num])) {
status |= 1 << USB_PORT_FEAT_C_SUSPEND;
- ehci->reset_done[wIndex] = 0;
+ ehci->reset_done[port_num] = 0;
/* stop resume signaling */
temp = ehci_readl(ehci, status_reg);
@@ -584,7 +583,7 @@ static int ehci_hub_control (
if (retval != 0) {
ehci_err(ehci,
"port %d resume error %d\n",
- wIndex + 1, retval);
+ port_num + 1, retval);
goto error;
}
temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
@@ -594,9 +593,9 @@ static int ehci_hub_control (
/* whoever resets must GetPortStatus to complete it!! */
if ((temp & PORT_RESET)
&& time_after_eq(jiffies,
- ehci->reset_done[wIndex])) {
+ ehci->reset_done[port_num])) {
status |= 1 << USB_PORT_FEAT_C_RESET;
- ehci->reset_done [wIndex] = 0;
+ ehci->reset_done[port_num] = 0;
/* force reset to complete */
ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET),
@@ -608,22 +607,22 @@ static int ehci_hub_control (
PORT_RESET, 0, 750);
if (retval != 0) {
ehci_err (ehci, "port %d reset error %d\n",
- wIndex + 1, retval);
+ port_num + 1, retval);
goto error;
}
/* see what we found out */
- temp = check_reset_complete (ehci, wIndex, status_reg,
+ temp = check_reset_complete (ehci, port_num, status_reg,
ehci_readl(ehci, status_reg));
}
/* transfer dedicated ports to the companion hc */
if ((temp & PORT_CONNECT) &&
- test_bit(wIndex, &ehci->companion_ports)) {
+ test_bit(port_num, &ehci->companion_ports)) {
temp &= ~PORT_RWC_BITS;
temp |= PORT_OWNER;
ehci_writel(ehci, temp, status_reg);
- ehci_dbg(ehci, "port %d --> companion\n", wIndex + 1);
+ ehci_dbg(ehci, "port %d --> companion\n", port_num + 1);
temp = ehci_readl(ehci, status_reg);
}
@@ -652,7 +651,7 @@ static int ehci_hub_control (
#ifndef EHCI_VERBOSE_DEBUG
if (status & ~0xffff) /* only if wPortChange is interesting */
#endif
- dbg_port (ehci, "GetStatus", wIndex + 1, temp);
+ dbg_port (ehci, "GetStatus", port_num + 1, temp);
put_unaligned(cpu_to_le32 (status), (__le32 *) buf);
break;
case SetHubFeature:
@@ -666,11 +665,8 @@ static int ehci_hub_control (
}
break;
case SetPortFeature:
- selector = wIndex >> 8;
- wIndex &= 0xff;
- if (!wIndex || wIndex > ports)
+ if (port_num >= ports)
goto error;
- wIndex--;
temp = ehci_readl(ehci, status_reg);
if (temp & PORT_OWNER)
break;
@@ -704,10 +700,11 @@ static int ehci_hub_control (
&& PORT_USB11 (temp)) {
ehci_dbg (ehci,
"port %d low speed --> companion\n",
- wIndex + 1);
+ port_num + 1);
temp |= PORT_OWNER;
} else {
- ehci_vdbg (ehci, "port %d reset\n", wIndex + 1);
+ ehci_vdbg (ehci, "port %d reset\n",
+ port_num + 1);
temp |= PORT_RESET;
temp &= ~PORT_PE;
@@ -715,7 +712,7 @@ static int ehci_hub_control (
* caller must wait, then call GetPortStatus
* usb 2.0 spec says 50 ms resets on root
*/
- ehci->reset_done [wIndex] = jiffies
+ ehci->reset_done[port_num] = jiffies
+ msecs_to_jiffies (50);
}
ehci_writel(ehci, temp, status_reg);
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel