@@ -2227,6 +2227,12 @@ static int hclge_mac_init(struct hclge_dev *hdev)
2227
2227
return hclge_cfg_func_mta_filter (hdev , 0 , hdev -> accept_mta_mc );
2228
2228
}
2229
2229
2230
+ static void hclge_mbx_task_schedule (struct hclge_dev * hdev )
2231
+ {
2232
+ if (!test_and_set_bit (HCLGE_STATE_MBX_SERVICE_SCHED , & hdev -> state ))
2233
+ schedule_work (& hdev -> mbx_service_task );
2234
+ }
2235
+
2230
2236
static void hclge_reset_task_schedule (struct hclge_dev * hdev )
2231
2237
{
2232
2238
if (!test_and_set_bit (HCLGE_STATE_RST_SERVICE_SCHED , & hdev -> state ))
@@ -2372,9 +2378,18 @@ static void hclge_service_complete(struct hclge_dev *hdev)
2372
2378
static u32 hclge_check_event_cause (struct hclge_dev * hdev , u32 * clearval )
2373
2379
{
2374
2380
u32 rst_src_reg ;
2381
+ u32 cmdq_src_reg ;
2375
2382
2376
2383
/* fetch the events from their corresponding regs */
2377
2384
rst_src_reg = hclge_read_dev (& hdev -> hw , HCLGE_MISC_RESET_STS_REG );
2385
+ cmdq_src_reg = hclge_read_dev (& hdev -> hw , HCLGE_VECTOR0_CMDQ_SRC_REG );
2386
+
2387
+ /* Assumption: If by any chance reset and mailbox events are reported
2388
+ * together then we will only process reset event in this go and will
2389
+ * defer the processing of the mailbox events. Since, we would have not
2390
+ * cleared RX CMDQ event this time we would receive again another
2391
+ * interrupt from H/W just for the mailbox.
2392
+ */
2378
2393
2379
2394
/* check for vector0 reset event sources */
2380
2395
if (BIT (HCLGE_VECTOR0_GLOBALRESET_INT_B ) & rst_src_reg ) {
@@ -2395,18 +2410,27 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
2395
2410
return HCLGE_VECTOR0_EVENT_RST ;
2396
2411
}
2397
2412
2398
- /* mailbox event sharing vector 0 interrupt would be placed here */
2413
+ /* check for vector0 mailbox(=CMDQ RX) event source */
2414
+ if (BIT (HCLGE_VECTOR0_RX_CMDQ_INT_B ) & cmdq_src_reg ) {
2415
+ cmdq_src_reg &= ~BIT (HCLGE_VECTOR0_RX_CMDQ_INT_B );
2416
+ * clearval = cmdq_src_reg ;
2417
+ return HCLGE_VECTOR0_EVENT_MBX ;
2418
+ }
2399
2419
2400
2420
return HCLGE_VECTOR0_EVENT_OTHER ;
2401
2421
}
2402
2422
2403
2423
static void hclge_clear_event_cause (struct hclge_dev * hdev , u32 event_type ,
2404
2424
u32 regclr )
2405
2425
{
2406
- if (event_type == HCLGE_VECTOR0_EVENT_RST )
2426
+ switch (event_type ) {
2427
+ case HCLGE_VECTOR0_EVENT_RST :
2407
2428
hclge_write_dev (& hdev -> hw , HCLGE_MISC_RESET_STS_REG , regclr );
2408
-
2409
- /* mailbox event sharing vector 0 interrupt would be placed here */
2429
+ break ;
2430
+ case HCLGE_VECTOR0_EVENT_MBX :
2431
+ hclge_write_dev (& hdev -> hw , HCLGE_VECTOR0_CMDQ_SRC_REG , regclr );
2432
+ break ;
2433
+ }
2410
2434
}
2411
2435
2412
2436
static void hclge_enable_vector (struct hclge_misc_vector * vector , bool enable )
@@ -2423,13 +2447,23 @@ static irqreturn_t hclge_misc_irq_handle(int irq, void *data)
2423
2447
hclge_enable_vector (& hdev -> misc_vector , false);
2424
2448
event_cause = hclge_check_event_cause (hdev , & clearval );
2425
2449
2426
- /* vector 0 interrupt is shared with reset and mailbox source events.
2427
- * For now, we are not handling mailbox events.
2428
- */
2450
+ /* vector 0 interrupt is shared with reset and mailbox source events.*/
2429
2451
switch (event_cause ) {
2430
2452
case HCLGE_VECTOR0_EVENT_RST :
2431
2453
hclge_reset_task_schedule (hdev );
2432
2454
break ;
2455
+ case HCLGE_VECTOR0_EVENT_MBX :
2456
+ /* If we are here then,
2457
+ * 1. Either we are not handling any mbx task and we are not
2458
+ * scheduled as well
2459
+ * OR
2460
+ * 2. We could be handling a mbx task but nothing more is
2461
+ * scheduled.
2462
+ * In both cases, we should schedule mbx task as there are more
2463
+ * mbx messages reported by this interrupt.
2464
+ */
2465
+ hclge_mbx_task_schedule (hdev );
2466
+
2433
2467
default :
2434
2468
dev_dbg (& hdev -> pdev -> dev ,
2435
2469
"received unknown or unhandled event of vector0\n" );
@@ -2708,6 +2742,21 @@ static void hclge_reset_service_task(struct work_struct *work)
2708
2742
clear_bit (HCLGE_STATE_RST_HANDLING , & hdev -> state );
2709
2743
}
2710
2744
2745
+ static void hclge_mailbox_service_task (struct work_struct * work )
2746
+ {
2747
+ struct hclge_dev * hdev =
2748
+ container_of (work , struct hclge_dev , mbx_service_task );
2749
+
2750
+ if (test_and_set_bit (HCLGE_STATE_MBX_HANDLING , & hdev -> state ))
2751
+ return ;
2752
+
2753
+ clear_bit (HCLGE_STATE_MBX_SERVICE_SCHED , & hdev -> state );
2754
+
2755
+ hclge_mbx_handler (hdev );
2756
+
2757
+ clear_bit (HCLGE_STATE_MBX_HANDLING , & hdev -> state );
2758
+ }
2759
+
2711
2760
static void hclge_service_task (struct work_struct * work )
2712
2761
{
2713
2762
struct hclge_dev * hdev =
@@ -4815,6 +4864,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
4815
4864
timer_setup (& hdev -> service_timer , hclge_service_timer , 0 );
4816
4865
INIT_WORK (& hdev -> service_task , hclge_service_task );
4817
4866
INIT_WORK (& hdev -> rst_service_task , hclge_reset_service_task );
4867
+ INIT_WORK (& hdev -> mbx_service_task , hclge_mailbox_service_task );
4818
4868
4819
4869
/* Enable MISC vector(vector0) */
4820
4870
hclge_enable_vector (& hdev -> misc_vector , true);
@@ -4823,6 +4873,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
4823
4873
set_bit (HCLGE_STATE_DOWN , & hdev -> state );
4824
4874
clear_bit (HCLGE_STATE_RST_SERVICE_SCHED , & hdev -> state );
4825
4875
clear_bit (HCLGE_STATE_RST_HANDLING , & hdev -> state );
4876
+ clear_bit (HCLGE_STATE_MBX_SERVICE_SCHED , & hdev -> state );
4877
+ clear_bit (HCLGE_STATE_MBX_HANDLING , & hdev -> state );
4826
4878
4827
4879
pr_info ("%s driver initialization finished.\n" , HCLGE_DRIVER_NAME );
4828
4880
return 0 ;
@@ -4936,6 +4988,8 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
4936
4988
cancel_work_sync (& hdev -> service_task );
4937
4989
if (hdev -> rst_service_task .func )
4938
4990
cancel_work_sync (& hdev -> rst_service_task );
4991
+ if (hdev -> mbx_service_task .func )
4992
+ cancel_work_sync (& hdev -> mbx_service_task );
4939
4993
4940
4994
if (mac -> phydev )
4941
4995
mdiobus_unregister (mac -> mdio_bus );
0 commit comments