@@ -110,11 +110,25 @@ static void mlx5e_rep_neigh_stats_work(struct work_struct *work)
110110	rtnl_unlock ();
111111}
112112
113+ struct  neigh_update_work  {
114+ 	struct  work_struct  work ;
115+ 	struct  neighbour  * n ;
116+ 	struct  mlx5e_neigh_hash_entry  * nhe ;
117+ };
118+ 
119+ static  void  mlx5e_release_neigh_update_work (struct  neigh_update_work  * update_work )
120+ {
121+ 	neigh_release (update_work -> n );
122+ 	mlx5e_rep_neigh_entry_release (update_work -> nhe );
123+ 	kfree (update_work );
124+ }
125+ 
113126static  void  mlx5e_rep_neigh_update (struct  work_struct  * work )
114127{
115- 	struct  mlx5e_neigh_hash_entry  * nhe  = 
116- 		container_of (work , struct  mlx5e_neigh_hash_entry , neigh_update_work );
117- 	struct  neighbour  * n  =  nhe -> n ;
128+ 	struct  neigh_update_work  * update_work  =  container_of (work , struct  neigh_update_work ,
129+ 							     work );
130+ 	struct  mlx5e_neigh_hash_entry  * nhe  =  update_work -> nhe ;
131+ 	struct  neighbour  * n  =  update_work -> n ;
118132	struct  mlx5e_encap_entry  * e ;
119133	unsigned char   ha [ETH_ALEN ];
120134	struct  mlx5e_priv  * priv ;
@@ -146,30 +160,42 @@ static void mlx5e_rep_neigh_update(struct work_struct *work)
146160		mlx5e_rep_update_flows (priv , e , neigh_connected , ha );
147161		mlx5e_encap_put (priv , e );
148162	}
149- 	mlx5e_rep_neigh_entry_release (nhe );
150163	rtnl_unlock ();
151- 	neigh_release ( n );
164+ 	mlx5e_release_neigh_update_work ( update_work );
152165}
153166
154- static  void  mlx5e_rep_queue_neigh_update_work (struct  mlx5e_priv  * priv ,
155- 					      struct  mlx5e_neigh_hash_entry  * nhe ,
156- 					      struct  neighbour  * n )
167+ static  struct  neigh_update_work  * mlx5e_alloc_neigh_update_work (struct  mlx5e_priv  * priv ,
168+ 							       struct  neighbour  * n )
157169{
158- 	/* Take a reference to ensure the neighbour and mlx5 encap 
159- 	 * entry won't be destructed until we drop the reference in 
160- 	 * delayed work. 
161- 	 */ 
162- 	neigh_hold (n );
170+ 	struct  neigh_update_work  * update_work ;
171+ 	struct  mlx5e_neigh_hash_entry  * nhe ;
172+ 	struct  mlx5e_neigh  m_neigh  =  {};
163173
164- 	/* This assignment is valid as long as the the neigh reference 
165- 	 * is taken 
166- 	 */ 
167- 	nhe -> n  =  n ;
174+ 	update_work  =  kzalloc (sizeof (* update_work ), GFP_ATOMIC );
175+ 	if  (WARN_ON (!update_work ))
176+ 		return  NULL ;
168177
169- 	if  (!queue_work (priv -> wq , & nhe -> neigh_update_work )) {
170- 		mlx5e_rep_neigh_entry_release (nhe );
171- 		neigh_release (n );
178+ 	m_neigh .dev  =  n -> dev ;
179+ 	m_neigh .family  =  n -> ops -> family ;
180+ 	memcpy (& m_neigh .dst_ip , n -> primary_key , n -> tbl -> key_len );
181+ 
182+ 	/* Obtain reference to nhe as last step in order not to release it in 
183+ 	 * atomic context. 
184+ 	 */ 
185+ 	rcu_read_lock ();
186+ 	nhe  =  mlx5e_rep_neigh_entry_lookup (priv , & m_neigh );
187+ 	rcu_read_unlock ();
188+ 	if  (!nhe ) {
189+ 		kfree (update_work );
190+ 		return  NULL ;
172191	}
192+ 
193+ 	INIT_WORK (& update_work -> work , mlx5e_rep_neigh_update );
194+ 	neigh_hold (n );
195+ 	update_work -> n  =  n ;
196+ 	update_work -> nhe  =  nhe ;
197+ 
198+ 	return  update_work ;
173199}
174200
175201static  int  mlx5e_rep_netevent_event (struct  notifier_block  * nb ,
@@ -181,7 +207,7 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
181207	struct  net_device  * netdev  =  rpriv -> netdev ;
182208	struct  mlx5e_priv  * priv  =  netdev_priv (netdev );
183209	struct  mlx5e_neigh_hash_entry  * nhe  =  NULL ;
184- 	struct  mlx5e_neigh   m_neigh   =  {} ;
210+ 	struct  neigh_update_work   * update_work ;
185211	struct  neigh_parms  * p ;
186212	struct  neighbour  * n ;
187213	bool  found  =  false;
@@ -196,17 +222,11 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
196222#endif 
197223			return  NOTIFY_DONE ;
198224
199- 		m_neigh .dev  =  n -> dev ;
200- 		m_neigh .family  =  n -> ops -> family ;
201- 		memcpy (& m_neigh .dst_ip , n -> primary_key , n -> tbl -> key_len );
202- 
203- 		rcu_read_lock ();
204- 		nhe  =  mlx5e_rep_neigh_entry_lookup (priv , & m_neigh );
205- 		rcu_read_unlock ();
206- 		if  (!nhe )
225+ 		update_work  =  mlx5e_alloc_neigh_update_work (priv , n );
226+ 		if  (!update_work )
207227			return  NOTIFY_DONE ;
208228
209- 		mlx5e_rep_queue_neigh_update_work (priv ,  nhe ,  n );
229+ 		queue_work (priv -> wq ,  & update_work -> work );
210230		break ;
211231
212232	case  NETEVENT_DELAY_PROBE_TIME_UPDATE :
@@ -352,7 +372,6 @@ int mlx5e_rep_neigh_entry_create(struct mlx5e_priv *priv,
352372
353373	(* nhe )-> priv  =  priv ;
354374	memcpy (& (* nhe )-> m_neigh , & e -> m_neigh , sizeof (e -> m_neigh ));
355- 	INIT_WORK (& (* nhe )-> neigh_update_work , mlx5e_rep_neigh_update );
356375	spin_lock_init (& (* nhe )-> encap_list_lock );
357376	INIT_LIST_HEAD (& (* nhe )-> encap_list );
358377	refcount_set (& (* nhe )-> refcnt , 1 );
0 commit comments