167b40dccSKalderon, Michal /* QLogic qed NIC Driver 267b40dccSKalderon, Michal * Copyright (c) 2015-2017 QLogic Corporation 367b40dccSKalderon, Michal * 467b40dccSKalderon, Michal * This software is available to you under a choice of one of two 567b40dccSKalderon, Michal * licenses. You may choose to be licensed under the terms of the GNU 667b40dccSKalderon, Michal * General Public License (GPL) Version 2, available from the file 767b40dccSKalderon, Michal * COPYING in the main directory of this source tree, or the 867b40dccSKalderon, Michal * OpenIB.org BSD license below: 967b40dccSKalderon, Michal * 1067b40dccSKalderon, Michal * Redistribution and use in source and binary forms, with or 1167b40dccSKalderon, Michal * without modification, are permitted provided that the following 1267b40dccSKalderon, Michal * conditions are met: 1367b40dccSKalderon, Michal * 1467b40dccSKalderon, Michal * - Redistributions of source code must retain the above 1567b40dccSKalderon, Michal * copyright notice, this list of conditions and the following 1667b40dccSKalderon, Michal * disclaimer. 1767b40dccSKalderon, Michal * 1867b40dccSKalderon, Michal * - Redistributions in binary form must reproduce the above 1967b40dccSKalderon, Michal * copyright notice, this list of conditions and the following 2067b40dccSKalderon, Michal * disclaimer in the documentation and /or other materials 2167b40dccSKalderon, Michal * provided with the distribution. 2267b40dccSKalderon, Michal * 2367b40dccSKalderon, Michal * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2467b40dccSKalderon, Michal * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2567b40dccSKalderon, Michal * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2667b40dccSKalderon, Michal * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2767b40dccSKalderon, Michal * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 2867b40dccSKalderon, Michal * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2967b40dccSKalderon, Michal * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 3067b40dccSKalderon, Michal * SOFTWARE. 3167b40dccSKalderon, Michal */ 32*b5c29ca7SKalderon, Michal #include <linux/if_ether.h> 33*b5c29ca7SKalderon, Michal #include <linux/if_vlan.h> 3467b40dccSKalderon, Michal #include "qed_cxt.h" 3567b40dccSKalderon, Michal #include "qed_hw.h" 36*b5c29ca7SKalderon, Michal #include "qed_ll2.h" 3767b40dccSKalderon, Michal #include "qed_rdma.h" 3867b40dccSKalderon, Michal #include "qed_reg_addr.h" 3967b40dccSKalderon, Michal #include "qed_sp.h" 4067b40dccSKalderon, Michal 4167b40dccSKalderon, Michal #define QED_IWARP_ORD_DEFAULT 32 4267b40dccSKalderon, Michal #define QED_IWARP_IRD_DEFAULT 32 4367b40dccSKalderon, Michal #define QED_IWARP_RCV_WND_SIZE_DEF (256 * 1024) 4467b40dccSKalderon, Michal #define QED_IWARP_RCV_WND_SIZE_MIN (64 * 1024) 4567b40dccSKalderon, Michal #define QED_IWARP_TS_EN BIT(0) 4667b40dccSKalderon, Michal #define QED_IWARP_PARAM_CRC_NEEDED (1) 4767b40dccSKalderon, Michal #define QED_IWARP_PARAM_P2P (1) 4867b40dccSKalderon, Michal 4967b40dccSKalderon, Michal static int qed_iwarp_async_event(struct qed_hwfn *p_hwfn, 5067b40dccSKalderon, Michal u8 fw_event_code, u16 echo, 5167b40dccSKalderon, Michal union event_ring_data *data, 5267b40dccSKalderon, Michal u8 fw_return_code); 5367b40dccSKalderon, Michal 5467b40dccSKalderon, Michal /* Override devinfo with iWARP specific values */ 5567b40dccSKalderon, Michal void qed_iwarp_init_devinfo(struct qed_hwfn *p_hwfn) 5667b40dccSKalderon, Michal { 5767b40dccSKalderon, Michal struct qed_rdma_device *dev = p_hwfn->p_rdma_info->dev; 5867b40dccSKalderon, Michal 5967b40dccSKalderon, Michal dev->max_inline = IWARP_REQ_MAX_INLINE_DATA_SIZE; 6067b40dccSKalderon, Michal dev->max_qp = min_t(u32, 6167b40dccSKalderon, Michal IWARP_MAX_QPS, 6267b40dccSKalderon, Michal p_hwfn->p_rdma_info->num_qps); 6367b40dccSKalderon, Michal 6467b40dccSKalderon, Michal dev->max_cq = dev->max_qp; 6567b40dccSKalderon, Michal 6667b40dccSKalderon, Michal dev->max_qp_resp_rd_atomic_resc = QED_IWARP_IRD_DEFAULT; 6767b40dccSKalderon, Michal dev->max_qp_req_rd_atomic_resc = QED_IWARP_ORD_DEFAULT; 6867b40dccSKalderon, Michal } 6967b40dccSKalderon, Michal 7067b40dccSKalderon, Michal void qed_iwarp_init_hw(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 7167b40dccSKalderon, Michal { 7267b40dccSKalderon, Michal p_hwfn->rdma_prs_search_reg = PRS_REG_SEARCH_TCP; 7367b40dccSKalderon, Michal qed_wr(p_hwfn, p_ptt, p_hwfn->rdma_prs_search_reg, 1); 7467b40dccSKalderon, Michal p_hwfn->b_rdma_enabled_in_prs = true; 7567b40dccSKalderon, Michal } 7667b40dccSKalderon, Michal 7767b40dccSKalderon, Michal static void qed_iwarp_cid_cleaned(struct qed_hwfn *p_hwfn, u32 cid) 7867b40dccSKalderon, Michal { 7967b40dccSKalderon, Michal cid -= qed_cxt_get_proto_cid_start(p_hwfn, p_hwfn->p_rdma_info->proto); 8067b40dccSKalderon, Michal 8167b40dccSKalderon, Michal spin_lock_bh(&p_hwfn->p_rdma_info->lock); 8267b40dccSKalderon, Michal qed_bmap_release_id(p_hwfn, &p_hwfn->p_rdma_info->cid_map, cid); 8367b40dccSKalderon, Michal spin_unlock_bh(&p_hwfn->p_rdma_info->lock); 8467b40dccSKalderon, Michal } 8567b40dccSKalderon, Michal 8667b40dccSKalderon, Michal static int qed_iwarp_alloc_cid(struct qed_hwfn *p_hwfn, u32 *cid) 8767b40dccSKalderon, Michal { 8867b40dccSKalderon, Michal int rc; 8967b40dccSKalderon, Michal 9067b40dccSKalderon, Michal spin_lock_bh(&p_hwfn->p_rdma_info->lock); 9167b40dccSKalderon, Michal rc = qed_rdma_bmap_alloc_id(p_hwfn, &p_hwfn->p_rdma_info->cid_map, cid); 9267b40dccSKalderon, Michal spin_unlock_bh(&p_hwfn->p_rdma_info->lock); 9367b40dccSKalderon, Michal if (rc) { 9467b40dccSKalderon, Michal DP_NOTICE(p_hwfn, "Failed in allocating iwarp cid\n"); 9567b40dccSKalderon, Michal return rc; 9667b40dccSKalderon, Michal } 9767b40dccSKalderon, Michal *cid += qed_cxt_get_proto_cid_start(p_hwfn, p_hwfn->p_rdma_info->proto); 9867b40dccSKalderon, Michal 9967b40dccSKalderon, Michal rc = qed_cxt_dynamic_ilt_alloc(p_hwfn, QED_ELEM_CXT, *cid); 10067b40dccSKalderon, Michal if (rc) 10167b40dccSKalderon, Michal qed_iwarp_cid_cleaned(p_hwfn, *cid); 10267b40dccSKalderon, Michal 10367b40dccSKalderon, Michal return rc; 10467b40dccSKalderon, Michal } 10567b40dccSKalderon, Michal 10667b40dccSKalderon, Michal int qed_iwarp_create_qp(struct qed_hwfn *p_hwfn, 10767b40dccSKalderon, Michal struct qed_rdma_qp *qp, 10867b40dccSKalderon, Michal struct qed_rdma_create_qp_out_params *out_params) 10967b40dccSKalderon, Michal { 11067b40dccSKalderon, Michal struct iwarp_create_qp_ramrod_data *p_ramrod; 11167b40dccSKalderon, Michal struct qed_sp_init_data init_data; 11267b40dccSKalderon, Michal struct qed_spq_entry *p_ent; 11367b40dccSKalderon, Michal u16 physical_queue; 11467b40dccSKalderon, Michal u32 cid; 11567b40dccSKalderon, Michal int rc; 11667b40dccSKalderon, Michal 11767b40dccSKalderon, Michal qp->shared_queue = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 11867b40dccSKalderon, Michal IWARP_SHARED_QUEUE_PAGE_SIZE, 11967b40dccSKalderon, Michal &qp->shared_queue_phys_addr, 12067b40dccSKalderon, Michal GFP_KERNEL); 12167b40dccSKalderon, Michal if (!qp->shared_queue) 12267b40dccSKalderon, Michal return -ENOMEM; 12367b40dccSKalderon, Michal 12467b40dccSKalderon, Michal out_params->sq_pbl_virt = (u8 *)qp->shared_queue + 12567b40dccSKalderon, Michal IWARP_SHARED_QUEUE_PAGE_SQ_PBL_OFFSET; 12667b40dccSKalderon, Michal out_params->sq_pbl_phys = qp->shared_queue_phys_addr + 12767b40dccSKalderon, Michal IWARP_SHARED_QUEUE_PAGE_SQ_PBL_OFFSET; 12867b40dccSKalderon, Michal out_params->rq_pbl_virt = (u8 *)qp->shared_queue + 12967b40dccSKalderon, Michal IWARP_SHARED_QUEUE_PAGE_RQ_PBL_OFFSET; 13067b40dccSKalderon, Michal out_params->rq_pbl_phys = qp->shared_queue_phys_addr + 13167b40dccSKalderon, Michal IWARP_SHARED_QUEUE_PAGE_RQ_PBL_OFFSET; 13267b40dccSKalderon, Michal 13367b40dccSKalderon, Michal rc = qed_iwarp_alloc_cid(p_hwfn, &cid); 13467b40dccSKalderon, Michal if (rc) 13567b40dccSKalderon, Michal goto err1; 13667b40dccSKalderon, Michal 13767b40dccSKalderon, Michal qp->icid = (u16)cid; 13867b40dccSKalderon, Michal 13967b40dccSKalderon, Michal memset(&init_data, 0, sizeof(init_data)); 14067b40dccSKalderon, Michal init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; 14167b40dccSKalderon, Michal init_data.cid = qp->icid; 14267b40dccSKalderon, Michal init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 14367b40dccSKalderon, Michal 14467b40dccSKalderon, Michal rc = qed_sp_init_request(p_hwfn, &p_ent, 14567b40dccSKalderon, Michal IWARP_RAMROD_CMD_ID_CREATE_QP, 14667b40dccSKalderon, Michal PROTOCOLID_IWARP, &init_data); 14767b40dccSKalderon, Michal if (rc) 14867b40dccSKalderon, Michal goto err2; 14967b40dccSKalderon, Michal 15067b40dccSKalderon, Michal p_ramrod = &p_ent->ramrod.iwarp_create_qp; 15167b40dccSKalderon, Michal 15267b40dccSKalderon, Michal SET_FIELD(p_ramrod->flags, 15367b40dccSKalderon, Michal IWARP_CREATE_QP_RAMROD_DATA_FMR_AND_RESERVED_EN, 15467b40dccSKalderon, Michal qp->fmr_and_reserved_lkey); 15567b40dccSKalderon, Michal 15667b40dccSKalderon, Michal SET_FIELD(p_ramrod->flags, 15767b40dccSKalderon, Michal IWARP_CREATE_QP_RAMROD_DATA_SIGNALED_COMP, qp->signal_all); 15867b40dccSKalderon, Michal 15967b40dccSKalderon, Michal SET_FIELD(p_ramrod->flags, 16067b40dccSKalderon, Michal IWARP_CREATE_QP_RAMROD_DATA_RDMA_RD_EN, 16167b40dccSKalderon, Michal qp->incoming_rdma_read_en); 16267b40dccSKalderon, Michal 16367b40dccSKalderon, Michal SET_FIELD(p_ramrod->flags, 16467b40dccSKalderon, Michal IWARP_CREATE_QP_RAMROD_DATA_RDMA_WR_EN, 16567b40dccSKalderon, Michal qp->incoming_rdma_write_en); 16667b40dccSKalderon, Michal 16767b40dccSKalderon, Michal SET_FIELD(p_ramrod->flags, 16867b40dccSKalderon, Michal IWARP_CREATE_QP_RAMROD_DATA_ATOMIC_EN, 16967b40dccSKalderon, Michal qp->incoming_atomic_en); 17067b40dccSKalderon, Michal 17167b40dccSKalderon, Michal SET_FIELD(p_ramrod->flags, 17267b40dccSKalderon, Michal IWARP_CREATE_QP_RAMROD_DATA_SRQ_FLG, qp->use_srq); 17367b40dccSKalderon, Michal 17467b40dccSKalderon, Michal p_ramrod->pd = qp->pd; 17567b40dccSKalderon, Michal p_ramrod->sq_num_pages = qp->sq_num_pages; 17667b40dccSKalderon, Michal p_ramrod->rq_num_pages = qp->rq_num_pages; 17767b40dccSKalderon, Michal 17867b40dccSKalderon, Michal p_ramrod->qp_handle_for_cqe.hi = cpu_to_le32(qp->qp_handle.hi); 17967b40dccSKalderon, Michal p_ramrod->qp_handle_for_cqe.lo = cpu_to_le32(qp->qp_handle.lo); 18067b40dccSKalderon, Michal 18167b40dccSKalderon, Michal p_ramrod->cq_cid_for_sq = 18267b40dccSKalderon, Michal cpu_to_le32((p_hwfn->hw_info.opaque_fid << 16) | qp->sq_cq_id); 18367b40dccSKalderon, Michal p_ramrod->cq_cid_for_rq = 18467b40dccSKalderon, Michal cpu_to_le32((p_hwfn->hw_info.opaque_fid << 16) | qp->rq_cq_id); 18567b40dccSKalderon, Michal 18667b40dccSKalderon, Michal p_ramrod->dpi = cpu_to_le16(qp->dpi); 18767b40dccSKalderon, Michal 18867b40dccSKalderon, Michal physical_queue = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_OFLD); 18967b40dccSKalderon, Michal p_ramrod->physical_q0 = cpu_to_le16(physical_queue); 19067b40dccSKalderon, Michal physical_queue = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_ACK); 19167b40dccSKalderon, Michal p_ramrod->physical_q1 = cpu_to_le16(physical_queue); 19267b40dccSKalderon, Michal 19367b40dccSKalderon, Michal rc = qed_spq_post(p_hwfn, p_ent, NULL); 19467b40dccSKalderon, Michal if (rc) 19567b40dccSKalderon, Michal goto err2; 19667b40dccSKalderon, Michal 19767b40dccSKalderon, Michal return rc; 19867b40dccSKalderon, Michal 19967b40dccSKalderon, Michal err2: 20067b40dccSKalderon, Michal qed_iwarp_cid_cleaned(p_hwfn, cid); 20167b40dccSKalderon, Michal err1: 20267b40dccSKalderon, Michal dma_free_coherent(&p_hwfn->cdev->pdev->dev, 20367b40dccSKalderon, Michal IWARP_SHARED_QUEUE_PAGE_SIZE, 20467b40dccSKalderon, Michal qp->shared_queue, qp->shared_queue_phys_addr); 20567b40dccSKalderon, Michal 20667b40dccSKalderon, Michal return rc; 20767b40dccSKalderon, Michal } 20867b40dccSKalderon, Michal 20967b40dccSKalderon, Michal static int qed_iwarp_modify_fw(struct qed_hwfn *p_hwfn, struct qed_rdma_qp *qp) 21067b40dccSKalderon, Michal { 21167b40dccSKalderon, Michal struct iwarp_modify_qp_ramrod_data *p_ramrod; 21267b40dccSKalderon, Michal struct qed_sp_init_data init_data; 21367b40dccSKalderon, Michal struct qed_spq_entry *p_ent; 21467b40dccSKalderon, Michal int rc; 21567b40dccSKalderon, Michal 21667b40dccSKalderon, Michal /* Get SPQ entry */ 21767b40dccSKalderon, Michal memset(&init_data, 0, sizeof(init_data)); 21867b40dccSKalderon, Michal init_data.cid = qp->icid; 21967b40dccSKalderon, Michal init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; 22067b40dccSKalderon, Michal init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 22167b40dccSKalderon, Michal 22267b40dccSKalderon, Michal rc = qed_sp_init_request(p_hwfn, &p_ent, 22367b40dccSKalderon, Michal IWARP_RAMROD_CMD_ID_MODIFY_QP, 22467b40dccSKalderon, Michal p_hwfn->p_rdma_info->proto, &init_data); 22567b40dccSKalderon, Michal if (rc) 22667b40dccSKalderon, Michal return rc; 22767b40dccSKalderon, Michal 22867b40dccSKalderon, Michal p_ramrod = &p_ent->ramrod.iwarp_modify_qp; 22967b40dccSKalderon, Michal SET_FIELD(p_ramrod->flags, IWARP_MODIFY_QP_RAMROD_DATA_STATE_TRANS_EN, 23067b40dccSKalderon, Michal 0x1); 23167b40dccSKalderon, Michal if (qp->iwarp_state == QED_IWARP_QP_STATE_CLOSING) 23267b40dccSKalderon, Michal p_ramrod->transition_to_state = IWARP_MODIFY_QP_STATE_CLOSING; 23367b40dccSKalderon, Michal else 23467b40dccSKalderon, Michal p_ramrod->transition_to_state = IWARP_MODIFY_QP_STATE_ERROR; 23567b40dccSKalderon, Michal 23667b40dccSKalderon, Michal rc = qed_spq_post(p_hwfn, p_ent, NULL); 23767b40dccSKalderon, Michal 23867b40dccSKalderon, Michal DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "QP(0x%x)rc=%d\n", qp->icid, rc); 23967b40dccSKalderon, Michal 24067b40dccSKalderon, Michal return rc; 24167b40dccSKalderon, Michal } 24267b40dccSKalderon, Michal 24367b40dccSKalderon, Michal enum qed_iwarp_qp_state qed_roce2iwarp_state(enum qed_roce_qp_state state) 24467b40dccSKalderon, Michal { 24567b40dccSKalderon, Michal switch (state) { 24667b40dccSKalderon, Michal case QED_ROCE_QP_STATE_RESET: 24767b40dccSKalderon, Michal case QED_ROCE_QP_STATE_INIT: 24867b40dccSKalderon, Michal case QED_ROCE_QP_STATE_RTR: 24967b40dccSKalderon, Michal return QED_IWARP_QP_STATE_IDLE; 25067b40dccSKalderon, Michal case QED_ROCE_QP_STATE_RTS: 25167b40dccSKalderon, Michal return QED_IWARP_QP_STATE_RTS; 25267b40dccSKalderon, Michal case QED_ROCE_QP_STATE_SQD: 25367b40dccSKalderon, Michal return QED_IWARP_QP_STATE_CLOSING; 25467b40dccSKalderon, Michal case QED_ROCE_QP_STATE_ERR: 25567b40dccSKalderon, Michal return QED_IWARP_QP_STATE_ERROR; 25667b40dccSKalderon, Michal case QED_ROCE_QP_STATE_SQE: 25767b40dccSKalderon, Michal return QED_IWARP_QP_STATE_TERMINATE; 25867b40dccSKalderon, Michal default: 25967b40dccSKalderon, Michal return QED_IWARP_QP_STATE_ERROR; 26067b40dccSKalderon, Michal } 26167b40dccSKalderon, Michal } 26267b40dccSKalderon, Michal 26367b40dccSKalderon, Michal static enum qed_roce_qp_state 26467b40dccSKalderon, Michal qed_iwarp2roce_state(enum qed_iwarp_qp_state state) 26567b40dccSKalderon, Michal { 26667b40dccSKalderon, Michal switch (state) { 26767b40dccSKalderon, Michal case QED_IWARP_QP_STATE_IDLE: 26867b40dccSKalderon, Michal return QED_ROCE_QP_STATE_INIT; 26967b40dccSKalderon, Michal case QED_IWARP_QP_STATE_RTS: 27067b40dccSKalderon, Michal return QED_ROCE_QP_STATE_RTS; 27167b40dccSKalderon, Michal case QED_IWARP_QP_STATE_TERMINATE: 27267b40dccSKalderon, Michal return QED_ROCE_QP_STATE_SQE; 27367b40dccSKalderon, Michal case QED_IWARP_QP_STATE_CLOSING: 27467b40dccSKalderon, Michal return QED_ROCE_QP_STATE_SQD; 27567b40dccSKalderon, Michal case QED_IWARP_QP_STATE_ERROR: 27667b40dccSKalderon, Michal return QED_ROCE_QP_STATE_ERR; 27767b40dccSKalderon, Michal default: 27867b40dccSKalderon, Michal return QED_ROCE_QP_STATE_ERR; 27967b40dccSKalderon, Michal } 28067b40dccSKalderon, Michal } 28167b40dccSKalderon, Michal 28267b40dccSKalderon, Michal const char *iwarp_state_names[] = { 28367b40dccSKalderon, Michal "IDLE", 28467b40dccSKalderon, Michal "RTS", 28567b40dccSKalderon, Michal "TERMINATE", 28667b40dccSKalderon, Michal "CLOSING", 28767b40dccSKalderon, Michal "ERROR", 28867b40dccSKalderon, Michal }; 28967b40dccSKalderon, Michal 29067b40dccSKalderon, Michal int 29167b40dccSKalderon, Michal qed_iwarp_modify_qp(struct qed_hwfn *p_hwfn, 29267b40dccSKalderon, Michal struct qed_rdma_qp *qp, 29367b40dccSKalderon, Michal enum qed_iwarp_qp_state new_state, bool internal) 29467b40dccSKalderon, Michal { 29567b40dccSKalderon, Michal enum qed_iwarp_qp_state prev_iw_state; 29667b40dccSKalderon, Michal bool modify_fw = false; 29767b40dccSKalderon, Michal int rc = 0; 29867b40dccSKalderon, Michal 29967b40dccSKalderon, Michal /* modify QP can be called from upper-layer or as a result of async 30067b40dccSKalderon, Michal * RST/FIN... therefore need to protect 30167b40dccSKalderon, Michal */ 30267b40dccSKalderon, Michal spin_lock_bh(&p_hwfn->p_rdma_info->iwarp.qp_lock); 30367b40dccSKalderon, Michal prev_iw_state = qp->iwarp_state; 30467b40dccSKalderon, Michal 30567b40dccSKalderon, Michal if (prev_iw_state == new_state) { 30667b40dccSKalderon, Michal spin_unlock_bh(&p_hwfn->p_rdma_info->iwarp.qp_lock); 30767b40dccSKalderon, Michal return 0; 30867b40dccSKalderon, Michal } 30967b40dccSKalderon, Michal 31067b40dccSKalderon, Michal switch (prev_iw_state) { 31167b40dccSKalderon, Michal case QED_IWARP_QP_STATE_IDLE: 31267b40dccSKalderon, Michal switch (new_state) { 31367b40dccSKalderon, Michal case QED_IWARP_QP_STATE_RTS: 31467b40dccSKalderon, Michal qp->iwarp_state = QED_IWARP_QP_STATE_RTS; 31567b40dccSKalderon, Michal break; 31667b40dccSKalderon, Michal case QED_IWARP_QP_STATE_ERROR: 31767b40dccSKalderon, Michal qp->iwarp_state = QED_IWARP_QP_STATE_ERROR; 31867b40dccSKalderon, Michal if (!internal) 31967b40dccSKalderon, Michal modify_fw = true; 32067b40dccSKalderon, Michal break; 32167b40dccSKalderon, Michal default: 32267b40dccSKalderon, Michal break; 32367b40dccSKalderon, Michal } 32467b40dccSKalderon, Michal break; 32567b40dccSKalderon, Michal case QED_IWARP_QP_STATE_RTS: 32667b40dccSKalderon, Michal switch (new_state) { 32767b40dccSKalderon, Michal case QED_IWARP_QP_STATE_CLOSING: 32867b40dccSKalderon, Michal if (!internal) 32967b40dccSKalderon, Michal modify_fw = true; 33067b40dccSKalderon, Michal 33167b40dccSKalderon, Michal qp->iwarp_state = QED_IWARP_QP_STATE_CLOSING; 33267b40dccSKalderon, Michal break; 33367b40dccSKalderon, Michal case QED_IWARP_QP_STATE_ERROR: 33467b40dccSKalderon, Michal if (!internal) 33567b40dccSKalderon, Michal modify_fw = true; 33667b40dccSKalderon, Michal qp->iwarp_state = QED_IWARP_QP_STATE_ERROR; 33767b40dccSKalderon, Michal break; 33867b40dccSKalderon, Michal default: 33967b40dccSKalderon, Michal break; 34067b40dccSKalderon, Michal } 34167b40dccSKalderon, Michal break; 34267b40dccSKalderon, Michal case QED_IWARP_QP_STATE_ERROR: 34367b40dccSKalderon, Michal switch (new_state) { 34467b40dccSKalderon, Michal case QED_IWARP_QP_STATE_IDLE: 34567b40dccSKalderon, Michal 34667b40dccSKalderon, Michal qp->iwarp_state = new_state; 34767b40dccSKalderon, Michal break; 34867b40dccSKalderon, Michal case QED_IWARP_QP_STATE_CLOSING: 34967b40dccSKalderon, Michal /* could happen due to race... do nothing.... */ 35067b40dccSKalderon, Michal break; 35167b40dccSKalderon, Michal default: 35267b40dccSKalderon, Michal rc = -EINVAL; 35367b40dccSKalderon, Michal } 35467b40dccSKalderon, Michal break; 35567b40dccSKalderon, Michal case QED_IWARP_QP_STATE_TERMINATE: 35667b40dccSKalderon, Michal case QED_IWARP_QP_STATE_CLOSING: 35767b40dccSKalderon, Michal qp->iwarp_state = new_state; 35867b40dccSKalderon, Michal break; 35967b40dccSKalderon, Michal default: 36067b40dccSKalderon, Michal break; 36167b40dccSKalderon, Michal } 36267b40dccSKalderon, Michal 36367b40dccSKalderon, Michal DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "QP(0x%x) %s --> %s%s\n", 36467b40dccSKalderon, Michal qp->icid, 36567b40dccSKalderon, Michal iwarp_state_names[prev_iw_state], 36667b40dccSKalderon, Michal iwarp_state_names[qp->iwarp_state], 36767b40dccSKalderon, Michal internal ? "internal" : ""); 36867b40dccSKalderon, Michal 36967b40dccSKalderon, Michal spin_unlock_bh(&p_hwfn->p_rdma_info->iwarp.qp_lock); 37067b40dccSKalderon, Michal 37167b40dccSKalderon, Michal if (modify_fw) 37267b40dccSKalderon, Michal rc = qed_iwarp_modify_fw(p_hwfn, qp); 37367b40dccSKalderon, Michal 37467b40dccSKalderon, Michal return rc; 37567b40dccSKalderon, Michal } 37667b40dccSKalderon, Michal 37767b40dccSKalderon, Michal int qed_iwarp_fw_destroy(struct qed_hwfn *p_hwfn, struct qed_rdma_qp *qp) 37867b40dccSKalderon, Michal { 37967b40dccSKalderon, Michal struct qed_sp_init_data init_data; 38067b40dccSKalderon, Michal struct qed_spq_entry *p_ent; 38167b40dccSKalderon, Michal int rc; 38267b40dccSKalderon, Michal 38367b40dccSKalderon, Michal /* Get SPQ entry */ 38467b40dccSKalderon, Michal memset(&init_data, 0, sizeof(init_data)); 38567b40dccSKalderon, Michal init_data.cid = qp->icid; 38667b40dccSKalderon, Michal init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; 38767b40dccSKalderon, Michal init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 38867b40dccSKalderon, Michal 38967b40dccSKalderon, Michal rc = qed_sp_init_request(p_hwfn, &p_ent, 39067b40dccSKalderon, Michal IWARP_RAMROD_CMD_ID_DESTROY_QP, 39167b40dccSKalderon, Michal p_hwfn->p_rdma_info->proto, &init_data); 39267b40dccSKalderon, Michal if (rc) 39367b40dccSKalderon, Michal return rc; 39467b40dccSKalderon, Michal 39567b40dccSKalderon, Michal rc = qed_spq_post(p_hwfn, p_ent, NULL); 39667b40dccSKalderon, Michal 39767b40dccSKalderon, Michal DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "QP(0x%x) rc = %d\n", qp->icid, rc); 39867b40dccSKalderon, Michal 39967b40dccSKalderon, Michal return rc; 40067b40dccSKalderon, Michal } 40167b40dccSKalderon, Michal 40267b40dccSKalderon, Michal int qed_iwarp_destroy_qp(struct qed_hwfn *p_hwfn, struct qed_rdma_qp *qp) 40367b40dccSKalderon, Michal { 40467b40dccSKalderon, Michal int rc = 0; 40567b40dccSKalderon, Michal 40667b40dccSKalderon, Michal if (qp->iwarp_state != QED_IWARP_QP_STATE_ERROR) { 40767b40dccSKalderon, Michal rc = qed_iwarp_modify_qp(p_hwfn, qp, 40867b40dccSKalderon, Michal QED_IWARP_QP_STATE_ERROR, false); 40967b40dccSKalderon, Michal if (rc) 41067b40dccSKalderon, Michal return rc; 41167b40dccSKalderon, Michal } 41267b40dccSKalderon, Michal 41367b40dccSKalderon, Michal rc = qed_iwarp_fw_destroy(p_hwfn, qp); 41467b40dccSKalderon, Michal 41567b40dccSKalderon, Michal if (qp->shared_queue) 41667b40dccSKalderon, Michal dma_free_coherent(&p_hwfn->cdev->pdev->dev, 41767b40dccSKalderon, Michal IWARP_SHARED_QUEUE_PAGE_SIZE, 41867b40dccSKalderon, Michal qp->shared_queue, qp->shared_queue_phys_addr); 41967b40dccSKalderon, Michal 42067b40dccSKalderon, Michal return rc; 42167b40dccSKalderon, Michal } 42267b40dccSKalderon, Michal 42367b40dccSKalderon, Michal #define QED_IWARP_MAX_CID_CLEAN_TIME 100 42467b40dccSKalderon, Michal #define QED_IWARP_MAX_NO_PROGRESS_CNT 5 42567b40dccSKalderon, Michal 42667b40dccSKalderon, Michal /* This function waits for all the bits of a bmap to be cleared, as long as 42767b40dccSKalderon, Michal * there is progress ( i.e. the number of bits left to be cleared decreases ) 42867b40dccSKalderon, Michal * the function continues. 42967b40dccSKalderon, Michal */ 43067b40dccSKalderon, Michal static int 43167b40dccSKalderon, Michal qed_iwarp_wait_cid_map_cleared(struct qed_hwfn *p_hwfn, struct qed_bmap *bmap) 43267b40dccSKalderon, Michal { 43367b40dccSKalderon, Michal int prev_weight = 0; 43467b40dccSKalderon, Michal int wait_count = 0; 43567b40dccSKalderon, Michal int weight = 0; 43667b40dccSKalderon, Michal 43767b40dccSKalderon, Michal weight = bitmap_weight(bmap->bitmap, bmap->max_count); 43867b40dccSKalderon, Michal prev_weight = weight; 43967b40dccSKalderon, Michal 44067b40dccSKalderon, Michal while (weight) { 44167b40dccSKalderon, Michal msleep(QED_IWARP_MAX_CID_CLEAN_TIME); 44267b40dccSKalderon, Michal 44367b40dccSKalderon, Michal weight = bitmap_weight(bmap->bitmap, bmap->max_count); 44467b40dccSKalderon, Michal 44567b40dccSKalderon, Michal if (prev_weight == weight) { 44667b40dccSKalderon, Michal wait_count++; 44767b40dccSKalderon, Michal } else { 44867b40dccSKalderon, Michal prev_weight = weight; 44967b40dccSKalderon, Michal wait_count = 0; 45067b40dccSKalderon, Michal } 45167b40dccSKalderon, Michal 45267b40dccSKalderon, Michal if (wait_count > QED_IWARP_MAX_NO_PROGRESS_CNT) { 45367b40dccSKalderon, Michal DP_NOTICE(p_hwfn, 45467b40dccSKalderon, Michal "%s bitmap wait timed out (%d cids pending)\n", 45567b40dccSKalderon, Michal bmap->name, weight); 45667b40dccSKalderon, Michal return -EBUSY; 45767b40dccSKalderon, Michal } 45867b40dccSKalderon, Michal } 45967b40dccSKalderon, Michal return 0; 46067b40dccSKalderon, Michal } 46167b40dccSKalderon, Michal 46267b40dccSKalderon, Michal static int qed_iwarp_wait_for_all_cids(struct qed_hwfn *p_hwfn) 46367b40dccSKalderon, Michal { 46467b40dccSKalderon, Michal /* Now wait for all cids to be completed */ 46567b40dccSKalderon, Michal return qed_iwarp_wait_cid_map_cleared(p_hwfn, 46667b40dccSKalderon, Michal &p_hwfn->p_rdma_info->cid_map); 46767b40dccSKalderon, Michal } 46867b40dccSKalderon, Michal 46967b40dccSKalderon, Michal int qed_iwarp_alloc(struct qed_hwfn *p_hwfn) 47067b40dccSKalderon, Michal { 47167b40dccSKalderon, Michal spin_lock_init(&p_hwfn->p_rdma_info->iwarp.iw_lock); 47267b40dccSKalderon, Michal 47367b40dccSKalderon, Michal return 0; 47467b40dccSKalderon, Michal } 47567b40dccSKalderon, Michal 47667b40dccSKalderon, Michal void qed_iwarp_resc_free(struct qed_hwfn *p_hwfn) 47767b40dccSKalderon, Michal { 47867b40dccSKalderon, Michal } 47967b40dccSKalderon, Michal 480*b5c29ca7SKalderon, Michal static int 481*b5c29ca7SKalderon, Michal qed_iwarp_ll2_post_rx(struct qed_hwfn *p_hwfn, 482*b5c29ca7SKalderon, Michal struct qed_iwarp_ll2_buff *buf, u8 handle) 483*b5c29ca7SKalderon, Michal { 484*b5c29ca7SKalderon, Michal int rc; 485*b5c29ca7SKalderon, Michal 486*b5c29ca7SKalderon, Michal rc = qed_ll2_post_rx_buffer(p_hwfn, handle, buf->data_phys_addr, 487*b5c29ca7SKalderon, Michal (u16)buf->buff_size, buf, 1); 488*b5c29ca7SKalderon, Michal if (rc) { 489*b5c29ca7SKalderon, Michal DP_NOTICE(p_hwfn, 490*b5c29ca7SKalderon, Michal "Failed to repost rx buffer to ll2 rc = %d, handle=%d\n", 491*b5c29ca7SKalderon, Michal rc, handle); 492*b5c29ca7SKalderon, Michal dma_free_coherent(&p_hwfn->cdev->pdev->dev, buf->buff_size, 493*b5c29ca7SKalderon, Michal buf->data, buf->data_phys_addr); 494*b5c29ca7SKalderon, Michal kfree(buf); 495*b5c29ca7SKalderon, Michal } 496*b5c29ca7SKalderon, Michal 497*b5c29ca7SKalderon, Michal return rc; 498*b5c29ca7SKalderon, Michal } 499*b5c29ca7SKalderon, Michal 500*b5c29ca7SKalderon, Michal static void 501*b5c29ca7SKalderon, Michal qed_iwarp_ll2_comp_syn_pkt(void *cxt, struct qed_ll2_comp_rx_data *data) 502*b5c29ca7SKalderon, Michal { 503*b5c29ca7SKalderon, Michal struct qed_iwarp_ll2_buff *buf = data->cookie; 504*b5c29ca7SKalderon, Michal struct qed_hwfn *p_hwfn = cxt; 505*b5c29ca7SKalderon, Michal 506*b5c29ca7SKalderon, Michal if (GET_FIELD(data->parse_flags, 507*b5c29ca7SKalderon, Michal PARSING_AND_ERR_FLAGS_L4CHKSMWASCALCULATED) && 508*b5c29ca7SKalderon, Michal GET_FIELD(data->parse_flags, PARSING_AND_ERR_FLAGS_L4CHKSMERROR)) { 509*b5c29ca7SKalderon, Michal DP_NOTICE(p_hwfn, "Syn packet received with checksum error\n"); 510*b5c29ca7SKalderon, Michal goto err; 511*b5c29ca7SKalderon, Michal } 512*b5c29ca7SKalderon, Michal 513*b5c29ca7SKalderon, Michal /* Process SYN packet - added later on in series */ 514*b5c29ca7SKalderon, Michal 515*b5c29ca7SKalderon, Michal err: 516*b5c29ca7SKalderon, Michal qed_iwarp_ll2_post_rx(p_hwfn, buf, 517*b5c29ca7SKalderon, Michal p_hwfn->p_rdma_info->iwarp.ll2_syn_handle); 518*b5c29ca7SKalderon, Michal } 519*b5c29ca7SKalderon, Michal 520*b5c29ca7SKalderon, Michal static void qed_iwarp_ll2_rel_rx_pkt(void *cxt, u8 connection_handle, 521*b5c29ca7SKalderon, Michal void *cookie, dma_addr_t rx_buf_addr, 522*b5c29ca7SKalderon, Michal bool b_last_packet) 523*b5c29ca7SKalderon, Michal { 524*b5c29ca7SKalderon, Michal struct qed_iwarp_ll2_buff *buffer = cookie; 525*b5c29ca7SKalderon, Michal struct qed_hwfn *p_hwfn = cxt; 526*b5c29ca7SKalderon, Michal 527*b5c29ca7SKalderon, Michal dma_free_coherent(&p_hwfn->cdev->pdev->dev, buffer->buff_size, 528*b5c29ca7SKalderon, Michal buffer->data, buffer->data_phys_addr); 529*b5c29ca7SKalderon, Michal kfree(buffer); 530*b5c29ca7SKalderon, Michal } 531*b5c29ca7SKalderon, Michal 532*b5c29ca7SKalderon, Michal static void qed_iwarp_ll2_comp_tx_pkt(void *cxt, u8 connection_handle, 533*b5c29ca7SKalderon, Michal void *cookie, dma_addr_t first_frag_addr, 534*b5c29ca7SKalderon, Michal bool b_last_fragment, bool b_last_packet) 535*b5c29ca7SKalderon, Michal { 536*b5c29ca7SKalderon, Michal struct qed_iwarp_ll2_buff *buffer = cookie; 537*b5c29ca7SKalderon, Michal struct qed_hwfn *p_hwfn = cxt; 538*b5c29ca7SKalderon, Michal 539*b5c29ca7SKalderon, Michal /* this was originally an rx packet, post it back */ 540*b5c29ca7SKalderon, Michal qed_iwarp_ll2_post_rx(p_hwfn, buffer, connection_handle); 541*b5c29ca7SKalderon, Michal } 542*b5c29ca7SKalderon, Michal 543*b5c29ca7SKalderon, Michal static void qed_iwarp_ll2_rel_tx_pkt(void *cxt, u8 connection_handle, 544*b5c29ca7SKalderon, Michal void *cookie, dma_addr_t first_frag_addr, 545*b5c29ca7SKalderon, Michal bool b_last_fragment, bool b_last_packet) 546*b5c29ca7SKalderon, Michal { 547*b5c29ca7SKalderon, Michal struct qed_iwarp_ll2_buff *buffer = cookie; 548*b5c29ca7SKalderon, Michal struct qed_hwfn *p_hwfn = cxt; 549*b5c29ca7SKalderon, Michal 550*b5c29ca7SKalderon, Michal if (!buffer) 551*b5c29ca7SKalderon, Michal return; 552*b5c29ca7SKalderon, Michal 553*b5c29ca7SKalderon, Michal dma_free_coherent(&p_hwfn->cdev->pdev->dev, buffer->buff_size, 554*b5c29ca7SKalderon, Michal buffer->data, buffer->data_phys_addr); 555*b5c29ca7SKalderon, Michal 556*b5c29ca7SKalderon, Michal kfree(buffer); 557*b5c29ca7SKalderon, Michal } 558*b5c29ca7SKalderon, Michal 559*b5c29ca7SKalderon, Michal static int qed_iwarp_ll2_stop(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 560*b5c29ca7SKalderon, Michal { 561*b5c29ca7SKalderon, Michal struct qed_iwarp_info *iwarp_info = &p_hwfn->p_rdma_info->iwarp; 562*b5c29ca7SKalderon, Michal int rc = 0; 563*b5c29ca7SKalderon, Michal 564*b5c29ca7SKalderon, Michal if (iwarp_info->ll2_syn_handle != QED_IWARP_HANDLE_INVAL) { 565*b5c29ca7SKalderon, Michal rc = qed_ll2_terminate_connection(p_hwfn, 566*b5c29ca7SKalderon, Michal iwarp_info->ll2_syn_handle); 567*b5c29ca7SKalderon, Michal if (rc) 568*b5c29ca7SKalderon, Michal DP_INFO(p_hwfn, "Failed to terminate syn connection\n"); 569*b5c29ca7SKalderon, Michal 570*b5c29ca7SKalderon, Michal qed_ll2_release_connection(p_hwfn, iwarp_info->ll2_syn_handle); 571*b5c29ca7SKalderon, Michal iwarp_info->ll2_syn_handle = QED_IWARP_HANDLE_INVAL; 572*b5c29ca7SKalderon, Michal } 573*b5c29ca7SKalderon, Michal 574*b5c29ca7SKalderon, Michal qed_llh_remove_mac_filter(p_hwfn, 575*b5c29ca7SKalderon, Michal p_ptt, p_hwfn->p_rdma_info->iwarp.mac_addr); 576*b5c29ca7SKalderon, Michal return rc; 577*b5c29ca7SKalderon, Michal } 578*b5c29ca7SKalderon, Michal 579*b5c29ca7SKalderon, Michal static int 580*b5c29ca7SKalderon, Michal qed_iwarp_ll2_alloc_buffers(struct qed_hwfn *p_hwfn, 581*b5c29ca7SKalderon, Michal int num_rx_bufs, int buff_size, u8 ll2_handle) 582*b5c29ca7SKalderon, Michal { 583*b5c29ca7SKalderon, Michal struct qed_iwarp_ll2_buff *buffer; 584*b5c29ca7SKalderon, Michal int rc = 0; 585*b5c29ca7SKalderon, Michal int i; 586*b5c29ca7SKalderon, Michal 587*b5c29ca7SKalderon, Michal for (i = 0; i < num_rx_bufs; i++) { 588*b5c29ca7SKalderon, Michal buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); 589*b5c29ca7SKalderon, Michal if (!buffer) { 590*b5c29ca7SKalderon, Michal rc = -ENOMEM; 591*b5c29ca7SKalderon, Michal break; 592*b5c29ca7SKalderon, Michal } 593*b5c29ca7SKalderon, Michal 594*b5c29ca7SKalderon, Michal buffer->data = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, 595*b5c29ca7SKalderon, Michal buff_size, 596*b5c29ca7SKalderon, Michal &buffer->data_phys_addr, 597*b5c29ca7SKalderon, Michal GFP_KERNEL); 598*b5c29ca7SKalderon, Michal if (!buffer->data) { 599*b5c29ca7SKalderon, Michal kfree(buffer); 600*b5c29ca7SKalderon, Michal rc = -ENOMEM; 601*b5c29ca7SKalderon, Michal break; 602*b5c29ca7SKalderon, Michal } 603*b5c29ca7SKalderon, Michal 604*b5c29ca7SKalderon, Michal buffer->buff_size = buff_size; 605*b5c29ca7SKalderon, Michal rc = qed_iwarp_ll2_post_rx(p_hwfn, buffer, ll2_handle); 606*b5c29ca7SKalderon, Michal if (rc) 607*b5c29ca7SKalderon, Michal /* buffers will be deallocated by qed_ll2 */ 608*b5c29ca7SKalderon, Michal break; 609*b5c29ca7SKalderon, Michal } 610*b5c29ca7SKalderon, Michal return rc; 611*b5c29ca7SKalderon, Michal } 612*b5c29ca7SKalderon, Michal 613*b5c29ca7SKalderon, Michal #define QED_IWARP_MAX_BUF_SIZE(mtu) \ 614*b5c29ca7SKalderon, Michal ALIGN((mtu) + ETH_HLEN + 2 * VLAN_HLEN + 2 + ETH_CACHE_LINE_SIZE, \ 615*b5c29ca7SKalderon, Michal ETH_CACHE_LINE_SIZE) 616*b5c29ca7SKalderon, Michal 617*b5c29ca7SKalderon, Michal static int 618*b5c29ca7SKalderon, Michal qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn, 619*b5c29ca7SKalderon, Michal struct qed_rdma_start_in_params *params, 620*b5c29ca7SKalderon, Michal struct qed_ptt *p_ptt) 621*b5c29ca7SKalderon, Michal { 622*b5c29ca7SKalderon, Michal struct qed_iwarp_info *iwarp_info; 623*b5c29ca7SKalderon, Michal struct qed_ll2_acquire_data data; 624*b5c29ca7SKalderon, Michal struct qed_ll2_cbs cbs; 625*b5c29ca7SKalderon, Michal int rc = 0; 626*b5c29ca7SKalderon, Michal 627*b5c29ca7SKalderon, Michal iwarp_info = &p_hwfn->p_rdma_info->iwarp; 628*b5c29ca7SKalderon, Michal iwarp_info->ll2_syn_handle = QED_IWARP_HANDLE_INVAL; 629*b5c29ca7SKalderon, Michal 630*b5c29ca7SKalderon, Michal iwarp_info->max_mtu = params->max_mtu; 631*b5c29ca7SKalderon, Michal 632*b5c29ca7SKalderon, Michal ether_addr_copy(p_hwfn->p_rdma_info->iwarp.mac_addr, params->mac_addr); 633*b5c29ca7SKalderon, Michal 634*b5c29ca7SKalderon, Michal rc = qed_llh_add_mac_filter(p_hwfn, p_ptt, params->mac_addr); 635*b5c29ca7SKalderon, Michal if (rc) 636*b5c29ca7SKalderon, Michal return rc; 637*b5c29ca7SKalderon, Michal 638*b5c29ca7SKalderon, Michal /* Start SYN connection */ 639*b5c29ca7SKalderon, Michal cbs.rx_comp_cb = qed_iwarp_ll2_comp_syn_pkt; 640*b5c29ca7SKalderon, Michal cbs.rx_release_cb = qed_iwarp_ll2_rel_rx_pkt; 641*b5c29ca7SKalderon, Michal cbs.tx_comp_cb = qed_iwarp_ll2_comp_tx_pkt; 642*b5c29ca7SKalderon, Michal cbs.tx_release_cb = qed_iwarp_ll2_rel_tx_pkt; 643*b5c29ca7SKalderon, Michal cbs.cookie = p_hwfn; 644*b5c29ca7SKalderon, Michal 645*b5c29ca7SKalderon, Michal memset(&data, 0, sizeof(data)); 646*b5c29ca7SKalderon, Michal data.input.conn_type = QED_LL2_TYPE_IWARP; 647*b5c29ca7SKalderon, Michal data.input.mtu = QED_IWARP_MAX_SYN_PKT_SIZE; 648*b5c29ca7SKalderon, Michal data.input.rx_num_desc = QED_IWARP_LL2_SYN_RX_SIZE; 649*b5c29ca7SKalderon, Michal data.input.tx_num_desc = QED_IWARP_LL2_SYN_TX_SIZE; 650*b5c29ca7SKalderon, Michal data.input.tx_max_bds_per_packet = 1; /* will never be fragmented */ 651*b5c29ca7SKalderon, Michal data.input.tx_tc = PKT_LB_TC; 652*b5c29ca7SKalderon, Michal data.input.tx_dest = QED_LL2_TX_DEST_LB; 653*b5c29ca7SKalderon, Michal data.p_connection_handle = &iwarp_info->ll2_syn_handle; 654*b5c29ca7SKalderon, Michal data.cbs = &cbs; 655*b5c29ca7SKalderon, Michal 656*b5c29ca7SKalderon, Michal rc = qed_ll2_acquire_connection(p_hwfn, &data); 657*b5c29ca7SKalderon, Michal if (rc) { 658*b5c29ca7SKalderon, Michal DP_NOTICE(p_hwfn, "Failed to acquire LL2 connection\n"); 659*b5c29ca7SKalderon, Michal qed_llh_remove_mac_filter(p_hwfn, p_ptt, params->mac_addr); 660*b5c29ca7SKalderon, Michal return rc; 661*b5c29ca7SKalderon, Michal } 662*b5c29ca7SKalderon, Michal 663*b5c29ca7SKalderon, Michal rc = qed_ll2_establish_connection(p_hwfn, iwarp_info->ll2_syn_handle); 664*b5c29ca7SKalderon, Michal if (rc) { 665*b5c29ca7SKalderon, Michal DP_NOTICE(p_hwfn, "Failed to establish LL2 connection\n"); 666*b5c29ca7SKalderon, Michal goto err; 667*b5c29ca7SKalderon, Michal } 668*b5c29ca7SKalderon, Michal 669*b5c29ca7SKalderon, Michal rc = qed_iwarp_ll2_alloc_buffers(p_hwfn, 670*b5c29ca7SKalderon, Michal QED_IWARP_LL2_SYN_RX_SIZE, 671*b5c29ca7SKalderon, Michal QED_IWARP_MAX_SYN_PKT_SIZE, 672*b5c29ca7SKalderon, Michal iwarp_info->ll2_syn_handle); 673*b5c29ca7SKalderon, Michal if (rc) 674*b5c29ca7SKalderon, Michal goto err; 675*b5c29ca7SKalderon, Michal 676*b5c29ca7SKalderon, Michal return rc; 677*b5c29ca7SKalderon, Michal err: 678*b5c29ca7SKalderon, Michal qed_iwarp_ll2_stop(p_hwfn, p_ptt); 679*b5c29ca7SKalderon, Michal 680*b5c29ca7SKalderon, Michal return rc; 681*b5c29ca7SKalderon, Michal } 682*b5c29ca7SKalderon, Michal 68367b40dccSKalderon, Michal int qed_iwarp_setup(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, 68467b40dccSKalderon, Michal struct qed_rdma_start_in_params *params) 68567b40dccSKalderon, Michal { 68667b40dccSKalderon, Michal struct qed_iwarp_info *iwarp_info; 68767b40dccSKalderon, Michal u32 rcv_wnd_size; 68867b40dccSKalderon, Michal 68967b40dccSKalderon, Michal iwarp_info = &p_hwfn->p_rdma_info->iwarp; 69067b40dccSKalderon, Michal 69167b40dccSKalderon, Michal iwarp_info->tcp_flags = QED_IWARP_TS_EN; 69267b40dccSKalderon, Michal rcv_wnd_size = QED_IWARP_RCV_WND_SIZE_DEF; 69367b40dccSKalderon, Michal 69467b40dccSKalderon, Michal /* value 0 is used for ilog2(QED_IWARP_RCV_WND_SIZE_MIN) */ 69567b40dccSKalderon, Michal iwarp_info->rcv_wnd_scale = ilog2(rcv_wnd_size) - 69667b40dccSKalderon, Michal ilog2(QED_IWARP_RCV_WND_SIZE_MIN); 69767b40dccSKalderon, Michal iwarp_info->crc_needed = QED_IWARP_PARAM_CRC_NEEDED; 69867b40dccSKalderon, Michal iwarp_info->mpa_rev = MPA_NEGOTIATION_TYPE_ENHANCED; 69967b40dccSKalderon, Michal 70067b40dccSKalderon, Michal iwarp_info->peer2peer = QED_IWARP_PARAM_P2P; 70167b40dccSKalderon, Michal 70267b40dccSKalderon, Michal spin_lock_init(&p_hwfn->p_rdma_info->iwarp.qp_lock); 70367b40dccSKalderon, Michal 70467b40dccSKalderon, Michal qed_spq_register_async_cb(p_hwfn, PROTOCOLID_IWARP, 70567b40dccSKalderon, Michal qed_iwarp_async_event); 70667b40dccSKalderon, Michal 707*b5c29ca7SKalderon, Michal return qed_iwarp_ll2_start(p_hwfn, params, p_ptt); 70867b40dccSKalderon, Michal } 70967b40dccSKalderon, Michal 71067b40dccSKalderon, Michal int qed_iwarp_stop(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 71167b40dccSKalderon, Michal { 71267b40dccSKalderon, Michal int rc; 71367b40dccSKalderon, Michal 71467b40dccSKalderon, Michal rc = qed_iwarp_wait_for_all_cids(p_hwfn); 71567b40dccSKalderon, Michal if (rc) 71667b40dccSKalderon, Michal return rc; 71767b40dccSKalderon, Michal 71867b40dccSKalderon, Michal qed_spq_unregister_async_cb(p_hwfn, PROTOCOLID_IWARP); 71967b40dccSKalderon, Michal 720*b5c29ca7SKalderon, Michal return qed_iwarp_ll2_stop(p_hwfn, p_ptt); 72167b40dccSKalderon, Michal } 72267b40dccSKalderon, Michal 72367b40dccSKalderon, Michal static int qed_iwarp_async_event(struct qed_hwfn *p_hwfn, 72467b40dccSKalderon, Michal u8 fw_event_code, u16 echo, 72567b40dccSKalderon, Michal union event_ring_data *data, 72667b40dccSKalderon, Michal u8 fw_return_code) 72767b40dccSKalderon, Michal { 72867b40dccSKalderon, Michal return 0; 72967b40dccSKalderon, Michal } 73067b40dccSKalderon, Michal 73167b40dccSKalderon, Michal void 73267b40dccSKalderon, Michal qed_iwarp_query_qp(struct qed_rdma_qp *qp, 73367b40dccSKalderon, Michal struct qed_rdma_query_qp_out_params *out_params) 73467b40dccSKalderon, Michal { 73567b40dccSKalderon, Michal out_params->state = qed_iwarp2roce_state(qp->iwarp_state); 73667b40dccSKalderon, Michal } 737