hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
....@@ -1,16 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Huawei HiNIC PCI Express Linux driver
34 * Copyright(c) 2017 Huawei Technologies Co., Ltd
4
- *
5
- * This program is free software; you can redistribute it and/or modify it
6
- * under the terms and conditions of the GNU General Public License,
7
- * version 2, as published by the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope it will be useful, but WITHOUT
10
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
- * for more details.
13
- *
145 */
156
167 #include <linux/kernel.h>
....@@ -21,8 +12,10 @@
2112 #include <linux/semaphore.h>
2213 #include <linux/completion.h>
2314 #include <linux/slab.h>
15
+#include <net/devlink.h>
2416 #include <asm/barrier.h>
2517
18
+#include "hinic_devlink.h"
2619 #include "hinic_hw_if.h"
2720 #include "hinic_hw_eqs.h"
2821 #include "hinic_hw_api_cmd.h"
....@@ -54,7 +47,11 @@
5447
5548 #define MGMT_MSG_TIMEOUT 5000
5649
50
+#define SET_FUNC_PORT_MBOX_TIMEOUT 30000
51
+
5752 #define SET_FUNC_PORT_MGMT_TIMEOUT 25000
53
+
54
+#define UPDATE_FW_MGMT_TIMEOUT 20000
5855
5956 #define mgmt_to_pfhwdev(pf_mgmt) \
6057 container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt)
....@@ -241,6 +238,7 @@
241238 * @out_size: response length
242239 * @direction: the direction of the original message
243240 * @resp_msg_id: msg id to response for
241
+ * @timeout: time-out period of waiting for response
244242 *
245243 * Return 0 - Success, negative - Failure
246244 **/
....@@ -283,6 +281,7 @@
283281
284282 if (!wait_for_completion_timeout(recv_done, timeo)) {
285283 dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id);
284
+ hinic_dump_aeq_info(pf_to_mgmt->hwdev);
286285 err = -ETIMEDOUT;
287286 goto unlock_sync_msg;
288287 }
....@@ -367,12 +366,69 @@
367366 return -EINVAL;
368367 }
369368
370
- if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
371
- timeout = SET_FUNC_PORT_MGMT_TIMEOUT;
369
+ if (HINIC_IS_VF(hwif)) {
370
+ if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
371
+ timeout = SET_FUNC_PORT_MBOX_TIMEOUT;
372372
373
- return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
373
+ return hinic_mbox_to_pf(pf_to_mgmt->hwdev, mod, cmd, buf_in,
374
+ in_size, buf_out, out_size, timeout);
375
+ } else {
376
+ if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
377
+ timeout = SET_FUNC_PORT_MGMT_TIMEOUT;
378
+ else if (cmd == HINIC_PORT_CMD_UPDATE_FW)
379
+ timeout = UPDATE_FW_MGMT_TIMEOUT;
380
+
381
+ return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
374382 buf_out, out_size, MGMT_DIRECT_SEND,
375383 MSG_NOT_RESP, timeout);
384
+ }
385
+}
386
+
387
+static void recv_mgmt_msg_work_handler(struct work_struct *work)
388
+{
389
+ struct hinic_mgmt_msg_handle_work *mgmt_work =
390
+ container_of(work, struct hinic_mgmt_msg_handle_work, work);
391
+ struct hinic_pf_to_mgmt *pf_to_mgmt = mgmt_work->pf_to_mgmt;
392
+ struct pci_dev *pdev = pf_to_mgmt->hwif->pdev;
393
+ u8 *buf_out = pf_to_mgmt->mgmt_ack_buf;
394
+ struct hinic_mgmt_cb *mgmt_cb;
395
+ unsigned long cb_state;
396
+ u16 out_size = 0;
397
+
398
+ memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE);
399
+
400
+ if (mgmt_work->mod >= HINIC_MOD_MAX) {
401
+ dev_err(&pdev->dev, "Unknown MGMT MSG module = %d\n",
402
+ mgmt_work->mod);
403
+ kfree(mgmt_work->msg);
404
+ kfree(mgmt_work);
405
+ return;
406
+ }
407
+
408
+ mgmt_cb = &pf_to_mgmt->mgmt_cb[mgmt_work->mod];
409
+
410
+ cb_state = cmpxchg(&mgmt_cb->state,
411
+ HINIC_MGMT_CB_ENABLED,
412
+ HINIC_MGMT_CB_ENABLED | HINIC_MGMT_CB_RUNNING);
413
+
414
+ if ((cb_state == HINIC_MGMT_CB_ENABLED) && (mgmt_cb->cb))
415
+ mgmt_cb->cb(mgmt_cb->handle, mgmt_work->cmd,
416
+ mgmt_work->msg, mgmt_work->msg_len,
417
+ buf_out, &out_size);
418
+ else
419
+ dev_err(&pdev->dev, "No MGMT msg handler, mod: %d, cmd: %d\n",
420
+ mgmt_work->mod, mgmt_work->cmd);
421
+
422
+ mgmt_cb->state &= ~HINIC_MGMT_CB_RUNNING;
423
+
424
+ if (!mgmt_work->async_mgmt_to_pf)
425
+ /* MGMT sent sync msg, send the response */
426
+ msg_to_mgmt_async(pf_to_mgmt, mgmt_work->mod, mgmt_work->cmd,
427
+ buf_out, out_size, MGMT_RESP,
428
+ mgmt_work->msg_id);
429
+
430
+ kfree(mgmt_work->msg);
431
+ kfree(mgmt_work);
376432 }
377433
378434 /**
....@@ -383,40 +439,34 @@
383439 static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
384440 struct hinic_recv_msg *recv_msg)
385441 {
386
- struct hinic_hwif *hwif = pf_to_mgmt->hwif;
387
- struct pci_dev *pdev = hwif->pdev;
388
- u8 *buf_out = recv_msg->buf_out;
389
- struct hinic_mgmt_cb *mgmt_cb;
390
- unsigned long cb_state;
391
- u16 out_size = 0;
442
+ struct hinic_mgmt_msg_handle_work *mgmt_work = NULL;
443
+ struct pci_dev *pdev = pf_to_mgmt->hwif->pdev;
392444
393
- if (recv_msg->mod >= HINIC_MOD_MAX) {
394
- dev_err(&pdev->dev, "Unknown MGMT MSG module = %d\n",
395
- recv_msg->mod);
445
+ mgmt_work = kzalloc(sizeof(*mgmt_work), GFP_KERNEL);
446
+ if (!mgmt_work) {
447
+ dev_err(&pdev->dev, "Allocate mgmt work memory failed\n");
396448 return;
397449 }
398450
399
- mgmt_cb = &pf_to_mgmt->mgmt_cb[recv_msg->mod];
451
+ if (recv_msg->msg_len) {
452
+ mgmt_work->msg = kzalloc(recv_msg->msg_len, GFP_KERNEL);
453
+ if (!mgmt_work->msg) {
454
+ dev_err(&pdev->dev, "Allocate mgmt msg memory failed\n");
455
+ kfree(mgmt_work);
456
+ return;
457
+ }
458
+ }
400459
401
- cb_state = cmpxchg(&mgmt_cb->state,
402
- HINIC_MGMT_CB_ENABLED,
403
- HINIC_MGMT_CB_ENABLED | HINIC_MGMT_CB_RUNNING);
460
+ mgmt_work->pf_to_mgmt = pf_to_mgmt;
461
+ mgmt_work->msg_len = recv_msg->msg_len;
462
+ memcpy(mgmt_work->msg, recv_msg->msg, recv_msg->msg_len);
463
+ mgmt_work->msg_id = recv_msg->msg_id;
464
+ mgmt_work->mod = recv_msg->mod;
465
+ mgmt_work->cmd = recv_msg->cmd;
466
+ mgmt_work->async_mgmt_to_pf = recv_msg->async_mgmt_to_pf;
404467
405
- if ((cb_state == HINIC_MGMT_CB_ENABLED) && (mgmt_cb->cb))
406
- mgmt_cb->cb(mgmt_cb->handle, recv_msg->cmd,
407
- recv_msg->msg, recv_msg->msg_len,
408
- buf_out, &out_size);
409
- else
410
- dev_err(&pdev->dev, "No MGMT msg handler, mod = %d\n",
411
- recv_msg->mod);
412
-
413
- mgmt_cb->state &= ~HINIC_MGMT_CB_RUNNING;
414
-
415
- if (!recv_msg->async_mgmt_to_pf)
416
- /* MGMT sent sync msg, send the response */
417
- msg_to_mgmt_async(pf_to_mgmt, recv_msg->mod, recv_msg->cmd,
418
- buf_out, out_size, MGMT_RESP,
419
- recv_msg->msg_id);
468
+ INIT_WORK(&mgmt_work->work, recv_mgmt_msg_work_handler);
469
+ queue_work(pf_to_mgmt->workq, &mgmt_work->work);
420470 }
421471
422472 /**
....@@ -551,6 +601,12 @@
551601 if (!pf_to_mgmt->sync_msg_buf)
552602 return -ENOMEM;
553603
604
+ pf_to_mgmt->mgmt_ack_buf = devm_kzalloc(&pdev->dev,
605
+ MAX_PF_MGMT_BUF_SIZE,
606
+ GFP_KERNEL);
607
+ if (!pf_to_mgmt->mgmt_ack_buf)
608
+ return -ENOMEM;
609
+
554610 return 0;
555611 }
556612
....@@ -570,19 +626,37 @@
570626 int err;
571627
572628 pf_to_mgmt->hwif = hwif;
629
+ pf_to_mgmt->hwdev = hwdev;
630
+
631
+ if (HINIC_IS_VF(hwif))
632
+ return 0;
633
+
634
+ err = hinic_health_reporters_create(hwdev->devlink_dev);
635
+ if (err)
636
+ return err;
573637
574638 sema_init(&pf_to_mgmt->sync_msg_lock, 1);
639
+ pf_to_mgmt->workq = create_singlethread_workqueue("hinic_mgmt");
640
+ if (!pf_to_mgmt->workq) {
641
+ dev_err(&pdev->dev, "Failed to initialize MGMT workqueue\n");
642
+ hinic_health_reporters_destroy(hwdev->devlink_dev);
643
+ return -ENOMEM;
644
+ }
575645 pf_to_mgmt->sync_msg_id = 0;
576646
577647 err = alloc_msg_buf(pf_to_mgmt);
578648 if (err) {
579649 dev_err(&pdev->dev, "Failed to allocate msg buffers\n");
650
+ destroy_workqueue(pf_to_mgmt->workq);
651
+ hinic_health_reporters_destroy(hwdev->devlink_dev);
580652 return err;
581653 }
582654
583655 err = hinic_api_cmd_init(pf_to_mgmt->cmd_chain, hwif);
584656 if (err) {
585657 dev_err(&pdev->dev, "Failed to initialize cmd chains\n");
658
+ destroy_workqueue(pf_to_mgmt->workq);
659
+ hinic_health_reporters_destroy(hwdev->devlink_dev);
586660 return err;
587661 }
588662
....@@ -601,6 +675,11 @@
601675 struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
602676 struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
603677
678
+ if (HINIC_IS_VF(hwdev->hwif))
679
+ return;
680
+
604681 hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU);
605682 hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
683
+ destroy_workqueue(pf_to_mgmt->workq);
684
+ hinic_health_reporters_destroy(hwdev->devlink_dev);
606685 }