@@ -58,6 +58,7 @@ static struct qedi_cmd *qedi_get_cmd_from_tid(struct qedi_ctx *qedi, u32 tid);
58
58
static void qedi_reset_uio_rings (struct qedi_uio_dev * udev );
59
59
static void qedi_ll2_free_skbs (struct qedi_ctx * qedi );
60
60
static struct nvm_iscsi_block * qedi_get_nvram_block (struct qedi_ctx * qedi );
61
+ static void qedi_recovery_handler (struct work_struct * work );
61
62
62
63
static int qedi_iscsi_event_cb (void * context , u8 fw_event_code , void * fw_handle )
63
64
{
@@ -1113,6 +1114,20 @@ static void qedi_get_protocol_tlv_data(void *dev, void *data)
1113
1114
return ;
1114
1115
}
1115
1116
1117
+ static void qedi_schedule_recovery_handler (void * dev )
1118
+ {
1119
+ struct qedi_ctx * qedi = dev ;
1120
+
1121
+ QEDI_ERR (& qedi -> dbg_ctx , "Recovery handler scheduled.\n" );
1122
+
1123
+ if (test_and_set_bit (QEDI_IN_RECOVERY , & qedi -> flags ))
1124
+ return ;
1125
+
1126
+ atomic_set (& qedi -> link_state , QEDI_LINK_DOWN );
1127
+
1128
+ schedule_delayed_work (& qedi -> recovery_work , 0 );
1129
+ }
1130
+
1116
1131
static void qedi_link_update (void * dev , struct qed_link_output * link )
1117
1132
{
1118
1133
struct qedi_ctx * qedi = (struct qedi_ctx * )dev ;
@@ -1130,6 +1145,7 @@ static void qedi_link_update(void *dev, struct qed_link_output *link)
1130
1145
static struct qed_iscsi_cb_ops qedi_cb_ops = {
1131
1146
{
1132
1147
.link_update = qedi_link_update ,
1148
+ .schedule_recovery_handler = qedi_schedule_recovery_handler ,
1133
1149
.get_protocol_tlv_data = qedi_get_protocol_tlv_data ,
1134
1150
.get_generic_tlv_data = qedi_get_generic_tlv_data ,
1135
1151
}
@@ -2328,16 +2344,18 @@ static void __qedi_remove(struct pci_dev *pdev, int mode)
2328
2344
struct qedi_ctx * qedi = pci_get_drvdata (pdev );
2329
2345
int rval ;
2330
2346
2331
- if (qedi -> tmf_thread ) {
2332
- flush_workqueue (qedi -> tmf_thread );
2333
- destroy_workqueue (qedi -> tmf_thread );
2334
- qedi -> tmf_thread = NULL ;
2335
- }
2347
+ if (mode == QEDI_MODE_NORMAL ) {
2348
+ if (qedi -> tmf_thread ) {
2349
+ flush_workqueue (qedi -> tmf_thread );
2350
+ destroy_workqueue (qedi -> tmf_thread );
2351
+ qedi -> tmf_thread = NULL ;
2352
+ }
2336
2353
2337
- if (qedi -> offload_thread ) {
2338
- flush_workqueue (qedi -> offload_thread );
2339
- destroy_workqueue (qedi -> offload_thread );
2340
- qedi -> offload_thread = NULL ;
2354
+ if (qedi -> offload_thread ) {
2355
+ flush_workqueue (qedi -> offload_thread );
2356
+ destroy_workqueue (qedi -> offload_thread );
2357
+ qedi -> offload_thread = NULL ;
2358
+ }
2341
2359
}
2342
2360
2343
2361
#ifdef CONFIG_DEBUG_FS
@@ -2353,8 +2371,7 @@ static void __qedi_remove(struct pci_dev *pdev, int mode)
2353
2371
qedi_ops -> ll2 -> stop (qedi -> cdev );
2354
2372
}
2355
2373
2356
- if (mode == QEDI_MODE_NORMAL )
2357
- qedi_free_iscsi_pf_param (qedi );
2374
+ qedi_free_iscsi_pf_param (qedi );
2358
2375
2359
2376
rval = qedi_ops -> common -> update_drv_state (qedi -> cdev , false);
2360
2377
if (rval )
@@ -2373,9 +2390,6 @@ static void __qedi_remove(struct pci_dev *pdev, int mode)
2373
2390
qedi_free_uio (qedi -> udev );
2374
2391
qedi_free_itt (qedi );
2375
2392
2376
- iscsi_host_remove (qedi -> shost );
2377
- iscsi_host_free (qedi -> shost );
2378
-
2379
2393
if (qedi -> ll2_recv_thread ) {
2380
2394
kthread_stop (qedi -> ll2_recv_thread );
2381
2395
qedi -> ll2_recv_thread = NULL ;
@@ -2384,6 +2398,9 @@ static void __qedi_remove(struct pci_dev *pdev, int mode)
2384
2398
2385
2399
if (qedi -> boot_kset )
2386
2400
iscsi_boot_destroy_kset (qedi -> boot_kset );
2401
+
2402
+ iscsi_host_remove (qedi -> shost );
2403
+ iscsi_host_free (qedi -> shost );
2387
2404
}
2388
2405
}
2389
2406
@@ -2435,14 +2452,12 @@ static int __qedi_probe(struct pci_dev *pdev, int mode)
2435
2452
qedi -> dev_info .common .num_hwfns ,
2436
2453
qedi_ops -> common -> get_affin_hwfn_idx (qedi -> cdev ));
2437
2454
2438
- if (mode != QEDI_MODE_RECOVERY ) {
2439
- rc = qedi_set_iscsi_pf_param (qedi );
2440
- if (rc ) {
2441
- rc = - ENOMEM ;
2442
- QEDI_ERR (& qedi -> dbg_ctx ,
2443
- "Set iSCSI pf param fail\n" );
2444
- goto free_host ;
2445
- }
2455
+ rc = qedi_set_iscsi_pf_param (qedi );
2456
+ if (rc ) {
2457
+ rc = - ENOMEM ;
2458
+ QEDI_ERR (& qedi -> dbg_ctx ,
2459
+ "Set iSCSI pf param fail\n" );
2460
+ goto free_host ;
2446
2461
}
2447
2462
2448
2463
qedi_ops -> common -> update_pf_params (qedi -> cdev , & qedi -> pf_params );
@@ -2633,6 +2648,8 @@ static int __qedi_probe(struct pci_dev *pdev, int mode)
2633
2648
goto free_cid_que ;
2634
2649
}
2635
2650
2651
+ INIT_DELAYED_WORK (& qedi -> recovery_work , qedi_recovery_handler );
2652
+
2636
2653
/* F/w needs 1st task context memory entry for performance */
2637
2654
set_bit (QEDI_RESERVE_TASK_ID , qedi -> task_idx_map );
2638
2655
atomic_set (& qedi -> num_offloads , 0 );
@@ -2673,6 +2690,32 @@ static int __qedi_probe(struct pci_dev *pdev, int mode)
2673
2690
return rc ;
2674
2691
}
2675
2692
2693
+ static void qedi_mark_conn_recovery (struct iscsi_cls_session * cls_session )
2694
+ {
2695
+ struct iscsi_session * session = cls_session -> dd_data ;
2696
+ struct iscsi_conn * conn = session -> leadconn ;
2697
+ struct qedi_conn * qedi_conn = conn -> dd_data ;
2698
+
2699
+ iscsi_conn_failure (qedi_conn -> cls_conn -> dd_data , ISCSI_ERR_CONN_FAILED );
2700
+ }
2701
+
2702
+ static void qedi_recovery_handler (struct work_struct * work )
2703
+ {
2704
+ struct qedi_ctx * qedi =
2705
+ container_of (work , struct qedi_ctx , recovery_work .work );
2706
+
2707
+ iscsi_host_for_each_session (qedi -> shost , qedi_mark_conn_recovery );
2708
+
2709
+ /* Call common_ops->recovery_prolog to allow the MFW to quiesce
2710
+ * any PCI transactions.
2711
+ */
2712
+ qedi_ops -> common -> recovery_prolog (qedi -> cdev );
2713
+
2714
+ __qedi_remove (qedi -> pdev , QEDI_MODE_RECOVERY );
2715
+ __qedi_probe (qedi -> pdev , QEDI_MODE_RECOVERY );
2716
+ clear_bit (QEDI_IN_RECOVERY , & qedi -> flags );
2717
+ }
2718
+
2676
2719
static int qedi_probe (struct pci_dev * pdev , const struct pci_device_id * id )
2677
2720
{
2678
2721
return __qedi_probe (pdev , QEDI_MODE_NORMAL );
0 commit comments