Skip to content

Commit 6dbb890

Browse files
Luo bindavem330
authored andcommitted
hinic: fix sending mailbox timeout in aeq event work
When sending mailbox in the work of aeq event, another aeq event will be triggered. because the last aeq work is not exited and only one work can be excuted simultaneously in the same workqueue, mailbox sending function will return failure of timeout. We create and use another workqueue to fix this. Signed-off-by: Luo bin <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c00e858 commit 6dbb890

File tree

2 files changed

+88
-19
lines changed

2 files changed

+88
-19
lines changed

drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -370,48 +370,89 @@ int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
370370
MSG_NOT_RESP, timeout);
371371
}
372372

373-
/**
374-
* mgmt_recv_msg_handler - handler for message from mgmt cpu
375-
* @pf_to_mgmt: PF to MGMT channel
376-
* @recv_msg: received message details
377-
**/
378-
static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
379-
struct hinic_recv_msg *recv_msg)
373+
static void recv_mgmt_msg_work_handler(struct work_struct *work)
380374
{
381-
struct hinic_hwif *hwif = pf_to_mgmt->hwif;
382-
struct pci_dev *pdev = hwif->pdev;
383-
u8 *buf_out = recv_msg->buf_out;
375+
struct hinic_mgmt_msg_handle_work *mgmt_work =
376+
container_of(work, struct hinic_mgmt_msg_handle_work, work);
377+
struct hinic_pf_to_mgmt *pf_to_mgmt = mgmt_work->pf_to_mgmt;
378+
struct pci_dev *pdev = pf_to_mgmt->hwif->pdev;
379+
u8 *buf_out = pf_to_mgmt->mgmt_ack_buf;
384380
struct hinic_mgmt_cb *mgmt_cb;
385381
unsigned long cb_state;
386382
u16 out_size = 0;
387383

388-
if (recv_msg->mod >= HINIC_MOD_MAX) {
384+
memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE);
385+
386+
if (mgmt_work->mod >= HINIC_MOD_MAX) {
389387
dev_err(&pdev->dev, "Unknown MGMT MSG module = %d\n",
390-
recv_msg->mod);
388+
mgmt_work->mod);
389+
kfree(mgmt_work->msg);
390+
kfree(mgmt_work);
391391
return;
392392
}
393393

394-
mgmt_cb = &pf_to_mgmt->mgmt_cb[recv_msg->mod];
394+
mgmt_cb = &pf_to_mgmt->mgmt_cb[mgmt_work->mod];
395395

396396
cb_state = cmpxchg(&mgmt_cb->state,
397397
HINIC_MGMT_CB_ENABLED,
398398
HINIC_MGMT_CB_ENABLED | HINIC_MGMT_CB_RUNNING);
399399

400400
if ((cb_state == HINIC_MGMT_CB_ENABLED) && (mgmt_cb->cb))
401-
mgmt_cb->cb(mgmt_cb->handle, recv_msg->cmd,
402-
recv_msg->msg, recv_msg->msg_len,
401+
mgmt_cb->cb(mgmt_cb->handle, mgmt_work->cmd,
402+
mgmt_work->msg, mgmt_work->msg_len,
403403
buf_out, &out_size);
404404
else
405405
dev_err(&pdev->dev, "No MGMT msg handler, mod: %d, cmd: %d\n",
406-
recv_msg->mod, recv_msg->cmd);
406+
mgmt_work->mod, mgmt_work->cmd);
407407

408408
mgmt_cb->state &= ~HINIC_MGMT_CB_RUNNING;
409409

410-
if (!recv_msg->async_mgmt_to_pf)
410+
if (!mgmt_work->async_mgmt_to_pf)
411411
/* MGMT sent sync msg, send the response */
412-
msg_to_mgmt_async(pf_to_mgmt, recv_msg->mod, recv_msg->cmd,
412+
msg_to_mgmt_async(pf_to_mgmt, mgmt_work->mod, mgmt_work->cmd,
413413
buf_out, out_size, MGMT_RESP,
414-
recv_msg->msg_id);
414+
mgmt_work->msg_id);
415+
416+
kfree(mgmt_work->msg);
417+
kfree(mgmt_work);
418+
}
419+
420+
/**
421+
* mgmt_recv_msg_handler - handler for message from mgmt cpu
422+
* @pf_to_mgmt: PF to MGMT channel
423+
* @recv_msg: received message details
424+
**/
425+
static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
426+
struct hinic_recv_msg *recv_msg)
427+
{
428+
struct hinic_mgmt_msg_handle_work *mgmt_work = NULL;
429+
struct pci_dev *pdev = pf_to_mgmt->hwif->pdev;
430+
431+
mgmt_work = kzalloc(sizeof(*mgmt_work), GFP_KERNEL);
432+
if (!mgmt_work) {
433+
dev_err(&pdev->dev, "Allocate mgmt work memory failed\n");
434+
return;
435+
}
436+
437+
if (recv_msg->msg_len) {
438+
mgmt_work->msg = kzalloc(recv_msg->msg_len, GFP_KERNEL);
439+
if (!mgmt_work->msg) {
440+
dev_err(&pdev->dev, "Allocate mgmt msg memory failed\n");
441+
kfree(mgmt_work);
442+
return;
443+
}
444+
}
445+
446+
mgmt_work->pf_to_mgmt = pf_to_mgmt;
447+
mgmt_work->msg_len = recv_msg->msg_len;
448+
memcpy(mgmt_work->msg, recv_msg->msg, recv_msg->msg_len);
449+
mgmt_work->msg_id = recv_msg->msg_id;
450+
mgmt_work->mod = recv_msg->mod;
451+
mgmt_work->cmd = recv_msg->cmd;
452+
mgmt_work->async_mgmt_to_pf = recv_msg->async_mgmt_to_pf;
453+
454+
INIT_WORK(&mgmt_work->work, recv_mgmt_msg_work_handler);
455+
queue_work(pf_to_mgmt->workq, &mgmt_work->work);
415456
}
416457

417458
/**
@@ -546,6 +587,12 @@ static int alloc_msg_buf(struct hinic_pf_to_mgmt *pf_to_mgmt)
546587
if (!pf_to_mgmt->sync_msg_buf)
547588
return -ENOMEM;
548589

590+
pf_to_mgmt->mgmt_ack_buf = devm_kzalloc(&pdev->dev,
591+
MAX_PF_MGMT_BUF_SIZE,
592+
GFP_KERNEL);
593+
if (!pf_to_mgmt->mgmt_ack_buf)
594+
return -ENOMEM;
595+
549596
return 0;
550597
}
551598

@@ -571,6 +618,11 @@ int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
571618
return 0;
572619

573620
sema_init(&pf_to_mgmt->sync_msg_lock, 1);
621+
pf_to_mgmt->workq = create_singlethread_workqueue("hinic_mgmt");
622+
if (!pf_to_mgmt->workq) {
623+
dev_err(&pdev->dev, "Failed to initialize MGMT workqueue\n");
624+
return -ENOMEM;
625+
}
574626
pf_to_mgmt->sync_msg_id = 0;
575627

576628
err = alloc_msg_buf(pf_to_mgmt);
@@ -605,4 +657,5 @@ void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt)
605657

606658
hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU);
607659
hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
660+
destroy_workqueue(pf_to_mgmt->workq);
608661
}

drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,29 @@ struct hinic_pf_to_mgmt {
119119
struct semaphore sync_msg_lock;
120120
u16 sync_msg_id;
121121
u8 *sync_msg_buf;
122+
void *mgmt_ack_buf;
122123

123124
struct hinic_recv_msg recv_resp_msg_from_mgmt;
124125
struct hinic_recv_msg recv_msg_from_mgmt;
125126

126127
struct hinic_api_cmd_chain *cmd_chain[HINIC_API_CMD_MAX];
127128

128129
struct hinic_mgmt_cb mgmt_cb[HINIC_MOD_MAX];
130+
131+
struct workqueue_struct *workq;
132+
};
133+
134+
struct hinic_mgmt_msg_handle_work {
135+
struct work_struct work;
136+
struct hinic_pf_to_mgmt *pf_to_mgmt;
137+
138+
void *msg;
139+
u16 msg_len;
140+
141+
enum hinic_mod_type mod;
142+
u8 cmd;
143+
u16 msg_id;
144+
int async_mgmt_to_pf;
129145
};
130146

131147
void hinic_register_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt,

0 commit comments

Comments
 (0)