forked from mirrors/linux
		
	USB: chipidea: re-order irq handling to avoid unhandled irqs
- let role driver handle irq before ID change check; this gives the role driver a chance to handle disconnect; - disable irq during switch role; no role driver to handle irq in the period. Tested-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Tested-by: Marc Kleine-Budde <mkl@pengutronix.de> Signed-off-by: Richard Zhao <richard.zhao@freescale.com> Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									388ed48723
								
							
						
					
					
						commit
						b183c19f98
					
				
					 1 changed files with 13 additions and 8 deletions
				
			
		| 
						 | 
				
			
			@ -279,6 +279,7 @@ static void ci_role_work(struct work_struct *work)
 | 
			
		|||
 | 
			
		||||
		ci_role_stop(ci);
 | 
			
		||||
		ci_role_start(ci, role);
 | 
			
		||||
		enable_irq(ci->irq);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -318,18 +319,22 @@ static irqreturn_t ci_irq(int irq, void *data)
 | 
			
		|||
{
 | 
			
		||||
	struct ci13xxx *ci = data;
 | 
			
		||||
	irqreturn_t ret = IRQ_NONE;
 | 
			
		||||
	u32 otgsc = 0;
 | 
			
		||||
 | 
			
		||||
	if (ci->is_otg) {
 | 
			
		||||
		u32 sts = hw_read(ci, OP_OTGSC, ~0);
 | 
			
		||||
	if (ci->is_otg)
 | 
			
		||||
		otgsc = hw_read(ci, OP_OTGSC, ~0);
 | 
			
		||||
 | 
			
		||||
		if (sts & OTGSC_IDIS) {
 | 
			
		||||
			hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS);
 | 
			
		||||
			queue_work(ci->wq, &ci->work);
 | 
			
		||||
			ret = IRQ_HANDLED;
 | 
			
		||||
		}
 | 
			
		||||
	if (ci->role != CI_ROLE_END)
 | 
			
		||||
		ret = ci_role(ci)->irq(ci);
 | 
			
		||||
 | 
			
		||||
	if (ci->is_otg && (otgsc & OTGSC_IDIS)) {
 | 
			
		||||
		hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS);
 | 
			
		||||
		disable_irq_nosync(ci->irq);
 | 
			
		||||
		queue_work(ci->wq, &ci->work);
 | 
			
		||||
		ret = IRQ_HANDLED;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static DEFINE_IDA(ci_ida);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue