mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	usb: renesas_usbhs: gadget: fix re-enabling pipe without re-connecting
This patch fixes an issue that the renesas_usbhs driver in gadget mode cannot work correctly even if I disabled DMAC of the driver when I used the g_zero driver and the testusb tool. When a usb cable is re-connected, the renesas_usbhs driver calls the usbhsp_flags_init() (via usbhs_hotplug() --> usbhs_mod_call(start) --> usbhsg_try_start() --> usbhs_pipe_init()). However, the driver doesn't call the usbhsp_flags_init() when usbhsg_ep_disable() is called. So, if a gadget driver calls usb_ep_enable() and usb_ep_disable() again and again, the renesas_usbhs driver will output the following log: renesas_usbhs renesas_usbhs: can't get pipe (BULK) renesas_usbhs renesas_usbhs: wrong recip request Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
		
							parent
							
								
									6a0541599f
								
							
						
					
					
						commit
						dfb87b8bfe
					
				
					 3 changed files with 13 additions and 0 deletions
				
			
		| 
						 | 
					@ -600,8 +600,10 @@ static int usbhsg_ep_enable(struct usb_ep *ep,
 | 
				
			||||||
static int usbhsg_ep_disable(struct usb_ep *ep)
 | 
					static int usbhsg_ep_disable(struct usb_ep *ep)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
 | 
						struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
 | 
				
			||||||
 | 
						struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	usbhsg_pipe_disable(uep);
 | 
						usbhsg_pipe_disable(uep);
 | 
				
			||||||
 | 
						usbhs_pipe_free(pipe);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uep->pipe->mod_private	= NULL;
 | 
						uep->pipe->mod_private	= NULL;
 | 
				
			||||||
	uep->pipe		= NULL;
 | 
						uep->pipe		= NULL;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -640,6 +640,11 @@ static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type)
 | 
				
			||||||
	return pipe;
 | 
						return pipe;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void usbhsp_put_pipe(struct usbhs_pipe *pipe)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						usbhsp_flags_init(pipe);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void usbhs_pipe_init(struct usbhs_priv *priv,
 | 
					void usbhs_pipe_init(struct usbhs_priv *priv,
 | 
				
			||||||
		     int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map))
 | 
							     int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map))
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -727,6 +732,11 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
 | 
				
			||||||
	return pipe;
 | 
						return pipe;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usbhs_pipe_free(struct usbhs_pipe *pipe)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						usbhsp_put_pipe(pipe);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo)
 | 
					void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (pipe->fifo)
 | 
						if (pipe->fifo)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,6 +75,7 @@ struct usbhs_pipe_info {
 | 
				
			||||||
char *usbhs_pipe_name(struct usbhs_pipe *pipe);
 | 
					char *usbhs_pipe_name(struct usbhs_pipe *pipe);
 | 
				
			||||||
struct usbhs_pipe
 | 
					struct usbhs_pipe
 | 
				
			||||||
*usbhs_pipe_malloc(struct usbhs_priv *priv, int endpoint_type, int dir_in);
 | 
					*usbhs_pipe_malloc(struct usbhs_priv *priv, int endpoint_type, int dir_in);
 | 
				
			||||||
 | 
					void usbhs_pipe_free(struct usbhs_pipe *pipe);
 | 
				
			||||||
int usbhs_pipe_probe(struct usbhs_priv *priv);
 | 
					int usbhs_pipe_probe(struct usbhs_priv *priv);
 | 
				
			||||||
void usbhs_pipe_remove(struct usbhs_priv *priv);
 | 
					void usbhs_pipe_remove(struct usbhs_priv *priv);
 | 
				
			||||||
int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe);
 | 
					int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue