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_stop(ci);
 | 
				
			||||||
		ci_role_start(ci, role);
 | 
							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;
 | 
						struct ci13xxx *ci = data;
 | 
				
			||||||
	irqreturn_t ret = IRQ_NONE;
 | 
						irqreturn_t ret = IRQ_NONE;
 | 
				
			||||||
 | 
						u32 otgsc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ci->is_otg) {
 | 
						if (ci->is_otg)
 | 
				
			||||||
		u32 sts = hw_read(ci, OP_OTGSC, ~0);
 | 
							otgsc = hw_read(ci, OP_OTGSC, ~0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (sts & OTGSC_IDIS) {
 | 
						if (ci->role != CI_ROLE_END)
 | 
				
			||||||
			hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS);
 | 
							ret = ci_role(ci)->irq(ci);
 | 
				
			||||||
			queue_work(ci->wq, &ci->work);
 | 
					
 | 
				
			||||||
			ret = IRQ_HANDLED;
 | 
						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);
 | 
					static DEFINE_IDA(ci_ida);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue