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: James Hogan <james.hogan@imgtec.com> Signed-off-by: Deng-Cheng Zhu <dengcheng.zhu@imgtec.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
					parent
					
						
							
								cae9160d9b
							
						
					
				
			
			
				commit
				
					
						5a3e2055c5
					
				
			
		
					 1 changed files with 20 additions and 20 deletions
				
			
		|  | @ -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; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Deng-Cheng Zhu
				Deng-Cheng Zhu