RDMA/nes: Fix hangs on ifdown
When ib_unregister_device() is called from netdev stop during ifdown, it sometimes hangs. Changes made to indicate port_err to ib_dispatch_event() during netdev stop and port_active during netdev open. The ib_unregister_device() is only called during remove of the module. Signed-off-by: Faisal Latif <faisal.latif@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
		
					parent
					
						
							
								0eec495ee6
							
						
					
				
			
			
				commit
				
					
						cd6860eb03
					
				
			
		
					 4 changed files with 33 additions and 6 deletions
				
			
		|  | @ -262,6 +262,7 @@ struct nes_device { | ||||||
| 	u16                    base_doorbell_index; | 	u16                    base_doorbell_index; | ||||||
| 	u16                    currcq_count; | 	u16                    currcq_count; | ||||||
| 	u16                    deepcq_count; | 	u16                    deepcq_count; | ||||||
|  | 	u8                     iw_status; | ||||||
| 	u8                     msi_enabled; | 	u8                     msi_enabled; | ||||||
| 	u8                     netdev_count; | 	u8                     netdev_count; | ||||||
| 	u8                     napi_isr_ran; | 	u8                     napi_isr_ran; | ||||||
|  | @ -527,6 +528,7 @@ void nes_cm_disconn_worker(void *); | ||||||
| int nes_hw_modify_qp(struct nes_device *, struct nes_qp *, u32, u32, u32); | int nes_hw_modify_qp(struct nes_device *, struct nes_qp *, u32, u32, u32); | ||||||
| int nes_modify_qp(struct ib_qp *, struct ib_qp_attr *, int, struct ib_udata *); | int nes_modify_qp(struct ib_qp *, struct ib_qp_attr *, int, struct ib_udata *); | ||||||
| struct nes_ib_device *nes_init_ofa_device(struct net_device *); | struct nes_ib_device *nes_init_ofa_device(struct net_device *); | ||||||
|  | void  nes_port_ibevent(struct nes_vnic *nesvnic); | ||||||
| void nes_destroy_ofa_device(struct nes_ib_device *); | void nes_destroy_ofa_device(struct nes_ib_device *); | ||||||
| int nes_register_ofa_device(struct nes_ib_device *); | int nes_register_ofa_device(struct nes_ib_device *); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3283,9 +3283,15 @@ static void nes_terminate_connection(struct nes_device *nesdev, struct nes_qp *n | ||||||
| 	else | 	else | ||||||
| 		mod_qp_flags |= NES_CQP_QP_TERM_DONT_SEND_TERM_MSG; | 		mod_qp_flags |= NES_CQP_QP_TERM_DONT_SEND_TERM_MSG; | ||||||
| 
 | 
 | ||||||
| 	nes_terminate_start_timer(nesqp); | 	if (!nesdev->iw_status)  { | ||||||
| 	nesqp->term_flags |= NES_TERM_SENT; | 		nesqp->term_flags = NES_TERM_DONE; | ||||||
| 	nes_hw_modify_qp(nesdev, nesqp, mod_qp_flags, termlen, 0); | 		nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_ERROR, 0, 0); | ||||||
|  | 		nes_cm_disconn(nesqp); | ||||||
|  | 	} else { | ||||||
|  | 		nes_terminate_start_timer(nesqp); | ||||||
|  | 		nesqp->term_flags |= NES_TERM_SENT; | ||||||
|  | 		nes_hw_modify_qp(nesdev, nesqp, mod_qp_flags, termlen, 0); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void nes_terminate_send_fin(struct nes_device *nesdev, | static void nes_terminate_send_fin(struct nes_device *nesdev, | ||||||
|  |  | ||||||
|  | @ -232,6 +232,13 @@ static int nes_netdev_open(struct net_device *netdev) | ||||||
| 				NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); | 				NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); | ||||||
| 		first_nesvnic = nesvnic; | 		first_nesvnic = nesvnic; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	if (nesvnic->of_device_registered) { | ||||||
|  | 		nesdev->iw_status = 1; | ||||||
|  | 		nesdev->nesadapter->send_term_ok = 1; | ||||||
|  | 		nes_port_ibevent(nesvnic); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if (first_nesvnic->linkup) { | 	if (first_nesvnic->linkup) { | ||||||
| 		/* Enable network packets */ | 		/* Enable network packets */ | ||||||
| 		nesvnic->linkup = 1; | 		nesvnic->linkup = 1; | ||||||
|  | @ -309,9 +316,9 @@ static int nes_netdev_stop(struct net_device *netdev) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	if (nesvnic->of_device_registered) { | 	if (nesvnic->of_device_registered) { | ||||||
| 		nes_destroy_ofa_device(nesvnic->nesibdev); | 		nesdev->nesadapter->send_term_ok = 0; | ||||||
| 		nesvnic->nesibdev = NULL; | 		nesdev->iw_status = 0; | ||||||
| 		nesvnic->of_device_registered = 0; | 		nes_port_ibevent(nesvnic); | ||||||
| 	} | 	} | ||||||
| 	nes_destroy_nic_qp(nesvnic); | 	nes_destroy_nic_qp(nesvnic); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3058,6 +3058,7 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | ||||||
| 						nesqp->hte_added = 0; | 						nesqp->hte_added = 0; | ||||||
| 					} | 					} | ||||||
| 				if ((nesqp->hw_tcp_state > NES_AEQE_TCP_STATE_CLOSED) && | 				if ((nesqp->hw_tcp_state > NES_AEQE_TCP_STATE_CLOSED) && | ||||||
|  | 						(nesdev->iw_status) && | ||||||
| 						(nesqp->hw_tcp_state != NES_AEQE_TCP_STATE_TIME_WAIT)) { | 						(nesqp->hw_tcp_state != NES_AEQE_TCP_STATE_TIME_WAIT)) { | ||||||
| 					next_iwarp_state |= NES_CQP_QP_RESET; | 					next_iwarp_state |= NES_CQP_QP_RESET; | ||||||
| 				} else { | 				} else { | ||||||
|  | @ -3936,6 +3937,17 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev) | ||||||
| 	return nesibdev; | 	return nesibdev; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void  nes_port_ibevent(struct nes_vnic *nesvnic) | ||||||
|  | { | ||||||
|  | 	struct nes_ib_device *nesibdev = nesvnic->nesibdev; | ||||||
|  | 	struct nes_device *nesdev = nesvnic->nesdev; | ||||||
|  | 	struct ib_event event; | ||||||
|  | 	event.device = &nesibdev->ibdev; | ||||||
|  | 	event.element.port_num = nesvnic->logical_port + 1; | ||||||
|  | 	event.event = nesdev->iw_status ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR; | ||||||
|  | 	ib_dispatch_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * nes_destroy_ofa_device |  * nes_destroy_ofa_device | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Faisal Latif
				Faisal Latif