From 6117561e1bb30b2fe7f51e1961f34dbedd0bec8a Mon Sep 17 00:00:00 2001 From: Michal Kalderon Date: Thu, 13 Jun 2019 11:29:40 +0300 Subject: [PATCH 1/4] qed: iWARP - Use READ_ONCE and smp_store_release to access ep->state Destroy QP waits for it's ep object state to be set to CLOSED before proceeding. ep->state can be updated from a different context. Add smp_store_release/READ_ONCE to synchronize. Fixes: fc4c6065e661 ("qed: iWARP implement disconnect flows") Signed-off-by: Ariel Elior Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_iwarp.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c index 7c71ea15251f..4c69adb0b535 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c @@ -532,7 +532,8 @@ int qed_iwarp_destroy_qp(struct qed_hwfn *p_hwfn, struct qed_rdma_qp *qp) /* Make sure ep is closed before returning and freeing memory. */ if (ep) { - while (ep->state != QED_IWARP_EP_CLOSED && wait_count++ < 200) + while (READ_ONCE(ep->state) != QED_IWARP_EP_CLOSED && + wait_count++ < 200) msleep(100); if (ep->state != QED_IWARP_EP_CLOSED) @@ -1022,8 +1023,6 @@ qed_iwarp_mpa_complete(struct qed_hwfn *p_hwfn, params.ep_context = ep; - ep->state = QED_IWARP_EP_CLOSED; - switch (fw_return_code) { case RDMA_RETURN_OK: ep->qp->max_rd_atomic_req = ep->cm_info.ord; @@ -1083,6 +1082,10 @@ qed_iwarp_mpa_complete(struct qed_hwfn *p_hwfn, break; } + if (fw_return_code != RDMA_RETURN_OK) + /* paired with READ_ONCE in destroy_qp */ + smp_store_release(&ep->state, QED_IWARP_EP_CLOSED); + ep->event_cb(ep->cb_context, ¶ms); /* on passive side, if there is no associated QP (REJECT) we need to @@ -2825,7 +2828,9 @@ static void qed_iwarp_qp_in_error(struct qed_hwfn *p_hwfn, params.status = (fw_return_code == IWARP_QP_IN_ERROR_GOOD_CLOSE) ? 0 : -ECONNRESET; - ep->state = QED_IWARP_EP_CLOSED; + /* paired with READ_ONCE in destroy_qp */ + smp_store_release(&ep->state, QED_IWARP_EP_CLOSED); + spin_lock_bh(&p_hwfn->p_rdma_info->iwarp.iw_lock); list_del(&ep->list_entry); spin_unlock_bh(&p_hwfn->p_rdma_info->iwarp.iw_lock); @@ -2914,7 +2919,8 @@ qed_iwarp_tcp_connect_unsuccessful(struct qed_hwfn *p_hwfn, params.event = QED_IWARP_EVENT_ACTIVE_COMPLETE; params.ep_context = ep; params.cm_info = &ep->cm_info; - ep->state = QED_IWARP_EP_CLOSED; + /* paired with READ_ONCE in destroy_qp */ + smp_store_release(&ep->state, QED_IWARP_EP_CLOSED); switch (fw_return_code) { case IWARP_CONN_ERROR_TCP_CONNECT_INVALID_PACKET: From 43cf40d93fadbb0d3edf0942a4612f8ff67478a1 Mon Sep 17 00:00:00 2001 From: Michal Kalderon Date: Thu, 13 Jun 2019 11:29:41 +0300 Subject: [PATCH 2/4] qed: iWARP - fix uninitialized callback Fix uninitialized variable warning by static checker. Fixes: ae3488ff37dc ("qed: Add ll2 connection for processing unaligned MPA packets") Signed-off-by: Ariel Elior Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_iwarp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c index 4c69adb0b535..099177c6aca2 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c @@ -2640,6 +2640,7 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn, cbs.rx_release_cb = qed_iwarp_ll2_rel_rx_pkt; cbs.tx_comp_cb = qed_iwarp_ll2_comp_tx_pkt; cbs.tx_release_cb = qed_iwarp_ll2_rel_tx_pkt; + cbs.slowpath_cb = NULL; cbs.cookie = p_hwfn; memset(&data, 0, sizeof(data)); From cb94d52b93c74fe1f2595734fabeda9f8ae891ee Mon Sep 17 00:00:00 2001 From: Michal Kalderon Date: Thu, 13 Jun 2019 11:29:42 +0300 Subject: [PATCH 3/4] qed: iWARP - Fix tc for MPA ll2 connection The driver needs to assign a lossless traffic class for the MPA ll2 connection to ensure no packets are dropped when returning from the driver as they will never be re-transmitted by the peer. Fixes: ae3488ff37dc ("qed: Add ll2 connection for processing unaligned MPA packets") Signed-off-by: Ariel Elior Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_iwarp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c index 099177c6aca2..431688c236ed 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c @@ -2712,6 +2712,8 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn, data.input.rx_num_desc = n_ooo_bufs * 2; data.input.tx_num_desc = data.input.rx_num_desc; data.input.tx_max_bds_per_packet = QED_IWARP_MAX_BDS_PER_FPDU; + data.input.tx_tc = PKT_LB_TC; + data.input.tx_dest = QED_LL2_TX_DEST_LB; data.p_connection_handle = &iwarp_info->ll2_mpa_handle; data.input.secondary_queue = true; data.cbs = &cbs; From fbce23a8036d995b17f79c31118d3f549ef44be8 Mon Sep 17 00:00:00 2001 From: Michal Kalderon Date: Thu, 13 Jun 2019 11:29:43 +0300 Subject: [PATCH 4/4] qed: iWARP - Fix default window size to be based on chip The default window size is calculated for best performance based on internal hw buffer sizes. The size differs between the different chips and modes. Fixes: 67b40dccc45f ("qed: Implement iWARP initialization, teardown and qp operations") Signed-off-by: Ariel Elior Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_iwarp.c | 30 +++++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c index 431688c236ed..f380fae8799d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c @@ -63,7 +63,12 @@ struct mpa_v2_hdr { #define MPA_REV2(_mpa_rev) ((_mpa_rev) == MPA_NEGOTIATION_TYPE_ENHANCED) #define QED_IWARP_INVALID_TCP_CID 0xffffffff -#define QED_IWARP_RCV_WND_SIZE_DEF (256 * 1024) + +#define QED_IWARP_RCV_WND_SIZE_DEF_BB_2P (200 * 1024) +#define QED_IWARP_RCV_WND_SIZE_DEF_BB_4P (100 * 1024) +#define QED_IWARP_RCV_WND_SIZE_DEF_AH_2P (150 * 1024) +#define QED_IWARP_RCV_WND_SIZE_DEF_AH_4P (90 * 1024) + #define QED_IWARP_RCV_WND_SIZE_MIN (0xffff) #define TIMESTAMP_HEADER_SIZE (12) #define QED_IWARP_MAX_FIN_RT_DEFAULT (2) @@ -2612,7 +2617,8 @@ qed_iwarp_ll2_alloc_buffers(struct qed_hwfn *p_hwfn, static int qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn, - struct qed_rdma_start_in_params *params) + struct qed_rdma_start_in_params *params, + u32 rcv_wnd_size) { struct qed_iwarp_info *iwarp_info; struct qed_ll2_acquire_data data; @@ -2679,7 +2685,7 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn, data.input.conn_type = QED_LL2_TYPE_OOO; data.input.mtu = params->max_mtu; - n_ooo_bufs = (QED_IWARP_MAX_OOO * QED_IWARP_RCV_WND_SIZE_DEF) / + n_ooo_bufs = (QED_IWARP_MAX_OOO * rcv_wnd_size) / iwarp_info->max_mtu; n_ooo_bufs = min_t(u32, n_ooo_bufs, QED_IWARP_LL2_OOO_MAX_RX_SIZE); @@ -2768,16 +2774,30 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn, return rc; } +static struct { + u32 two_ports; + u32 four_ports; +} qed_iwarp_rcv_wnd_size[MAX_CHIP_IDS] = { + {QED_IWARP_RCV_WND_SIZE_DEF_BB_2P, QED_IWARP_RCV_WND_SIZE_DEF_BB_4P}, + {QED_IWARP_RCV_WND_SIZE_DEF_AH_2P, QED_IWARP_RCV_WND_SIZE_DEF_AH_4P} +}; + int qed_iwarp_setup(struct qed_hwfn *p_hwfn, struct qed_rdma_start_in_params *params) { + struct qed_dev *cdev = p_hwfn->cdev; struct qed_iwarp_info *iwarp_info; + enum chip_ids chip_id; u32 rcv_wnd_size; iwarp_info = &p_hwfn->p_rdma_info->iwarp; iwarp_info->tcp_flags = QED_IWARP_TS_EN; - rcv_wnd_size = QED_IWARP_RCV_WND_SIZE_DEF; + + chip_id = QED_IS_BB(cdev) ? CHIP_BB : CHIP_K2; + rcv_wnd_size = (qed_device_num_ports(cdev) == 4) ? + qed_iwarp_rcv_wnd_size[chip_id].four_ports : + qed_iwarp_rcv_wnd_size[chip_id].two_ports; /* value 0 is used for ilog2(QED_IWARP_RCV_WND_SIZE_MIN) */ iwarp_info->rcv_wnd_scale = ilog2(rcv_wnd_size) - @@ -2800,7 +2820,7 @@ int qed_iwarp_setup(struct qed_hwfn *p_hwfn, qed_iwarp_async_event); qed_ooo_setup(p_hwfn); - return qed_iwarp_ll2_start(p_hwfn, params); + return qed_iwarp_ll2_start(p_hwfn, params, rcv_wnd_size); } int qed_iwarp_stop(struct qed_hwfn *p_hwfn)