git: 623918a198f9 - main - mana: Improve the HWC error handling
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 13 Jan 2022 06:10:02 UTC
The branch main has been updated by whu: URL: https://cgit.FreeBSD.org/src/commit/?id=623918a198f9231621d60c9294ac1db469fe1565 commit 623918a198f9231621d60c9294ac1db469fe1565 Author: Wei Hu <whu@FreeBSD.org> AuthorDate: 2022-01-12 14:33:54 +0000 Commit: Wei Hu <whu@FreeBSD.org> CommitDate: 2022-01-13 06:08:43 +0000 mana: Improve the HWC error handling Currently when the HWC creation fails, the error handling is flawed, e.g. if mana_hwc_create_channel() -> mana_hwc_establish_channel() fails, the resources acquired in mana_hwc_init_queues() is not released. Enhance mana_hwc_destroy_channel() to do the proper cleanup work and call it accordingly. MFC after: 2 weeks Sponsored by: Microsoft --- sys/dev/mana/gdma_main.c | 5 ---- sys/dev/mana/hw_channel.c | 73 +++++++++++++++++++++-------------------------- 2 files changed, 33 insertions(+), 45 deletions(-) diff --git a/sys/dev/mana/gdma_main.c b/sys/dev/mana/gdma_main.c index 49af54f4be5d..b879695825b1 100644 --- a/sys/dev/mana/gdma_main.c +++ b/sys/dev/mana/gdma_main.c @@ -1808,9 +1808,6 @@ mana_gd_attach(device_t dev) err_clean_up_gdma: mana_hwc_destroy_channel(gc); - if (gc->cq_table) - free(gc->cq_table, M_DEVBUF); - gc->cq_table = NULL; err_remove_irq: mana_gd_remove_irqs(dev); err_free_pci_res: @@ -1836,8 +1833,6 @@ mana_gd_detach(device_t dev) mana_remove(&gc->mana); mana_hwc_destroy_channel(gc); - free(gc->cq_table, M_DEVBUF); - gc->cq_table = NULL; mana_gd_remove_irqs(dev); diff --git a/sys/dev/mana/hw_channel.c b/sys/dev/mana/hw_channel.c index c24e62970f69..16b644d6c6b7 100644 --- a/sys/dev/mana/hw_channel.c +++ b/sys/dev/mana/hw_channel.c @@ -383,9 +383,6 @@ mana_hwc_comp_event(void *ctx, struct gdma_queue *q_self) static void mana_hwc_destroy_cq(struct gdma_context *gc, struct hwc_cq *hwc_cq) { - if (!hwc_cq) - return; - if (hwc_cq->comp_buf) free(hwc_cq->comp_buf, M_DEVBUF); @@ -531,9 +528,6 @@ static void mana_hwc_destroy_wq(struct hw_channel_context *hwc, struct hwc_wq *hwc_wq) { - if (!hwc_wq) - return; - mana_hwc_dealloc_dma_buf(hwc, hwc_wq->msg_buf); if (hwc_wq->gdma_wq) @@ -718,6 +712,7 @@ mana_hwc_establish_channel(struct gdma_context *gc, uint16_t *q_depth, *max_req_msg_size = hwc->hwc_init_max_req_msg_size; *max_resp_msg_size = hwc->hwc_init_max_resp_msg_size; + /* Both were set in mana_hwc_init_event_handler(). */ if (cq->id >= gc->max_num_cqs) { mana_warn(NULL, "invalid cq id %u > %u\n", cq->id, gc->max_num_cqs); @@ -738,9 +733,6 @@ static int mana_hwc_init_queues(struct hw_channel_context *hwc, uint16_t q_depth, uint32_t max_req_msg_size, uint32_t max_resp_msg_size) { - struct hwc_wq *hwc_rxq = NULL; - struct hwc_wq *hwc_txq = NULL; - struct hwc_cq *hwc_cq = NULL; int err; err = mana_hwc_init_inflight_msg(hwc, q_depth); @@ -753,44 +745,32 @@ mana_hwc_init_queues(struct hw_channel_context *hwc, uint16_t q_depth, err = mana_hwc_create_cq(hwc, q_depth * 2, mana_hwc_init_event_handler, hwc, mana_hwc_rx_event_handler, hwc, - mana_hwc_tx_event_handler, hwc, &hwc_cq); + mana_hwc_tx_event_handler, hwc, &hwc->cq); if (err) { device_printf(hwc->dev, "Failed to create HWC CQ: %d\n", err); goto out; } - hwc->cq = hwc_cq; err = mana_hwc_create_wq(hwc, GDMA_RQ, q_depth, max_req_msg_size, - hwc_cq, &hwc_rxq); + hwc->cq, &hwc->rxq); if (err) { device_printf(hwc->dev, "Failed to create HWC RQ: %d\n", err); goto out; } - hwc->rxq = hwc_rxq; err = mana_hwc_create_wq(hwc, GDMA_SQ, q_depth, max_resp_msg_size, - hwc_cq, &hwc_txq); + hwc->cq, &hwc->txq); if (err) { device_printf(hwc->dev, "Failed to create HWC SQ: %d\n", err); goto out; } - hwc->txq = hwc_txq; hwc->num_inflight_msg = q_depth; hwc->max_req_msg_size = max_req_msg_size; return 0; out: - if (hwc_txq) - mana_hwc_destroy_wq(hwc, hwc_txq); - - if (hwc_rxq) - mana_hwc_destroy_wq(hwc, hwc_rxq); - - if (hwc_cq) - mana_hwc_destroy_cq(hwc->gdma_dev->gdma_context, hwc_cq); - - mana_gd_free_res_map(&hwc->inflight_msg_res); + /* mana_hwc_create_channel() will do the cleanup.*/ return err; } @@ -819,6 +799,10 @@ mana_hwc_create_channel(struct gdma_context *gc) gd->pdid = INVALID_PDID; gd->doorbell = INVALID_DOORBELL; + /* + * mana_hwc_init_queues() only creates the required data structures, + * and doesn't touch the HWC device. + */ err = mana_hwc_init_queues(hwc, HW_CHANNEL_VF_BOOTSTRAP_QUEUE_DEPTH, HW_CHANNEL_MAX_REQUEST_SIZE, HW_CHANNEL_MAX_RESPONSE_SIZE); @@ -846,7 +830,7 @@ mana_hwc_create_channel(struct gdma_context *gc) return 0; out: - free(hwc, M_DEVBUF); + mana_hwc_destroy_channel(gc); return (err); } @@ -854,35 +838,44 @@ void mana_hwc_destroy_channel(struct gdma_context *gc) { struct hw_channel_context *hwc = gc->hwc.driver_data; - struct hwc_caller_ctx *ctx; - mana_smc_teardown_hwc(&gc->shm_channel, false); + if (!hwc) + return; + + /* + * gc->max_num_cqs is set in mana_hwc_init_event_handler(). If it's + * non-zero, the HWC worked and we should tear down the HWC here. + */ + if (gc->max_num_cqs > 0) { + mana_smc_teardown_hwc(&gc->shm_channel, false); + gc->max_num_cqs = 0; + } - ctx = hwc->caller_ctx; - free(ctx, M_DEVBUF); + free(hwc->caller_ctx, M_DEVBUF); hwc->caller_ctx = NULL; - mana_hwc_destroy_wq(hwc, hwc->txq); - hwc->txq = NULL; + if (hwc->txq) + mana_hwc_destroy_wq(hwc, hwc->txq); - mana_hwc_destroy_wq(hwc, hwc->rxq); - hwc->rxq = NULL; + if (hwc->rxq) + mana_hwc_destroy_wq(hwc, hwc->rxq); - mana_hwc_destroy_cq(hwc->gdma_dev->gdma_context, hwc->cq); - hwc->cq = NULL; + if (hwc->cq) + mana_hwc_destroy_cq(hwc->gdma_dev->gdma_context, hwc->cq); mana_gd_free_res_map(&hwc->inflight_msg_res); hwc->num_inflight_msg = 0; - if (hwc->gdma_dev->pdid != INVALID_PDID) { - hwc->gdma_dev->doorbell = INVALID_DOORBELL; - hwc->gdma_dev->pdid = INVALID_PDID; - } + hwc->gdma_dev->doorbell = INVALID_DOORBELL; + hwc->gdma_dev->pdid = INVALID_PDID; free(hwc, M_DEVBUF); gc->hwc.driver_data = NULL; gc->hwc.gdma_context = NULL; + + free(gc->cq_table, M_DEVBUF); + gc->cq_table = NULL; } int