This version of the patch is against kernel 2.6.22-rc5 and has been checked with scripts/checkpatch.pl and sparse.

Craig
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 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-21 13:54:41.000000000 -0400
+++ b/drivers/usb/host/ehci-hub.c	2007-06-21 15:40:11.000000000 -0400
@@ -448,11 +448,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.
@@ -474,9 +475,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);
 
 		/*
@@ -506,7 +506,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;
@@ -545,9 +545,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);
 
@@ -563,20 +562,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);
@@ -588,7 +587,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));
@@ -598,9 +597,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),
@@ -612,22 +611,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);
 		}
 
@@ -656,7 +655,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:
@@ -670,11 +669,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;
@@ -708,10 +704,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;
 
@@ -719,7 +716,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

Reply via email to