Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a3e2055 authored by Deng-Cheng Zhu's avatar Deng-Cheng Zhu Committed by Greg Kroah-Hartman
Browse files

USB/host: Bugfix: Return length of copied buffer in uhci_hub_control()



In addition to the error statuses -ETIMEDOUT and -EPIPE, uhci_hub_control()
needs to return the length of copied buffer when appropriate, so that the
returned status of ->hub_control() in rh_call_control() in the USB core
HCD can be properly handled.

This patch also removes the OK() macro to make the code more readable.

Reviewed-by: default avatarJames Hogan <james.hogan@imgtec.com>
Signed-off-by: default avatarDeng-Cheng Zhu <dengcheng.zhu@imgtec.com>
Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent cae9160d
Loading
Loading
Loading
Loading
+20 −20
Original line number Diff line number Diff line
@@ -75,8 +75,6 @@ static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)
	return !!*buf;
}

#define OK(x)			len = (x); break

#define CLR_RH_PORTSTAT(x) \
	status = uhci_readw(uhci, port_addr);	\
	status &= ~(RWC_BITS|WZ_BITS); \
@@ -244,7 +242,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
			u16 wIndex, char *buf, u16 wLength)
{
	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
	int status, lstatus, retval = 0, len = 0;
	int status, lstatus, retval = 0;
	unsigned int port = wIndex - 1;
	unsigned long port_addr = USBPORTSC1 + 2 * port;
	u16 wPortChange, wPortStatus;
@@ -258,7 +256,8 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,

	case GetHubStatus:
		*(__le32 *)buf = cpu_to_le32(0);
		OK(4);		/* hub power */
		retval = 4; /* hub power */
		break;
	case GetPortStatus:
		if (port >= uhci->rh_numports)
			goto err;
@@ -311,13 +310,14 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,

		*(__le16 *)buf = cpu_to_le16(wPortStatus);
		*(__le16 *)(buf + 2) = cpu_to_le16(wPortChange);
		OK(4);
		retval = 4;
		break;
	case SetHubFeature:		/* We don't implement these */
	case ClearHubFeature:
		switch (wValue) {
		case C_HUB_OVER_CURRENT:
		case C_HUB_LOCAL_POWER:
			OK(0);
			break;
		default:
			goto err;
		}
@@ -329,7 +329,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
		switch (wValue) {
		case USB_PORT_FEAT_SUSPEND:
			SET_RH_PORTSTAT(USBPORTSC_SUSP);
			OK(0);
			break;
		case USB_PORT_FEAT_RESET:
			SET_RH_PORTSTAT(USBPORTSC_PR);

@@ -338,10 +338,10 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,

			/* USB v2.0 7.1.7.5 */
			uhci->ports_timeout = jiffies + msecs_to_jiffies(50);
			OK(0);
			break;
		case USB_PORT_FEAT_POWER:
			/* UHCI has no power switching */
			OK(0);
			break;
		default:
			goto err;
		}
@@ -356,10 +356,10 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,

			/* Disable terminates Resume signalling */
			uhci_finish_suspend(uhci, port, port_addr);
			OK(0);
			break;
		case USB_PORT_FEAT_C_ENABLE:
			CLR_RH_PORTSTAT(USBPORTSC_PEC);
			OK(0);
			break;
		case USB_PORT_FEAT_SUSPEND:
			if (!(uhci_readw(uhci, port_addr) & USBPORTSC_SUSP)) {

@@ -382,32 +382,32 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
					uhci->ports_timeout = jiffies +
						msecs_to_jiffies(20);
			}
			OK(0);
			break;
		case USB_PORT_FEAT_C_SUSPEND:
			clear_bit(port, &uhci->port_c_suspend);
			OK(0);
			break;
		case USB_PORT_FEAT_POWER:
			/* UHCI has no power switching */
			goto err;
		case USB_PORT_FEAT_C_CONNECTION:
			CLR_RH_PORTSTAT(USBPORTSC_CSC);
			OK(0);
			break;
		case USB_PORT_FEAT_C_OVER_CURRENT:
			CLR_RH_PORTSTAT(USBPORTSC_OCC);
			OK(0);
			break;
		case USB_PORT_FEAT_C_RESET:
			/* this driver won't report these */
			OK(0);
			break;
		default:
			goto err;
		}
		break;
	case GetHubDescriptor:
		len = min_t(unsigned int, sizeof(root_hub_hub_des), wLength);
		memcpy(buf, root_hub_hub_des, len);
		if (len > 2)
		retval = min_t(unsigned int, sizeof(root_hub_hub_des), wLength);
		memcpy(buf, root_hub_hub_des, retval);
		if (retval > 2)
			buf[2] = uhci->rh_numports;
		OK(len);
		break;
	default:
err:
		retval = -EPIPE;