@@ -50,6 +50,13 @@ static int hn_vf_match(const struct rte_eth_dev *dev)
5050}
5151
5252
53+ static int hn_eth_recovering_callback (uint16_t port_id ,
54+ enum rte_eth_event_type event , void * cb_arg , void * out );
55+ static int hn_eth_recovery_success_callback (uint16_t port_id ,
56+ enum rte_eth_event_type event , void * cb_arg , void * out );
57+ static int hn_eth_recovery_failed_callback (uint16_t port_id ,
58+ enum rte_eth_event_type event , void * cb_arg , void * out );
59+
5360/*
5461 * Attach new PCI VF device and return the port_id
5562 */
@@ -111,7 +118,56 @@ static int hn_vf_attach(struct rte_eth_dev *dev, struct hn_data *hv)
111118 return ret ;
112119 }
113120
121+ /* Register recovery event callbacks for service reset handling */
122+ ret = rte_eth_dev_callback_register (hv -> vf_ctx .vf_port ,
123+ RTE_ETH_EVENT_ERR_RECOVERING ,
124+ hn_eth_recovering_callback , hv );
125+ if (ret ) {
126+ PMD_DRV_LOG (ERR ,
127+ "Registering recovering callback failed for vf port %d ret %d" ,
128+ port , ret );
129+ goto err_recovering ;
130+ }
131+
132+ ret = rte_eth_dev_callback_register (hv -> vf_ctx .vf_port ,
133+ RTE_ETH_EVENT_RECOVERY_SUCCESS ,
134+ hn_eth_recovery_success_callback , hv );
135+ if (ret ) {
136+ PMD_DRV_LOG (ERR ,
137+ "Registering recovery success callback failed for vf port %d ret %d" ,
138+ port , ret );
139+ goto err_recovery_success ;
140+ }
141+
142+ ret = rte_eth_dev_callback_register (hv -> vf_ctx .vf_port ,
143+ RTE_ETH_EVENT_RECOVERY_FAILED ,
144+ hn_eth_recovery_failed_callback , hv );
145+ if (ret ) {
146+ PMD_DRV_LOG (ERR ,
147+ "Registering recovery failed callback failed for vf port %d ret %d" ,
148+ port , ret );
149+ goto err_recovery_failed ;
150+ }
151+
114152 return 0 ;
153+
154+ err_recovery_failed :
155+ rte_eth_dev_callback_unregister (hv -> vf_ctx .vf_port ,
156+ RTE_ETH_EVENT_RECOVERY_SUCCESS ,
157+ hn_eth_recovery_success_callback , hv );
158+ err_recovery_success :
159+ rte_eth_dev_callback_unregister (hv -> vf_ctx .vf_port ,
160+ RTE_ETH_EVENT_ERR_RECOVERING ,
161+ hn_eth_recovering_callback , hv );
162+ err_recovering :
163+ rte_eth_dev_callback_unregister (hv -> vf_ctx .vf_port ,
164+ RTE_ETH_EVENT_INTR_RMV ,
165+ hn_eth_rmv_event_callback , hv );
166+ hv -> vf_ctx .vf_attached = false;
167+ hv -> vf_ctx .vf_port = 0 ;
168+ if (rte_eth_dev_owner_unset (port , hv -> owner .id ) < 0 )
169+ PMD_DRV_LOG (ERR , "Failed to unset owner for port %d" , port );
170+ return ret ;
115171}
116172
117173static void hn_vf_remove_unlocked (struct hn_data * hv );
@@ -143,6 +199,12 @@ static void hn_remove_delayed(void *args)
143199 PMD_DRV_LOG (ERR ,
144200 "rte_eth_dev_callback_unregister failed ret=%d" ,
145201 ret );
202+ rte_eth_dev_callback_unregister (port_id , RTE_ETH_EVENT_ERR_RECOVERING ,
203+ hn_eth_recovering_callback , hv );
204+ rte_eth_dev_callback_unregister (port_id , RTE_ETH_EVENT_RECOVERY_SUCCESS ,
205+ hn_eth_recovery_success_callback , hv );
206+ rte_eth_dev_callback_unregister (port_id , RTE_ETH_EVENT_RECOVERY_FAILED ,
207+ hn_eth_recovery_failed_callback , hv );
146208
147209 /* Detach and release port_id from system */
148210 ret = rte_eth_dev_stop (port_id );
@@ -187,6 +249,70 @@ int hn_eth_rmv_event_callback(uint16_t port_id,
187249 return 0 ;
188250}
189251
252+ /*
253+ * Handle VF error recovery event from MANA PMD.
254+ * Switch data path to synthetic but keep the VF attached.
255+ */
256+ static int
257+ hn_eth_recovering_callback (uint16_t port_id ,
258+ enum rte_eth_event_type event __rte_unused ,
259+ void * cb_arg , void * out __rte_unused )
260+ {
261+ struct hn_data * hv = cb_arg ;
262+
263+ PMD_DRV_LOG (NOTICE , "VF port %u recovering from error" , port_id );
264+
265+ rte_rwlock_write_lock (& hv -> vf_lock );
266+ hn_vf_remove_unlocked (hv );
267+ rte_rwlock_write_unlock (& hv -> vf_lock );
268+
269+ return 0 ;
270+ }
271+
272+ /*
273+ * Handle VF recovery success event from MANA PMD.
274+ * Switch data path back to VF.
275+ */
276+ static int
277+ hn_eth_recovery_success_callback (uint16_t port_id ,
278+ enum rte_eth_event_type event __rte_unused ,
279+ void * cb_arg , void * out __rte_unused )
280+ {
281+ struct hn_data * hv = cb_arg ;
282+ int ret ;
283+
284+ PMD_DRV_LOG (NOTICE , "VF port %u recovery succeeded" , port_id );
285+
286+ rte_rwlock_write_lock (& hv -> vf_lock );
287+ if (hv -> vf_ctx .vf_attached && !hv -> vf_ctx .vf_vsc_switched ) {
288+ ret = hn_nvs_set_datapath (hv , NVS_DATAPATH_VF );
289+ if (ret )
290+ PMD_DRV_LOG (ERR , "Failed to switch to VF after recovery" );
291+ else
292+ hv -> vf_ctx .vf_vsc_switched = true;
293+ }
294+ rte_rwlock_write_unlock (& hv -> vf_lock );
295+
296+ return 0 ;
297+ }
298+
299+ /*
300+ * Handle VF recovery failure event from MANA PMD.
301+ * VF is unusable, do full removal.
302+ */
303+ static int
304+ hn_eth_recovery_failed_callback (uint16_t port_id ,
305+ enum rte_eth_event_type event __rte_unused ,
306+ void * cb_arg , void * out __rte_unused )
307+ {
308+ struct hn_data * hv = cb_arg ;
309+
310+ PMD_DRV_LOG (NOTICE , "VF port %u recovery failed, removing" , port_id );
311+ rte_eal_alarm_set (1 , hn_remove_delayed , hv );
312+
313+ return 0 ;
314+ }
315+
190316static int hn_setup_vf_queues (int port , struct rte_eth_dev * dev )
191317{
192318 struct hn_rx_queue * rx_queue ;
@@ -247,6 +373,12 @@ static void hn_vf_detach(struct hn_data *hv)
247373
248374 rte_eth_dev_callback_unregister (port , RTE_ETH_EVENT_INTR_RMV ,
249375 hn_eth_rmv_event_callback , hv );
376+ rte_eth_dev_callback_unregister (port , RTE_ETH_EVENT_ERR_RECOVERING ,
377+ hn_eth_recovering_callback , hv );
378+ rte_eth_dev_callback_unregister (port , RTE_ETH_EVENT_RECOVERY_SUCCESS ,
379+ hn_eth_recovery_success_callback , hv );
380+ rte_eth_dev_callback_unregister (port , RTE_ETH_EVENT_RECOVERY_FAILED ,
381+ hn_eth_recovery_failed_callback , hv );
250382
251383 if (rte_eth_dev_owner_unset (port , hv -> owner .id ) < 0 )
252384 PMD_DRV_LOG (ERR , "Failed to unset owner for port %d" , port );
@@ -630,6 +762,18 @@ int hn_vf_close(struct rte_eth_dev *dev)
630762 RTE_ETH_EVENT_INTR_RMV ,
631763 hn_eth_rmv_event_callback ,
632764 hv );
765+ rte_eth_dev_callback_unregister (hv -> vf_ctx .vf_port ,
766+ RTE_ETH_EVENT_ERR_RECOVERING ,
767+ hn_eth_recovering_callback ,
768+ hv );
769+ rte_eth_dev_callback_unregister (hv -> vf_ctx .vf_port ,
770+ RTE_ETH_EVENT_RECOVERY_SUCCESS ,
771+ hn_eth_recovery_success_callback ,
772+ hv );
773+ rte_eth_dev_callback_unregister (hv -> vf_ctx .vf_port ,
774+ RTE_ETH_EVENT_RECOVERY_FAILED ,
775+ hn_eth_recovery_failed_callback ,
776+ hv );
633777 rte_eal_alarm_cancel (hn_remove_delayed , hv );
634778 ret = rte_eth_dev_close (hv -> vf_ctx .vf_port );
635779 hv -> vf_ctx .vf_attached = false;
0 commit comments