be2net: fix a possible events_get() race on BE2
On BE2 chip, an interrupt being raised even when EQ is in un-armed state has been observed a few times. This is not expected and has never been observed on BE3/Lancer chips. As a consequence, be_msix()::events_get() and be_poll()::events_get() can race and notify an EQ wrongly causing a CEV UE. The other possible side-effect would be traffic stalling because after notifying EQ, napi_schedule() is ignored as NAPI is already running. This patch fixes this issue by counting events only in be_poll(). Signed-off-by: Sathya Perla <sathya.perla@emulex.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
					parent
					
						
							
								9ce99cf6dc
							
						
					
				
			
			
				commit
				
					
						0b545a6291
					
				
			
		
					 1 changed files with 7 additions and 4 deletions
				
			
		|  | @ -2029,7 +2029,8 @@ static irqreturn_t be_msix(int irq, void *dev) | |||
| { | ||||
| 	struct be_eq_obj *eqo = dev; | ||||
| 
 | ||||
| 	event_handle(eqo); | ||||
| 	be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0); | ||||
| 	napi_schedule(&eqo->napi); | ||||
| 	return IRQ_HANDLED; | ||||
| } | ||||
| 
 | ||||
|  | @ -2125,9 +2126,11 @@ int be_poll(struct napi_struct *napi, int budget) | |||
| { | ||||
| 	struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi); | ||||
| 	struct be_adapter *adapter = eqo->adapter; | ||||
| 	int max_work = 0, work, i; | ||||
| 	int max_work = 0, work, i, num_evts; | ||||
| 	bool tx_done; | ||||
| 
 | ||||
| 	num_evts = events_get(eqo); | ||||
| 
 | ||||
| 	/* Process all TXQs serviced by this EQ */ | ||||
| 	for (i = eqo->idx; i < adapter->num_tx_qs; i += adapter->num_evt_qs) { | ||||
| 		tx_done = be_process_tx(adapter, &adapter->tx_obj[i], | ||||
|  | @ -2150,10 +2153,10 @@ int be_poll(struct napi_struct *napi, int budget) | |||
| 
 | ||||
| 	if (max_work < budget) { | ||||
| 		napi_complete(napi); | ||||
| 		be_eq_notify(adapter, eqo->q.id, true, false, 0); | ||||
| 		be_eq_notify(adapter, eqo->q.id, true, false, num_evts); | ||||
| 	} else { | ||||
| 		/* As we'll continue in polling mode, count and clear events */ | ||||
| 		be_eq_notify(adapter, eqo->q.id, false, false, events_get(eqo)); | ||||
| 		be_eq_notify(adapter, eqo->q.id, false, false, num_evts); | ||||
| 	} | ||||
| 	return max_work; | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Sathya Perla
				Sathya Perla