Path: blob/master/drivers/infiniband/hw/nes/nes_verbs.c
15112 views
/*1* Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.2*3* This software is available to you under a choice of one of two4* licenses. You may choose to be licensed under the terms of the GNU5* General Public License (GPL) Version 2, available from the file6* COPYING in the main directory of this source tree, or the7* OpenIB.org BSD license below:8*9* Redistribution and use in source and binary forms, with or10* without modification, are permitted provided that the following11* conditions are met:12*13* - Redistributions of source code must retain the above14* copyright notice, this list of conditions and the following15* disclaimer.16*17* - Redistributions in binary form must reproduce the above18* copyright notice, this list of conditions and the following19* disclaimer in the documentation and/or other materials20* provided with the distribution.21*22* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,23* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF24* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND25* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS26* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN27* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN28* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE29* SOFTWARE.30*31*/3233#include <linux/module.h>34#include <linux/moduleparam.h>35#include <linux/random.h>36#include <linux/highmem.h>37#include <linux/slab.h>38#include <asm/byteorder.h>3940#include <rdma/ib_verbs.h>41#include <rdma/iw_cm.h>42#include <rdma/ib_user_verbs.h>4344#include "nes.h"4546#include <rdma/ib_umem.h>4748atomic_t mod_qp_timouts;49atomic_t qps_created;50atomic_t sw_qps_destroyed;5152static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev);5354/**55* nes_alloc_mw56*/57static struct ib_mw *nes_alloc_mw(struct ib_pd *ibpd) {58struct nes_pd *nespd = to_nespd(ibpd);59struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);60struct nes_device *nesdev = nesvnic->nesdev;61struct nes_adapter *nesadapter = nesdev->nesadapter;62struct nes_cqp_request *cqp_request;63struct nes_mr *nesmr;64struct ib_mw *ibmw;65struct nes_hw_cqp_wqe *cqp_wqe;66int ret;67u32 stag;68u32 stag_index = 0;69u32 next_stag_index = 0;70u32 driver_key = 0;71u8 stag_key = 0;7273get_random_bytes(&next_stag_index, sizeof(next_stag_index));74stag_key = (u8)next_stag_index;7576driver_key = 0;7778next_stag_index >>= 8;79next_stag_index %= nesadapter->max_mr;8081ret = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,82nesadapter->max_mr, &stag_index, &next_stag_index);83if (ret) {84return ERR_PTR(ret);85}8687nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);88if (!nesmr) {89nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);90return ERR_PTR(-ENOMEM);91}9293stag = stag_index << 8;94stag |= driver_key;95stag += (u32)stag_key;9697nes_debug(NES_DBG_MR, "Registering STag 0x%08X, index = 0x%08X\n",98stag, stag_index);99100/* Register the region with the adapter */101cqp_request = nes_get_cqp_request(nesdev);102if (cqp_request == NULL) {103kfree(nesmr);104nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);105return ERR_PTR(-ENOMEM);106}107108cqp_request->waiting = 1;109cqp_wqe = &cqp_request->cqp_wqe;110111cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] =112cpu_to_le32( NES_CQP_ALLOCATE_STAG | NES_CQP_STAG_RIGHTS_REMOTE_READ |113NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_VA_TO |114NES_CQP_STAG_REM_ACC_EN);115116nes_fill_init_cqp_wqe(cqp_wqe, nesdev);117set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX, (nespd->pd_id & 0x00007fff));118set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag);119120atomic_set(&cqp_request->refcount, 2);121nes_post_cqp_request(nesdev, cqp_request);122123/* Wait for CQP */124ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),125NES_EVENT_TIMEOUT);126nes_debug(NES_DBG_MR, "Register STag 0x%08X completed, wait_event_timeout ret = %u,"127" CQP Major:Minor codes = 0x%04X:0x%04X.\n",128stag, ret, cqp_request->major_code, cqp_request->minor_code);129if ((!ret) || (cqp_request->major_code)) {130nes_put_cqp_request(nesdev, cqp_request);131kfree(nesmr);132nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);133if (!ret) {134return ERR_PTR(-ETIME);135} else {136return ERR_PTR(-ENOMEM);137}138}139nes_put_cqp_request(nesdev, cqp_request);140141nesmr->ibmw.rkey = stag;142nesmr->mode = IWNES_MEMREG_TYPE_MW;143ibmw = &nesmr->ibmw;144nesmr->pbl_4k = 0;145nesmr->pbls_used = 0;146147return ibmw;148}149150151/**152* nes_dealloc_mw153*/154static int nes_dealloc_mw(struct ib_mw *ibmw)155{156struct nes_mr *nesmr = to_nesmw(ibmw);157struct nes_vnic *nesvnic = to_nesvnic(ibmw->device);158struct nes_device *nesdev = nesvnic->nesdev;159struct nes_adapter *nesadapter = nesdev->nesadapter;160struct nes_hw_cqp_wqe *cqp_wqe;161struct nes_cqp_request *cqp_request;162int err = 0;163int ret;164165/* Deallocate the window with the adapter */166cqp_request = nes_get_cqp_request(nesdev);167if (cqp_request == NULL) {168nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n");169return -ENOMEM;170}171cqp_request->waiting = 1;172cqp_wqe = &cqp_request->cqp_wqe;173nes_fill_init_cqp_wqe(cqp_wqe, nesdev);174set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, NES_CQP_DEALLOCATE_STAG);175set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, ibmw->rkey);176177atomic_set(&cqp_request->refcount, 2);178nes_post_cqp_request(nesdev, cqp_request);179180/* Wait for CQP */181nes_debug(NES_DBG_MR, "Waiting for deallocate STag 0x%08X to complete.\n",182ibmw->rkey);183ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done),184NES_EVENT_TIMEOUT);185nes_debug(NES_DBG_MR, "Deallocate STag completed, wait_event_timeout ret = %u,"186" CQP Major:Minor codes = 0x%04X:0x%04X.\n",187ret, cqp_request->major_code, cqp_request->minor_code);188if (!ret)189err = -ETIME;190else if (cqp_request->major_code)191err = -EIO;192193nes_put_cqp_request(nesdev, cqp_request);194195nes_free_resource(nesadapter, nesadapter->allocated_mrs,196(ibmw->rkey & 0x0fffff00) >> 8);197kfree(nesmr);198199return err;200}201202203/**204* nes_bind_mw205*/206static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw,207struct ib_mw_bind *ibmw_bind)208{209u64 u64temp;210struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);211struct nes_device *nesdev = nesvnic->nesdev;212/* struct nes_mr *nesmr = to_nesmw(ibmw); */213struct nes_qp *nesqp = to_nesqp(ibqp);214struct nes_hw_qp_wqe *wqe;215unsigned long flags = 0;216u32 head;217u32 wqe_misc = 0;218u32 qsize;219220if (nesqp->ibqp_state > IB_QPS_RTS)221return -EINVAL;222223spin_lock_irqsave(&nesqp->lock, flags);224225head = nesqp->hwqp.sq_head;226qsize = nesqp->hwqp.sq_tail;227228/* Check for SQ overflow */229if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) {230spin_unlock_irqrestore(&nesqp->lock, flags);231return -ENOMEM;232}233234wqe = &nesqp->hwqp.sq_vbase[head];235/* nes_debug(NES_DBG_MR, "processing sq wqe at %p, head = %u.\n", wqe, head); */236nes_fill_init_qp_wqe(wqe, nesqp, head);237u64temp = ibmw_bind->wr_id;238set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX, u64temp);239wqe_misc = NES_IWARP_SQ_OP_BIND;240241wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;242243if (ibmw_bind->send_flags & IB_SEND_SIGNALED)244wqe_misc |= NES_IWARP_SQ_WQE_SIGNALED_COMPL;245246if (ibmw_bind->mw_access_flags & IB_ACCESS_REMOTE_WRITE) {247wqe_misc |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE;248}249if (ibmw_bind->mw_access_flags & IB_ACCESS_REMOTE_READ) {250wqe_misc |= NES_CQP_STAG_RIGHTS_REMOTE_READ;251}252253set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_MISC_IDX, wqe_misc);254set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_MR_IDX, ibmw_bind->mr->lkey);255set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_MW_IDX, ibmw->rkey);256set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_LENGTH_LOW_IDX,257ibmw_bind->length);258wqe->wqe_words[NES_IWARP_SQ_BIND_WQE_LENGTH_HIGH_IDX] = 0;259u64temp = (u64)ibmw_bind->addr;260set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_VA_FBO_LOW_IDX, u64temp);261262head++;263if (head >= qsize)264head = 0;265266nesqp->hwqp.sq_head = head;267barrier();268269nes_write32(nesdev->regs+NES_WQE_ALLOC,270(1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);271272spin_unlock_irqrestore(&nesqp->lock, flags);273274return 0;275}276277278/*279* nes_alloc_fast_mr280*/281static int alloc_fast_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd,282u32 stag, u32 page_count)283{284struct nes_hw_cqp_wqe *cqp_wqe;285struct nes_cqp_request *cqp_request;286unsigned long flags;287int ret;288struct nes_adapter *nesadapter = nesdev->nesadapter;289u32 opcode = 0;290u16 major_code;291u64 region_length = page_count * PAGE_SIZE;292293294cqp_request = nes_get_cqp_request(nesdev);295if (cqp_request == NULL) {296nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n");297return -ENOMEM;298}299nes_debug(NES_DBG_MR, "alloc_fast_reg_mr: page_count = %d, "300"region_length = %llu\n",301page_count, region_length);302cqp_request->waiting = 1;303cqp_wqe = &cqp_request->cqp_wqe;304305spin_lock_irqsave(&nesadapter->pbl_lock, flags);306if (nesadapter->free_4kpbl > 0) {307nesadapter->free_4kpbl--;308spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);309} else {310/* No 4kpbl's available: */311spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);312nes_debug(NES_DBG_MR, "Out of Pbls\n");313nes_free_cqp_request(nesdev, cqp_request);314return -ENOMEM;315}316317opcode = NES_CQP_ALLOCATE_STAG | NES_CQP_STAG_MR |318NES_CQP_STAG_PBL_BLK_SIZE | NES_CQP_STAG_VA_TO |319NES_CQP_STAG_REM_ACC_EN;320/*321* The current OFED API does not support the zero based TO option.322* If added then need to changed the NES_CQP_STAG_VA* option. Also,323* the API does not support that ability to have the MR set for local324* access only when created and not allow the SQ op to override. Given325* this the remote enable must be set here.326*/327328nes_fill_init_cqp_wqe(cqp_wqe, nesdev);329set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);330set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX, 1);331332cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] =333cpu_to_le32((u32)(region_length >> 8) & 0xff000000);334cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] |=335cpu_to_le32(nespd->pd_id & 0x00007fff);336337set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag);338set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_VA_LOW_IDX, 0);339set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_LOW_IDX, 0);340set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PA_LOW_IDX, 0);341set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_LEN_IDX, (page_count * 8));342cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_STAG_PBL_BLK_SIZE);343barrier();344345atomic_set(&cqp_request->refcount, 2);346nes_post_cqp_request(nesdev, cqp_request);347348/* Wait for CQP */349ret = wait_event_timeout(cqp_request->waitq,350(0 != cqp_request->request_done),351NES_EVENT_TIMEOUT);352353nes_debug(NES_DBG_MR, "Allocate STag 0x%08X completed, "354"wait_event_timeout ret = %u, CQP Major:Minor codes = "355"0x%04X:0x%04X.\n", stag, ret, cqp_request->major_code,356cqp_request->minor_code);357major_code = cqp_request->major_code;358nes_put_cqp_request(nesdev, cqp_request);359360if (!ret || major_code) {361spin_lock_irqsave(&nesadapter->pbl_lock, flags);362nesadapter->free_4kpbl++;363spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);364}365366if (!ret)367return -ETIME;368else if (major_code)369return -EIO;370return 0;371}372373/*374* nes_alloc_fast_reg_mr375*/376static struct ib_mr *nes_alloc_fast_reg_mr(struct ib_pd *ibpd, int max_page_list_len)377{378struct nes_pd *nespd = to_nespd(ibpd);379struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);380struct nes_device *nesdev = nesvnic->nesdev;381struct nes_adapter *nesadapter = nesdev->nesadapter;382383u32 next_stag_index;384u8 stag_key = 0;385u32 driver_key = 0;386int err = 0;387u32 stag_index = 0;388struct nes_mr *nesmr;389u32 stag;390int ret;391struct ib_mr *ibmr;392/*393* Note: Set to always use a fixed length single page entry PBL. This is to allow394* for the fast_reg_mr operation to always know the size of the PBL.395*/396if (max_page_list_len > (NES_4K_PBL_CHUNK_SIZE / sizeof(u64)))397return ERR_PTR(-E2BIG);398399get_random_bytes(&next_stag_index, sizeof(next_stag_index));400stag_key = (u8)next_stag_index;401next_stag_index >>= 8;402next_stag_index %= nesadapter->max_mr;403404err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,405nesadapter->max_mr, &stag_index,406&next_stag_index);407if (err)408return ERR_PTR(err);409410nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);411if (!nesmr) {412nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);413return ERR_PTR(-ENOMEM);414}415416stag = stag_index << 8;417stag |= driver_key;418stag += (u32)stag_key;419420nes_debug(NES_DBG_MR, "Allocating STag 0x%08X index = 0x%08X\n",421stag, stag_index);422423ret = alloc_fast_reg_mr(nesdev, nespd, stag, max_page_list_len);424425if (ret == 0) {426nesmr->ibmr.rkey = stag;427nesmr->ibmr.lkey = stag;428nesmr->mode = IWNES_MEMREG_TYPE_FMEM;429ibmr = &nesmr->ibmr;430} else {431kfree(nesmr);432nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);433ibmr = ERR_PTR(-ENOMEM);434}435return ibmr;436}437438/*439* nes_alloc_fast_reg_page_list440*/441static struct ib_fast_reg_page_list *nes_alloc_fast_reg_page_list(442struct ib_device *ibdev,443int page_list_len)444{445struct nes_vnic *nesvnic = to_nesvnic(ibdev);446struct nes_device *nesdev = nesvnic->nesdev;447struct ib_fast_reg_page_list *pifrpl;448struct nes_ib_fast_reg_page_list *pnesfrpl;449450if (page_list_len > (NES_4K_PBL_CHUNK_SIZE / sizeof(u64)))451return ERR_PTR(-E2BIG);452/*453* Allocate the ib_fast_reg_page_list structure, the454* nes_fast_bpl structure, and the PLB table.455*/456pnesfrpl = kmalloc(sizeof(struct nes_ib_fast_reg_page_list) +457page_list_len * sizeof(u64), GFP_KERNEL);458459if (!pnesfrpl)460return ERR_PTR(-ENOMEM);461462pifrpl = &pnesfrpl->ibfrpl;463pifrpl->page_list = &pnesfrpl->pbl;464pifrpl->max_page_list_len = page_list_len;465/*466* Allocate the WQE PBL467*/468pnesfrpl->nes_wqe_pbl.kva = pci_alloc_consistent(nesdev->pcidev,469page_list_len * sizeof(u64),470&pnesfrpl->nes_wqe_pbl.paddr);471472if (!pnesfrpl->nes_wqe_pbl.kva) {473kfree(pnesfrpl);474return ERR_PTR(-ENOMEM);475}476nes_debug(NES_DBG_MR, "nes_alloc_fast_reg_pbl: nes_frpl = %p, "477"ibfrpl = %p, ibfrpl.page_list = %p, pbl.kva = %p, "478"pbl.paddr = %llx\n", pnesfrpl, &pnesfrpl->ibfrpl,479pnesfrpl->ibfrpl.page_list, pnesfrpl->nes_wqe_pbl.kva,480(unsigned long long) pnesfrpl->nes_wqe_pbl.paddr);481482return pifrpl;483}484485/*486* nes_free_fast_reg_page_list487*/488static void nes_free_fast_reg_page_list(struct ib_fast_reg_page_list *pifrpl)489{490struct nes_vnic *nesvnic = to_nesvnic(pifrpl->device);491struct nes_device *nesdev = nesvnic->nesdev;492struct nes_ib_fast_reg_page_list *pnesfrpl;493494pnesfrpl = container_of(pifrpl, struct nes_ib_fast_reg_page_list, ibfrpl);495/*496* Free the WQE PBL.497*/498pci_free_consistent(nesdev->pcidev,499pifrpl->max_page_list_len * sizeof(u64),500pnesfrpl->nes_wqe_pbl.kva,501pnesfrpl->nes_wqe_pbl.paddr);502/*503* Free the PBL structure504*/505kfree(pnesfrpl);506}507508/**509* nes_query_device510*/511static int nes_query_device(struct ib_device *ibdev, struct ib_device_attr *props)512{513struct nes_vnic *nesvnic = to_nesvnic(ibdev);514struct nes_device *nesdev = nesvnic->nesdev;515struct nes_ib_device *nesibdev = nesvnic->nesibdev;516517memset(props, 0, sizeof(*props));518memcpy(&props->sys_image_guid, nesvnic->netdev->dev_addr, 6);519520props->fw_ver = nesdev->nesadapter->firmware_version;521props->device_cap_flags = nesdev->nesadapter->device_cap_flags;522props->vendor_id = nesdev->nesadapter->vendor_id;523props->vendor_part_id = nesdev->nesadapter->vendor_part_id;524props->hw_ver = nesdev->nesadapter->hw_rev;525props->max_mr_size = 0x80000000;526props->max_qp = nesibdev->max_qp;527props->max_qp_wr = nesdev->nesadapter->max_qp_wr - 2;528props->max_sge = nesdev->nesadapter->max_sge;529props->max_cq = nesibdev->max_cq;530props->max_cqe = nesdev->nesadapter->max_cqe;531props->max_mr = nesibdev->max_mr;532props->max_mw = nesibdev->max_mr;533props->max_pd = nesibdev->max_pd;534props->max_sge_rd = 1;535switch (nesdev->nesadapter->max_irrq_wr) {536case 0:537props->max_qp_rd_atom = 2;538break;539case 1:540props->max_qp_rd_atom = 8;541break;542case 2:543props->max_qp_rd_atom = 32;544break;545case 3:546props->max_qp_rd_atom = 64;547break;548default:549props->max_qp_rd_atom = 0;550}551props->max_qp_init_rd_atom = props->max_qp_rd_atom;552props->atomic_cap = IB_ATOMIC_NONE;553props->max_map_per_fmr = 1;554555return 0;556}557558559/**560* nes_query_port561*/562static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr *props)563{564struct nes_vnic *nesvnic = to_nesvnic(ibdev);565struct net_device *netdev = nesvnic->netdev;566567memset(props, 0, sizeof(*props));568569props->max_mtu = IB_MTU_4096;570571if (netdev->mtu >= 4096)572props->active_mtu = IB_MTU_4096;573else if (netdev->mtu >= 2048)574props->active_mtu = IB_MTU_2048;575else if (netdev->mtu >= 1024)576props->active_mtu = IB_MTU_1024;577else if (netdev->mtu >= 512)578props->active_mtu = IB_MTU_512;579else580props->active_mtu = IB_MTU_256;581582props->lid = 1;583props->lmc = 0;584props->sm_lid = 0;585props->sm_sl = 0;586if (netif_queue_stopped(netdev))587props->state = IB_PORT_DOWN;588else if (nesvnic->linkup)589props->state = IB_PORT_ACTIVE;590else591props->state = IB_PORT_DOWN;592props->phys_state = 0;593props->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_REINIT_SUP |594IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP;595props->gid_tbl_len = 1;596props->pkey_tbl_len = 1;597props->qkey_viol_cntr = 0;598props->active_width = IB_WIDTH_4X;599props->active_speed = 1;600props->max_msg_sz = 0x80000000;601602return 0;603}604605606/**607* nes_modify_port608*/609static int nes_modify_port(struct ib_device *ibdev, u8 port,610int port_modify_mask, struct ib_port_modify *props)611{612return 0;613}614615616/**617* nes_query_pkey618*/619static int nes_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)620{621*pkey = 0;622return 0;623}624625626/**627* nes_query_gid628*/629static int nes_query_gid(struct ib_device *ibdev, u8 port,630int index, union ib_gid *gid)631{632struct nes_vnic *nesvnic = to_nesvnic(ibdev);633634memset(&(gid->raw[0]), 0, sizeof(gid->raw));635memcpy(&(gid->raw[0]), nesvnic->netdev->dev_addr, 6);636637return 0;638}639640641/**642* nes_alloc_ucontext - Allocate the user context data structure. This keeps track643* of all objects associated with a particular user-mode client.644*/645static struct ib_ucontext *nes_alloc_ucontext(struct ib_device *ibdev,646struct ib_udata *udata)647{648struct nes_vnic *nesvnic = to_nesvnic(ibdev);649struct nes_device *nesdev = nesvnic->nesdev;650struct nes_adapter *nesadapter = nesdev->nesadapter;651struct nes_alloc_ucontext_req req;652struct nes_alloc_ucontext_resp uresp;653struct nes_ucontext *nes_ucontext;654struct nes_ib_device *nesibdev = nesvnic->nesibdev;655656657if (ib_copy_from_udata(&req, udata, sizeof(struct nes_alloc_ucontext_req))) {658printk(KERN_ERR PFX "Invalid structure size on allocate user context.\n");659return ERR_PTR(-EINVAL);660}661662if (req.userspace_ver != NES_ABI_USERSPACE_VER) {663printk(KERN_ERR PFX "Invalid userspace driver version detected. Detected version %d, should be %d\n",664req.userspace_ver, NES_ABI_USERSPACE_VER);665return ERR_PTR(-EINVAL);666}667668669memset(&uresp, 0, sizeof uresp);670671uresp.max_qps = nesibdev->max_qp;672uresp.max_pds = nesibdev->max_pd;673uresp.wq_size = nesdev->nesadapter->max_qp_wr * 2;674uresp.virtwq = nesadapter->virtwq;675uresp.kernel_ver = NES_ABI_KERNEL_VER;676677nes_ucontext = kzalloc(sizeof *nes_ucontext, GFP_KERNEL);678if (!nes_ucontext)679return ERR_PTR(-ENOMEM);680681nes_ucontext->nesdev = nesdev;682nes_ucontext->mmap_wq_offset = uresp.max_pds;683nes_ucontext->mmap_cq_offset = nes_ucontext->mmap_wq_offset +684((sizeof(struct nes_hw_qp_wqe) * uresp.max_qps * 2) + PAGE_SIZE-1) /685PAGE_SIZE;686687688if (ib_copy_to_udata(udata, &uresp, sizeof uresp)) {689kfree(nes_ucontext);690return ERR_PTR(-EFAULT);691}692693INIT_LIST_HEAD(&nes_ucontext->cq_reg_mem_list);694INIT_LIST_HEAD(&nes_ucontext->qp_reg_mem_list);695atomic_set(&nes_ucontext->usecnt, 1);696return &nes_ucontext->ibucontext;697}698699700/**701* nes_dealloc_ucontext702*/703static int nes_dealloc_ucontext(struct ib_ucontext *context)704{705/* struct nes_vnic *nesvnic = to_nesvnic(context->device); */706/* struct nes_device *nesdev = nesvnic->nesdev; */707struct nes_ucontext *nes_ucontext = to_nesucontext(context);708709if (!atomic_dec_and_test(&nes_ucontext->usecnt))710return 0;711kfree(nes_ucontext);712return 0;713}714715716/**717* nes_mmap718*/719static int nes_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)720{721unsigned long index;722struct nes_vnic *nesvnic = to_nesvnic(context->device);723struct nes_device *nesdev = nesvnic->nesdev;724/* struct nes_adapter *nesadapter = nesdev->nesadapter; */725struct nes_ucontext *nes_ucontext;726struct nes_qp *nesqp;727728nes_ucontext = to_nesucontext(context);729730731if (vma->vm_pgoff >= nes_ucontext->mmap_wq_offset) {732index = (vma->vm_pgoff - nes_ucontext->mmap_wq_offset) * PAGE_SIZE;733index /= ((sizeof(struct nes_hw_qp_wqe) * nesdev->nesadapter->max_qp_wr * 2) +734PAGE_SIZE-1) & (~(PAGE_SIZE-1));735if (!test_bit(index, nes_ucontext->allocated_wqs)) {736nes_debug(NES_DBG_MMAP, "wq %lu not allocated\n", index);737return -EFAULT;738}739nesqp = nes_ucontext->mmap_nesqp[index];740if (nesqp == NULL) {741nes_debug(NES_DBG_MMAP, "wq %lu has a NULL QP base.\n", index);742return -EFAULT;743}744if (remap_pfn_range(vma, vma->vm_start,745virt_to_phys(nesqp->hwqp.sq_vbase) >> PAGE_SHIFT,746vma->vm_end - vma->vm_start,747vma->vm_page_prot)) {748nes_debug(NES_DBG_MMAP, "remap_pfn_range failed.\n");749return -EAGAIN;750}751vma->vm_private_data = nesqp;752return 0;753} else {754index = vma->vm_pgoff;755if (!test_bit(index, nes_ucontext->allocated_doorbells))756return -EFAULT;757758vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);759if (io_remap_pfn_range(vma, vma->vm_start,760(nesdev->doorbell_start +761((nes_ucontext->mmap_db_index[index] - nesdev->base_doorbell_index) * 4096))762>> PAGE_SHIFT, PAGE_SIZE, vma->vm_page_prot))763return -EAGAIN;764vma->vm_private_data = nes_ucontext;765return 0;766}767768return -ENOSYS;769}770771772/**773* nes_alloc_pd774*/775static struct ib_pd *nes_alloc_pd(struct ib_device *ibdev,776struct ib_ucontext *context, struct ib_udata *udata)777{778struct nes_pd *nespd;779struct nes_vnic *nesvnic = to_nesvnic(ibdev);780struct nes_device *nesdev = nesvnic->nesdev;781struct nes_adapter *nesadapter = nesdev->nesadapter;782struct nes_ucontext *nesucontext;783struct nes_alloc_pd_resp uresp;784u32 pd_num = 0;785int err;786787nes_debug(NES_DBG_PD, "nesvnic=%p, netdev=%p %s, ibdev=%p, context=%p, netdev refcnt=%u\n",788nesvnic, nesdev->netdev[0], nesdev->netdev[0]->name, ibdev, context,789netdev_refcnt_read(nesvnic->netdev));790791err = nes_alloc_resource(nesadapter, nesadapter->allocated_pds,792nesadapter->max_pd, &pd_num, &nesadapter->next_pd);793if (err) {794return ERR_PTR(err);795}796797nespd = kzalloc(sizeof (struct nes_pd), GFP_KERNEL);798if (!nespd) {799nes_free_resource(nesadapter, nesadapter->allocated_pds, pd_num);800return ERR_PTR(-ENOMEM);801}802803nes_debug(NES_DBG_PD, "Allocating PD (%p) for ib device %s\n",804nespd, nesvnic->nesibdev->ibdev.name);805806nespd->pd_id = (pd_num << (PAGE_SHIFT-12)) + nesadapter->base_pd;807808if (context) {809nesucontext = to_nesucontext(context);810nespd->mmap_db_index = find_next_zero_bit(nesucontext->allocated_doorbells,811NES_MAX_USER_DB_REGIONS, nesucontext->first_free_db);812nes_debug(NES_DBG_PD, "find_first_zero_biton doorbells returned %u, mapping pd_id %u.\n",813nespd->mmap_db_index, nespd->pd_id);814if (nespd->mmap_db_index >= NES_MAX_USER_DB_REGIONS) {815nes_debug(NES_DBG_PD, "mmap_db_index > MAX\n");816nes_free_resource(nesadapter, nesadapter->allocated_pds, pd_num);817kfree(nespd);818return ERR_PTR(-ENOMEM);819}820821uresp.pd_id = nespd->pd_id;822uresp.mmap_db_index = nespd->mmap_db_index;823if (ib_copy_to_udata(udata, &uresp, sizeof (struct nes_alloc_pd_resp))) {824nes_free_resource(nesadapter, nesadapter->allocated_pds, pd_num);825kfree(nespd);826return ERR_PTR(-EFAULT);827}828829set_bit(nespd->mmap_db_index, nesucontext->allocated_doorbells);830nesucontext->mmap_db_index[nespd->mmap_db_index] = nespd->pd_id;831nesucontext->first_free_db = nespd->mmap_db_index + 1;832}833834nes_debug(NES_DBG_PD, "PD%u structure located @%p.\n", nespd->pd_id, nespd);835return &nespd->ibpd;836}837838839/**840* nes_dealloc_pd841*/842static int nes_dealloc_pd(struct ib_pd *ibpd)843{844struct nes_ucontext *nesucontext;845struct nes_pd *nespd = to_nespd(ibpd);846struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);847struct nes_device *nesdev = nesvnic->nesdev;848struct nes_adapter *nesadapter = nesdev->nesadapter;849850if ((ibpd->uobject) && (ibpd->uobject->context)) {851nesucontext = to_nesucontext(ibpd->uobject->context);852nes_debug(NES_DBG_PD, "Clearing bit %u from allocated doorbells\n",853nespd->mmap_db_index);854clear_bit(nespd->mmap_db_index, nesucontext->allocated_doorbells);855nesucontext->mmap_db_index[nespd->mmap_db_index] = 0;856if (nesucontext->first_free_db > nespd->mmap_db_index) {857nesucontext->first_free_db = nespd->mmap_db_index;858}859}860861nes_debug(NES_DBG_PD, "Deallocating PD%u structure located @%p.\n",862nespd->pd_id, nespd);863nes_free_resource(nesadapter, nesadapter->allocated_pds,864(nespd->pd_id-nesadapter->base_pd)>>(PAGE_SHIFT-12));865kfree(nespd);866867return 0;868}869870871/**872* nes_create_ah873*/874static struct ib_ah *nes_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)875{876return ERR_PTR(-ENOSYS);877}878879880/**881* nes_destroy_ah882*/883static int nes_destroy_ah(struct ib_ah *ah)884{885return -ENOSYS;886}887888889/**890* nes_get_encoded_size891*/892static inline u8 nes_get_encoded_size(int *size)893{894u8 encoded_size = 0;895if (*size <= 32) {896*size = 32;897encoded_size = 1;898} else if (*size <= 128) {899*size = 128;900encoded_size = 2;901} else if (*size <= 512) {902*size = 512;903encoded_size = 3;904}905return (encoded_size);906}907908909910/**911* nes_setup_virt_qp912*/913static int nes_setup_virt_qp(struct nes_qp *nesqp, struct nes_pbl *nespbl,914struct nes_vnic *nesvnic, int sq_size, int rq_size)915{916unsigned long flags;917void *mem;918__le64 *pbl = NULL;919__le64 *tpbl;920__le64 *pblbuffer;921struct nes_device *nesdev = nesvnic->nesdev;922struct nes_adapter *nesadapter = nesdev->nesadapter;923u32 pbl_entries;924u8 rq_pbl_entries;925u8 sq_pbl_entries;926927pbl_entries = nespbl->pbl_size >> 3;928nes_debug(NES_DBG_QP, "Userspace PBL, pbl_size=%u, pbl_entries = %d pbl_vbase=%p, pbl_pbase=%lx\n",929nespbl->pbl_size, pbl_entries,930(void *)nespbl->pbl_vbase,931(unsigned long) nespbl->pbl_pbase);932pbl = (__le64 *) nespbl->pbl_vbase; /* points to first pbl entry */933/* now lets set the sq_vbase as well as rq_vbase addrs we will assign */934/* the first pbl to be fro the rq_vbase... */935rq_pbl_entries = (rq_size * sizeof(struct nes_hw_qp_wqe)) >> 12;936sq_pbl_entries = (sq_size * sizeof(struct nes_hw_qp_wqe)) >> 12;937nesqp->hwqp.sq_pbase = (le32_to_cpu(((__le32 *)pbl)[0])) | ((u64)((le32_to_cpu(((__le32 *)pbl)[1]))) << 32);938if (!nespbl->page) {939nes_debug(NES_DBG_QP, "QP nespbl->page is NULL \n");940kfree(nespbl);941return -ENOMEM;942}943944nesqp->hwqp.sq_vbase = kmap(nespbl->page);945nesqp->page = nespbl->page;946if (!nesqp->hwqp.sq_vbase) {947nes_debug(NES_DBG_QP, "QP sq_vbase kmap failed\n");948kfree(nespbl);949return -ENOMEM;950}951952/* Now to get to sq.. we need to calculate how many */953/* PBL entries were used by the rq.. */954pbl += sq_pbl_entries;955nesqp->hwqp.rq_pbase = (le32_to_cpu(((__le32 *)pbl)[0])) | ((u64)((le32_to_cpu(((__le32 *)pbl)[1]))) << 32);956/* nesqp->hwqp.rq_vbase = bus_to_virt(*pbl); */957/*nesqp->hwqp.rq_vbase = phys_to_virt(*pbl); */958959nes_debug(NES_DBG_QP, "QP sq_vbase= %p sq_pbase=%lx rq_vbase=%p rq_pbase=%lx\n",960nesqp->hwqp.sq_vbase, (unsigned long) nesqp->hwqp.sq_pbase,961nesqp->hwqp.rq_vbase, (unsigned long) nesqp->hwqp.rq_pbase);962spin_lock_irqsave(&nesadapter->pbl_lock, flags);963if (!nesadapter->free_256pbl) {964pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,965nespbl->pbl_pbase);966spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);967kunmap(nesqp->page);968kfree(nespbl);969return -ENOMEM;970}971nesadapter->free_256pbl--;972spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);973974nesqp->pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 256, &nesqp->pbl_pbase);975pblbuffer = nesqp->pbl_vbase;976if (!nesqp->pbl_vbase) {977/* memory allocated during nes_reg_user_mr() */978pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,979nespbl->pbl_pbase);980kfree(nespbl);981spin_lock_irqsave(&nesadapter->pbl_lock, flags);982nesadapter->free_256pbl++;983spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);984kunmap(nesqp->page);985return -ENOMEM;986}987memset(nesqp->pbl_vbase, 0, 256);988/* fill in the page address in the pbl buffer.. */989tpbl = pblbuffer + 16;990pbl = (__le64 *)nespbl->pbl_vbase;991while (sq_pbl_entries--)992*tpbl++ = *pbl++;993tpbl = pblbuffer;994while (rq_pbl_entries--)995*tpbl++ = *pbl++;996997/* done with memory allocated during nes_reg_user_mr() */998pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,999nespbl->pbl_pbase);1000kfree(nespbl);10011002nesqp->qp_mem_size =1003max((u32)sizeof(struct nes_qp_context), ((u32)256)) + 256; /* this is Q2 */1004/* Round up to a multiple of a page */1005nesqp->qp_mem_size += PAGE_SIZE - 1;1006nesqp->qp_mem_size &= ~(PAGE_SIZE - 1);10071008mem = pci_alloc_consistent(nesdev->pcidev, nesqp->qp_mem_size,1009&nesqp->hwqp.q2_pbase);10101011if (!mem) {1012pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase);1013nesqp->pbl_vbase = NULL;1014spin_lock_irqsave(&nesadapter->pbl_lock, flags);1015nesadapter->free_256pbl++;1016spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);1017kunmap(nesqp->page);1018return -ENOMEM;1019}1020nesqp->sq_kmapped = 1;1021nesqp->hwqp.q2_vbase = mem;1022mem += 256;1023memset(nesqp->hwqp.q2_vbase, 0, 256);1024nesqp->nesqp_context = mem;1025memset(nesqp->nesqp_context, 0, sizeof(*nesqp->nesqp_context));1026nesqp->nesqp_context_pbase = nesqp->hwqp.q2_pbase + 256;10271028return 0;1029}103010311032/**1033* nes_setup_mmap_qp1034*/1035static int nes_setup_mmap_qp(struct nes_qp *nesqp, struct nes_vnic *nesvnic,1036int sq_size, int rq_size)1037{1038void *mem;1039struct nes_device *nesdev = nesvnic->nesdev;10401041nesqp->qp_mem_size = (sizeof(struct nes_hw_qp_wqe) * sq_size) +1042(sizeof(struct nes_hw_qp_wqe) * rq_size) +1043max((u32)sizeof(struct nes_qp_context), ((u32)256)) +1044256; /* this is Q2 */1045/* Round up to a multiple of a page */1046nesqp->qp_mem_size += PAGE_SIZE - 1;1047nesqp->qp_mem_size &= ~(PAGE_SIZE - 1);10481049mem = pci_alloc_consistent(nesdev->pcidev, nesqp->qp_mem_size,1050&nesqp->hwqp.sq_pbase);1051if (!mem)1052return -ENOMEM;1053nes_debug(NES_DBG_QP, "PCI consistent memory for "1054"host descriptor rings located @ %p (pa = 0x%08lX.) size = %u.\n",1055mem, (unsigned long)nesqp->hwqp.sq_pbase, nesqp->qp_mem_size);10561057memset(mem, 0, nesqp->qp_mem_size);10581059nesqp->hwqp.sq_vbase = mem;1060mem += sizeof(struct nes_hw_qp_wqe) * sq_size;10611062nesqp->hwqp.rq_vbase = mem;1063nesqp->hwqp.rq_pbase = nesqp->hwqp.sq_pbase +1064sizeof(struct nes_hw_qp_wqe) * sq_size;1065mem += sizeof(struct nes_hw_qp_wqe) * rq_size;10661067nesqp->hwqp.q2_vbase = mem;1068nesqp->hwqp.q2_pbase = nesqp->hwqp.rq_pbase +1069sizeof(struct nes_hw_qp_wqe) * rq_size;1070mem += 256;1071memset(nesqp->hwqp.q2_vbase, 0, 256);10721073nesqp->nesqp_context = mem;1074nesqp->nesqp_context_pbase = nesqp->hwqp.q2_pbase + 256;1075memset(nesqp->nesqp_context, 0, sizeof(*nesqp->nesqp_context));1076return 0;1077}107810791080/**1081* nes_free_qp_mem() is to free up the qp's pci_alloc_consistent() memory.1082*/1083static inline void nes_free_qp_mem(struct nes_device *nesdev,1084struct nes_qp *nesqp, int virt_wqs)1085{1086unsigned long flags;1087struct nes_adapter *nesadapter = nesdev->nesadapter;1088if (!virt_wqs) {1089pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size,1090nesqp->hwqp.sq_vbase, nesqp->hwqp.sq_pbase);1091}else {1092spin_lock_irqsave(&nesadapter->pbl_lock, flags);1093nesadapter->free_256pbl++;1094spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);1095pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, nesqp->hwqp.q2_vbase, nesqp->hwqp.q2_pbase);1096pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase );1097nesqp->pbl_vbase = NULL;1098if (nesqp->sq_kmapped) {1099nesqp->sq_kmapped = 0;1100kunmap(nesqp->page);1101}1102}1103}110411051106/**1107* nes_create_qp1108*/1109static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,1110struct ib_qp_init_attr *init_attr, struct ib_udata *udata)1111{1112u64 u64temp= 0;1113u64 u64nesqp = 0;1114struct nes_pd *nespd = to_nespd(ibpd);1115struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);1116struct nes_device *nesdev = nesvnic->nesdev;1117struct nes_adapter *nesadapter = nesdev->nesadapter;1118struct nes_qp *nesqp;1119struct nes_cq *nescq;1120struct nes_ucontext *nes_ucontext;1121struct nes_hw_cqp_wqe *cqp_wqe;1122struct nes_cqp_request *cqp_request;1123struct nes_create_qp_req req;1124struct nes_create_qp_resp uresp;1125struct nes_pbl *nespbl = NULL;1126u32 qp_num = 0;1127u32 opcode = 0;1128/* u32 counter = 0; */1129void *mem;1130unsigned long flags;1131int ret;1132int err;1133int virt_wqs = 0;1134int sq_size;1135int rq_size;1136u8 sq_encoded_size;1137u8 rq_encoded_size;1138/* int counter; */11391140if (init_attr->create_flags)1141return ERR_PTR(-EINVAL);11421143atomic_inc(&qps_created);1144switch (init_attr->qp_type) {1145case IB_QPT_RC:1146if (nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) {1147init_attr->cap.max_inline_data = 0;1148} else {1149init_attr->cap.max_inline_data = 64;1150}1151sq_size = init_attr->cap.max_send_wr;1152rq_size = init_attr->cap.max_recv_wr;11531154/* check if the encoded sizes are OK or not... */1155sq_encoded_size = nes_get_encoded_size(&sq_size);1156rq_encoded_size = nes_get_encoded_size(&rq_size);11571158if ((!sq_encoded_size) || (!rq_encoded_size)) {1159nes_debug(NES_DBG_QP, "ERROR bad rq (%u) or sq (%u) size\n",1160rq_size, sq_size);1161return ERR_PTR(-EINVAL);1162}11631164init_attr->cap.max_send_wr = sq_size -2;1165init_attr->cap.max_recv_wr = rq_size -1;1166nes_debug(NES_DBG_QP, "RQ size=%u, SQ Size=%u\n", rq_size, sq_size);11671168ret = nes_alloc_resource(nesadapter, nesadapter->allocated_qps,1169nesadapter->max_qp, &qp_num, &nesadapter->next_qp);1170if (ret) {1171return ERR_PTR(ret);1172}11731174/* Need 512 (actually now 1024) byte alignment on this structure */1175mem = kzalloc(sizeof(*nesqp)+NES_SW_CONTEXT_ALIGN-1, GFP_KERNEL);1176if (!mem) {1177nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);1178nes_debug(NES_DBG_QP, "Unable to allocate QP\n");1179return ERR_PTR(-ENOMEM);1180}1181u64nesqp = (unsigned long)mem;1182u64nesqp += ((u64)NES_SW_CONTEXT_ALIGN) - 1;1183u64temp = ((u64)NES_SW_CONTEXT_ALIGN) - 1;1184u64nesqp &= ~u64temp;1185nesqp = (struct nes_qp *)(unsigned long)u64nesqp;1186/* nes_debug(NES_DBG_QP, "nesqp=%p, allocated buffer=%p. Rounded to closest %u\n",1187nesqp, mem, NES_SW_CONTEXT_ALIGN); */1188nesqp->allocated_buffer = mem;11891190if (udata) {1191if (ib_copy_from_udata(&req, udata, sizeof(struct nes_create_qp_req))) {1192nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);1193kfree(nesqp->allocated_buffer);1194nes_debug(NES_DBG_QP, "ib_copy_from_udata() Failed \n");1195return NULL;1196}1197if (req.user_wqe_buffers) {1198virt_wqs = 1;1199}1200if ((ibpd->uobject) && (ibpd->uobject->context)) {1201nesqp->user_mode = 1;1202nes_ucontext = to_nesucontext(ibpd->uobject->context);1203if (virt_wqs) {1204err = 1;1205list_for_each_entry(nespbl, &nes_ucontext->qp_reg_mem_list, list) {1206if (nespbl->user_base == (unsigned long )req.user_wqe_buffers) {1207list_del(&nespbl->list);1208err = 0;1209nes_debug(NES_DBG_QP, "Found PBL for virtual QP. nespbl=%p. user_base=0x%lx\n",1210nespbl, nespbl->user_base);1211break;1212}1213}1214if (err) {1215nes_debug(NES_DBG_QP, "Didn't Find PBL for virtual QP. address = %llx.\n",1216(long long unsigned int)req.user_wqe_buffers);1217nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);1218kfree(nesqp->allocated_buffer);1219return ERR_PTR(-EFAULT);1220}1221}12221223nes_ucontext = to_nesucontext(ibpd->uobject->context);1224nesqp->mmap_sq_db_index =1225find_next_zero_bit(nes_ucontext->allocated_wqs,1226NES_MAX_USER_WQ_REGIONS, nes_ucontext->first_free_wq);1227/* nes_debug(NES_DBG_QP, "find_first_zero_biton wqs returned %u\n",1228nespd->mmap_db_index); */1229if (nesqp->mmap_sq_db_index >= NES_MAX_USER_WQ_REGIONS) {1230nes_debug(NES_DBG_QP,1231"db index > max user regions, failing create QP\n");1232nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);1233if (virt_wqs) {1234pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,1235nespbl->pbl_pbase);1236kfree(nespbl);1237}1238kfree(nesqp->allocated_buffer);1239return ERR_PTR(-ENOMEM);1240}1241set_bit(nesqp->mmap_sq_db_index, nes_ucontext->allocated_wqs);1242nes_ucontext->mmap_nesqp[nesqp->mmap_sq_db_index] = nesqp;1243nes_ucontext->first_free_wq = nesqp->mmap_sq_db_index + 1;1244} else {1245nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);1246kfree(nesqp->allocated_buffer);1247return ERR_PTR(-EFAULT);1248}1249}1250err = (!virt_wqs) ? nes_setup_mmap_qp(nesqp, nesvnic, sq_size, rq_size) :1251nes_setup_virt_qp(nesqp, nespbl, nesvnic, sq_size, rq_size);1252if (err) {1253nes_debug(NES_DBG_QP,1254"error geting qp mem code = %d\n", err);1255nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);1256kfree(nesqp->allocated_buffer);1257return ERR_PTR(-ENOMEM);1258}12591260nesqp->hwqp.sq_size = sq_size;1261nesqp->hwqp.sq_encoded_size = sq_encoded_size;1262nesqp->hwqp.sq_head = 1;1263nesqp->hwqp.rq_size = rq_size;1264nesqp->hwqp.rq_encoded_size = rq_encoded_size;1265/* nes_debug(NES_DBG_QP, "nesqp->nesqp_context_pbase = %p\n",1266(void *)nesqp->nesqp_context_pbase);1267*/1268nesqp->hwqp.qp_id = qp_num;1269nesqp->ibqp.qp_num = nesqp->hwqp.qp_id;1270nesqp->nespd = nespd;12711272nescq = to_nescq(init_attr->send_cq);1273nesqp->nesscq = nescq;1274nescq = to_nescq(init_attr->recv_cq);1275nesqp->nesrcq = nescq;12761277nesqp->nesqp_context->misc |= cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) <<1278NES_QPCONTEXT_MISC_PCI_FCN_SHIFT);1279nesqp->nesqp_context->misc |= cpu_to_le32((u32)nesqp->hwqp.rq_encoded_size <<1280NES_QPCONTEXT_MISC_RQ_SIZE_SHIFT);1281nesqp->nesqp_context->misc |= cpu_to_le32((u32)nesqp->hwqp.sq_encoded_size <<1282NES_QPCONTEXT_MISC_SQ_SIZE_SHIFT);1283if (!udata) {1284nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_PRIV_EN);1285nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_FAST_REGISTER_EN);1286}1287nesqp->nesqp_context->cqs = cpu_to_le32(nesqp->nesscq->hw_cq.cq_number +1288((u32)nesqp->nesrcq->hw_cq.cq_number << 16));1289u64temp = (u64)nesqp->hwqp.sq_pbase;1290nesqp->nesqp_context->sq_addr_low = cpu_to_le32((u32)u64temp);1291nesqp->nesqp_context->sq_addr_high = cpu_to_le32((u32)(u64temp >> 32));129212931294if (!virt_wqs) {1295u64temp = (u64)nesqp->hwqp.sq_pbase;1296nesqp->nesqp_context->sq_addr_low = cpu_to_le32((u32)u64temp);1297nesqp->nesqp_context->sq_addr_high = cpu_to_le32((u32)(u64temp >> 32));1298u64temp = (u64)nesqp->hwqp.rq_pbase;1299nesqp->nesqp_context->rq_addr_low = cpu_to_le32((u32)u64temp);1300nesqp->nesqp_context->rq_addr_high = cpu_to_le32((u32)(u64temp >> 32));1301} else {1302u64temp = (u64)nesqp->pbl_pbase;1303nesqp->nesqp_context->rq_addr_low = cpu_to_le32((u32)u64temp);1304nesqp->nesqp_context->rq_addr_high = cpu_to_le32((u32)(u64temp >> 32));1305}13061307/* nes_debug(NES_DBG_QP, "next_qp_nic_index=%u, using nic_index=%d\n",1308nesvnic->next_qp_nic_index,1309nesvnic->qp_nic_index[nesvnic->next_qp_nic_index]); */1310spin_lock_irqsave(&nesdev->cqp.lock, flags);1311nesqp->nesqp_context->misc2 |= cpu_to_le32(1312(u32)nesvnic->qp_nic_index[nesvnic->next_qp_nic_index] <<1313NES_QPCONTEXT_MISC2_NIC_INDEX_SHIFT);1314nesvnic->next_qp_nic_index++;1315if ((nesvnic->next_qp_nic_index > 3) ||1316(nesvnic->qp_nic_index[nesvnic->next_qp_nic_index] == 0xf)) {1317nesvnic->next_qp_nic_index = 0;1318}1319spin_unlock_irqrestore(&nesdev->cqp.lock, flags);13201321nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32((u32)nesqp->nespd->pd_id << 16);1322u64temp = (u64)nesqp->hwqp.q2_pbase;1323nesqp->nesqp_context->q2_addr_low = cpu_to_le32((u32)u64temp);1324nesqp->nesqp_context->q2_addr_high = cpu_to_le32((u32)(u64temp >> 32));1325nesqp->nesqp_context->aeq_token_low = cpu_to_le32((u32)((unsigned long)(nesqp)));1326nesqp->nesqp_context->aeq_token_high = cpu_to_le32((u32)(upper_32_bits((unsigned long)(nesqp))));1327nesqp->nesqp_context->ird_ord_sizes = cpu_to_le32(NES_QPCONTEXT_ORDIRD_ALSMM |1328NES_QPCONTEXT_ORDIRD_AAH |1329((((u32)nesadapter->max_irrq_wr) <<1330NES_QPCONTEXT_ORDIRD_IRDSIZE_SHIFT) & NES_QPCONTEXT_ORDIRD_IRDSIZE_MASK));1331if (disable_mpa_crc) {1332nes_debug(NES_DBG_QP, "Disabling MPA crc checking due to module option.\n");1333nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(NES_QPCONTEXT_ORDIRD_RNMC);1334}133513361337/* Create the QP */1338cqp_request = nes_get_cqp_request(nesdev);1339if (cqp_request == NULL) {1340nes_debug(NES_DBG_QP, "Failed to get a cqp_request\n");1341nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);1342nes_free_qp_mem(nesdev, nesqp,virt_wqs);1343kfree(nesqp->allocated_buffer);1344return ERR_PTR(-ENOMEM);1345}1346cqp_request->waiting = 1;1347cqp_wqe = &cqp_request->cqp_wqe;13481349if (!virt_wqs) {1350opcode = NES_CQP_CREATE_QP | NES_CQP_QP_TYPE_IWARP |1351NES_CQP_QP_IWARP_STATE_IDLE;1352} else {1353opcode = NES_CQP_CREATE_QP | NES_CQP_QP_TYPE_IWARP | NES_CQP_QP_VIRT_WQS |1354NES_CQP_QP_IWARP_STATE_IDLE;1355}1356opcode |= NES_CQP_QP_CQS_VALID;1357nes_fill_init_cqp_wqe(cqp_wqe, nesdev);1358set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);1359set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);13601361u64temp = (u64)nesqp->nesqp_context_pbase;1362set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);13631364atomic_set(&cqp_request->refcount, 2);1365nes_post_cqp_request(nesdev, cqp_request);13661367/* Wait for CQP */1368nes_debug(NES_DBG_QP, "Waiting for create iWARP QP%u to complete.\n",1369nesqp->hwqp.qp_id);1370ret = wait_event_timeout(cqp_request->waitq,1371(cqp_request->request_done != 0), NES_EVENT_TIMEOUT);1372nes_debug(NES_DBG_QP, "Create iwarp QP%u completed, wait_event_timeout ret=%u,"1373" nesdev->cqp_head = %u, nesdev->cqp.sq_tail = %u,"1374" CQP Major:Minor codes = 0x%04X:0x%04X.\n",1375nesqp->hwqp.qp_id, ret, nesdev->cqp.sq_head, nesdev->cqp.sq_tail,1376cqp_request->major_code, cqp_request->minor_code);1377if ((!ret) || (cqp_request->major_code)) {1378nes_put_cqp_request(nesdev, cqp_request);1379nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);1380nes_free_qp_mem(nesdev, nesqp,virt_wqs);1381kfree(nesqp->allocated_buffer);1382if (!ret) {1383return ERR_PTR(-ETIME);1384} else {1385return ERR_PTR(-EIO);1386}1387}13881389nes_put_cqp_request(nesdev, cqp_request);13901391if (ibpd->uobject) {1392uresp.mmap_sq_db_index = nesqp->mmap_sq_db_index;1393uresp.actual_sq_size = sq_size;1394uresp.actual_rq_size = rq_size;1395uresp.qp_id = nesqp->hwqp.qp_id;1396uresp.nes_drv_opt = nes_drv_opt;1397if (ib_copy_to_udata(udata, &uresp, sizeof uresp)) {1398nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);1399nes_free_qp_mem(nesdev, nesqp,virt_wqs);1400kfree(nesqp->allocated_buffer);1401return ERR_PTR(-EFAULT);1402}1403}14041405nes_debug(NES_DBG_QP, "QP%u structure located @%p.Size = %u.\n",1406nesqp->hwqp.qp_id, nesqp, (u32)sizeof(*nesqp));1407spin_lock_init(&nesqp->lock);1408nes_add_ref(&nesqp->ibqp);1409break;1410default:1411nes_debug(NES_DBG_QP, "Invalid QP type: %d\n", init_attr->qp_type);1412return ERR_PTR(-EINVAL);1413}14141415nesqp->sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR);14161417/* update the QP table */1418nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp;1419nes_debug(NES_DBG_QP, "netdev refcnt=%u\n",1420netdev_refcnt_read(nesvnic->netdev));14211422return &nesqp->ibqp;1423}142414251426/**1427* nes_clean_cq1428*/1429static void nes_clean_cq(struct nes_qp *nesqp, struct nes_cq *nescq)1430{1431u32 cq_head;1432u32 lo;1433u32 hi;1434u64 u64temp;1435unsigned long flags = 0;14361437spin_lock_irqsave(&nescq->lock, flags);14381439cq_head = nescq->hw_cq.cq_head;1440while (le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {1441rmb();1442lo = le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]);1443hi = le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]);1444u64temp = (((u64)hi) << 32) | ((u64)lo);1445u64temp &= ~(NES_SW_CONTEXT_ALIGN-1);1446if (u64temp == (u64)(unsigned long)nesqp) {1447/* Zero the context value so cqe will be ignored */1448nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX] = 0;1449nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX] = 0;1450}14511452if (++cq_head >= nescq->hw_cq.cq_size)1453cq_head = 0;1454}14551456spin_unlock_irqrestore(&nescq->lock, flags);1457}145814591460/**1461* nes_destroy_qp1462*/1463static int nes_destroy_qp(struct ib_qp *ibqp)1464{1465struct nes_qp *nesqp = to_nesqp(ibqp);1466struct nes_ucontext *nes_ucontext;1467struct ib_qp_attr attr;1468struct iw_cm_id *cm_id;1469struct iw_cm_event cm_event;1470int ret;14711472atomic_inc(&sw_qps_destroyed);1473nesqp->destroyed = 1;14741475/* Blow away the connection if it exists. */1476if (nesqp->ibqp_state >= IB_QPS_INIT && nesqp->ibqp_state <= IB_QPS_RTS) {1477/* if (nesqp->ibqp_state == IB_QPS_RTS) { */1478attr.qp_state = IB_QPS_ERR;1479nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);1480}14811482if (((nesqp->ibqp_state == IB_QPS_INIT) ||1483(nesqp->ibqp_state == IB_QPS_RTR)) && (nesqp->cm_id)) {1484cm_id = nesqp->cm_id;1485cm_event.event = IW_CM_EVENT_CONNECT_REPLY;1486cm_event.status = -ETIMEDOUT;1487cm_event.local_addr = cm_id->local_addr;1488cm_event.remote_addr = cm_id->remote_addr;1489cm_event.private_data = NULL;1490cm_event.private_data_len = 0;14911492nes_debug(NES_DBG_QP, "Generating a CM Timeout Event for "1493"QP%u. cm_id = %p, refcount = %u. \n",1494nesqp->hwqp.qp_id, cm_id, atomic_read(&nesqp->refcount));14951496cm_id->rem_ref(cm_id);1497ret = cm_id->event_handler(cm_id, &cm_event);1498if (ret)1499nes_debug(NES_DBG_QP, "OFA CM event_handler returned, ret=%d\n", ret);1500}15011502if (nesqp->user_mode) {1503if ((ibqp->uobject)&&(ibqp->uobject->context)) {1504nes_ucontext = to_nesucontext(ibqp->uobject->context);1505clear_bit(nesqp->mmap_sq_db_index, nes_ucontext->allocated_wqs);1506nes_ucontext->mmap_nesqp[nesqp->mmap_sq_db_index] = NULL;1507if (nes_ucontext->first_free_wq > nesqp->mmap_sq_db_index) {1508nes_ucontext->first_free_wq = nesqp->mmap_sq_db_index;1509}1510}1511if (nesqp->pbl_pbase && nesqp->sq_kmapped) {1512nesqp->sq_kmapped = 0;1513kunmap(nesqp->page);1514}1515} else {1516/* Clean any pending completions from the cq(s) */1517if (nesqp->nesscq)1518nes_clean_cq(nesqp, nesqp->nesscq);15191520if ((nesqp->nesrcq) && (nesqp->nesrcq != nesqp->nesscq))1521nes_clean_cq(nesqp, nesqp->nesrcq);1522}15231524nes_rem_ref(&nesqp->ibqp);1525return 0;1526}152715281529/**1530* nes_create_cq1531*/1532static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,1533int comp_vector,1534struct ib_ucontext *context, struct ib_udata *udata)1535{1536u64 u64temp;1537struct nes_vnic *nesvnic = to_nesvnic(ibdev);1538struct nes_device *nesdev = nesvnic->nesdev;1539struct nes_adapter *nesadapter = nesdev->nesadapter;1540struct nes_cq *nescq;1541struct nes_ucontext *nes_ucontext = NULL;1542struct nes_cqp_request *cqp_request;1543void *mem = NULL;1544struct nes_hw_cqp_wqe *cqp_wqe;1545struct nes_pbl *nespbl = NULL;1546struct nes_create_cq_req req;1547struct nes_create_cq_resp resp;1548u32 cq_num = 0;1549u32 opcode = 0;1550u32 pbl_entries = 1;1551int err;1552unsigned long flags;1553int ret;15541555if (entries > nesadapter->max_cqe)1556return ERR_PTR(-EINVAL);15571558err = nes_alloc_resource(nesadapter, nesadapter->allocated_cqs,1559nesadapter->max_cq, &cq_num, &nesadapter->next_cq);1560if (err) {1561return ERR_PTR(err);1562}15631564nescq = kzalloc(sizeof(struct nes_cq), GFP_KERNEL);1565if (!nescq) {1566nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);1567nes_debug(NES_DBG_CQ, "Unable to allocate nes_cq struct\n");1568return ERR_PTR(-ENOMEM);1569}15701571nescq->hw_cq.cq_size = max(entries + 1, 5);1572nescq->hw_cq.cq_number = cq_num;1573nescq->ibcq.cqe = nescq->hw_cq.cq_size - 1;157415751576if (context) {1577nes_ucontext = to_nesucontext(context);1578if (ib_copy_from_udata(&req, udata, sizeof (struct nes_create_cq_req))) {1579nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);1580kfree(nescq);1581return ERR_PTR(-EFAULT);1582}1583nesvnic->mcrq_ucontext = nes_ucontext;1584nes_ucontext->mcrqf = req.mcrqf;1585if (nes_ucontext->mcrqf) {1586if (nes_ucontext->mcrqf & 0x80000000)1587nescq->hw_cq.cq_number = nesvnic->nic.qp_id + 28 + 2 * ((nes_ucontext->mcrqf & 0xf) - 1);1588else if (nes_ucontext->mcrqf & 0x40000000)1589nescq->hw_cq.cq_number = nes_ucontext->mcrqf & 0xffff;1590else1591nescq->hw_cq.cq_number = nesvnic->mcrq_qp_id + nes_ucontext->mcrqf-1;1592nescq->mcrqf = nes_ucontext->mcrqf;1593nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);1594}1595nes_debug(NES_DBG_CQ, "CQ Virtual Address = %08lX, size = %u.\n",1596(unsigned long)req.user_cq_buffer, entries);1597err = 1;1598list_for_each_entry(nespbl, &nes_ucontext->cq_reg_mem_list, list) {1599if (nespbl->user_base == (unsigned long )req.user_cq_buffer) {1600list_del(&nespbl->list);1601err = 0;1602nes_debug(NES_DBG_CQ, "Found PBL for virtual CQ. nespbl=%p.\n",1603nespbl);1604break;1605}1606}1607if (err) {1608nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);1609kfree(nescq);1610return ERR_PTR(-EFAULT);1611}16121613pbl_entries = nespbl->pbl_size >> 3;1614nescq->cq_mem_size = 0;1615} else {1616nescq->cq_mem_size = nescq->hw_cq.cq_size * sizeof(struct nes_hw_cqe);1617nes_debug(NES_DBG_CQ, "Attempting to allocate pci memory (%u entries, %u bytes) for CQ%u.\n",1618entries, nescq->cq_mem_size, nescq->hw_cq.cq_number);16191620/* allocate the physical buffer space */1621mem = pci_alloc_consistent(nesdev->pcidev, nescq->cq_mem_size,1622&nescq->hw_cq.cq_pbase);1623if (!mem) {1624printk(KERN_ERR PFX "Unable to allocate pci memory for cq\n");1625nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);1626kfree(nescq);1627return ERR_PTR(-ENOMEM);1628}16291630memset(mem, 0, nescq->cq_mem_size);1631nescq->hw_cq.cq_vbase = mem;1632nescq->hw_cq.cq_head = 0;1633nes_debug(NES_DBG_CQ, "CQ%u virtual address @ %p, phys = 0x%08X\n",1634nescq->hw_cq.cq_number, nescq->hw_cq.cq_vbase,1635(u32)nescq->hw_cq.cq_pbase);1636}16371638nescq->hw_cq.ce_handler = nes_iwarp_ce_handler;1639spin_lock_init(&nescq->lock);16401641/* send CreateCQ request to CQP */1642cqp_request = nes_get_cqp_request(nesdev);1643if (cqp_request == NULL) {1644nes_debug(NES_DBG_CQ, "Failed to get a cqp_request.\n");1645if (!context)1646pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,1647nescq->hw_cq.cq_pbase);1648else {1649pci_free_consistent(nesdev->pcidev, nespbl->pbl_size,1650nespbl->pbl_vbase, nespbl->pbl_pbase);1651kfree(nespbl);1652}16531654nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);1655kfree(nescq);1656return ERR_PTR(-ENOMEM);1657}1658cqp_request->waiting = 1;1659cqp_wqe = &cqp_request->cqp_wqe;16601661opcode = NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |1662NES_CQP_CQ_CHK_OVERFLOW |1663NES_CQP_CQ_CEQE_MASK | ((u32)nescq->hw_cq.cq_size << 16);16641665spin_lock_irqsave(&nesadapter->pbl_lock, flags);16661667if (pbl_entries != 1) {1668if (pbl_entries > 32) {1669/* use 4k pbl */1670nes_debug(NES_DBG_CQ, "pbl_entries=%u, use a 4k PBL\n", pbl_entries);1671if (nesadapter->free_4kpbl == 0) {1672spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);1673nes_free_cqp_request(nesdev, cqp_request);1674if (!context)1675pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,1676nescq->hw_cq.cq_pbase);1677else {1678pci_free_consistent(nesdev->pcidev, nespbl->pbl_size,1679nespbl->pbl_vbase, nespbl->pbl_pbase);1680kfree(nespbl);1681}1682nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);1683kfree(nescq);1684return ERR_PTR(-ENOMEM);1685} else {1686opcode |= (NES_CQP_CQ_VIRT | NES_CQP_CQ_4KB_CHUNK);1687nescq->virtual_cq = 2;1688nesadapter->free_4kpbl--;1689}1690} else {1691/* use 256 byte pbl */1692nes_debug(NES_DBG_CQ, "pbl_entries=%u, use a 256 byte PBL\n", pbl_entries);1693if (nesadapter->free_256pbl == 0) {1694spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);1695nes_free_cqp_request(nesdev, cqp_request);1696if (!context)1697pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,1698nescq->hw_cq.cq_pbase);1699else {1700pci_free_consistent(nesdev->pcidev, nespbl->pbl_size,1701nespbl->pbl_vbase, nespbl->pbl_pbase);1702kfree(nespbl);1703}1704nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);1705kfree(nescq);1706return ERR_PTR(-ENOMEM);1707} else {1708opcode |= NES_CQP_CQ_VIRT;1709nescq->virtual_cq = 1;1710nesadapter->free_256pbl--;1711}1712}1713}17141715spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);17161717nes_fill_init_cqp_wqe(cqp_wqe, nesdev);1718set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);1719set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,1720(nescq->hw_cq.cq_number | ((u32)nesdev->ceq_index << 16)));17211722if (context) {1723if (pbl_entries != 1)1724u64temp = (u64)nespbl->pbl_pbase;1725else1726u64temp = le64_to_cpu(nespbl->pbl_vbase[0]);1727set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX,1728nes_ucontext->mmap_db_index[0]);1729} else {1730u64temp = (u64)nescq->hw_cq.cq_pbase;1731cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;1732}1733set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);1734cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;1735u64temp = (u64)(unsigned long)&nescq->hw_cq;1736cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] =1737cpu_to_le32((u32)(u64temp >> 1));1738cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =1739cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);17401741atomic_set(&cqp_request->refcount, 2);1742nes_post_cqp_request(nesdev, cqp_request);17431744/* Wait for CQP */1745nes_debug(NES_DBG_CQ, "Waiting for create iWARP CQ%u to complete.\n",1746nescq->hw_cq.cq_number);1747ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done),1748NES_EVENT_TIMEOUT * 2);1749nes_debug(NES_DBG_CQ, "Create iWARP CQ%u completed, wait_event_timeout ret = %d.\n",1750nescq->hw_cq.cq_number, ret);1751if ((!ret) || (cqp_request->major_code)) {1752nes_put_cqp_request(nesdev, cqp_request);1753if (!context)1754pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,1755nescq->hw_cq.cq_pbase);1756else {1757pci_free_consistent(nesdev->pcidev, nespbl->pbl_size,1758nespbl->pbl_vbase, nespbl->pbl_pbase);1759kfree(nespbl);1760}1761nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);1762kfree(nescq);1763return ERR_PTR(-EIO);1764}1765nes_put_cqp_request(nesdev, cqp_request);17661767if (context) {1768/* free the nespbl */1769pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,1770nespbl->pbl_pbase);1771kfree(nespbl);1772resp.cq_id = nescq->hw_cq.cq_number;1773resp.cq_size = nescq->hw_cq.cq_size;1774resp.mmap_db_index = 0;1775if (ib_copy_to_udata(udata, &resp, sizeof resp)) {1776nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);1777kfree(nescq);1778return ERR_PTR(-EFAULT);1779}1780}17811782return &nescq->ibcq;1783}178417851786/**1787* nes_destroy_cq1788*/1789static int nes_destroy_cq(struct ib_cq *ib_cq)1790{1791struct nes_cq *nescq;1792struct nes_device *nesdev;1793struct nes_vnic *nesvnic;1794struct nes_adapter *nesadapter;1795struct nes_hw_cqp_wqe *cqp_wqe;1796struct nes_cqp_request *cqp_request;1797unsigned long flags;1798u32 opcode = 0;1799int ret;18001801if (ib_cq == NULL)1802return 0;18031804nescq = to_nescq(ib_cq);1805nesvnic = to_nesvnic(ib_cq->device);1806nesdev = nesvnic->nesdev;1807nesadapter = nesdev->nesadapter;18081809nes_debug(NES_DBG_CQ, "Destroy CQ%u\n", nescq->hw_cq.cq_number);18101811/* Send DestroyCQ request to CQP */1812cqp_request = nes_get_cqp_request(nesdev);1813if (cqp_request == NULL) {1814nes_debug(NES_DBG_CQ, "Failed to get a cqp_request.\n");1815return -ENOMEM;1816}1817cqp_request->waiting = 1;1818cqp_wqe = &cqp_request->cqp_wqe;1819opcode = NES_CQP_DESTROY_CQ | (nescq->hw_cq.cq_size << 16);1820spin_lock_irqsave(&nesadapter->pbl_lock, flags);1821if (nescq->virtual_cq == 1) {1822nesadapter->free_256pbl++;1823if (nesadapter->free_256pbl > nesadapter->max_256pbl) {1824printk(KERN_ERR PFX "%s: free 256B PBLs(%u) has exceeded the max(%u)\n",1825__func__, nesadapter->free_256pbl, nesadapter->max_256pbl);1826}1827} else if (nescq->virtual_cq == 2) {1828nesadapter->free_4kpbl++;1829if (nesadapter->free_4kpbl > nesadapter->max_4kpbl) {1830printk(KERN_ERR PFX "%s: free 4K PBLs(%u) has exceeded the max(%u)\n",1831__func__, nesadapter->free_4kpbl, nesadapter->max_4kpbl);1832}1833opcode |= NES_CQP_CQ_4KB_CHUNK;1834}18351836spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);18371838nes_fill_init_cqp_wqe(cqp_wqe, nesdev);1839set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);1840set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,1841(nescq->hw_cq.cq_number | ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 16)));1842if (!nescq->mcrqf)1843nes_free_resource(nesadapter, nesadapter->allocated_cqs, nescq->hw_cq.cq_number);18441845atomic_set(&cqp_request->refcount, 2);1846nes_post_cqp_request(nesdev, cqp_request);18471848/* Wait for CQP */1849nes_debug(NES_DBG_CQ, "Waiting for destroy iWARP CQ%u to complete.\n",1850nescq->hw_cq.cq_number);1851ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done),1852NES_EVENT_TIMEOUT);1853nes_debug(NES_DBG_CQ, "Destroy iWARP CQ%u completed, wait_event_timeout ret = %u,"1854" CQP Major:Minor codes = 0x%04X:0x%04X.\n",1855nescq->hw_cq.cq_number, ret, cqp_request->major_code,1856cqp_request->minor_code);1857if (!ret) {1858nes_debug(NES_DBG_CQ, "iWARP CQ%u destroy timeout expired\n",1859nescq->hw_cq.cq_number);1860ret = -ETIME;1861} else if (cqp_request->major_code) {1862nes_debug(NES_DBG_CQ, "iWARP CQ%u destroy failed\n",1863nescq->hw_cq.cq_number);1864ret = -EIO;1865} else {1866ret = 0;1867}1868nes_put_cqp_request(nesdev, cqp_request);18691870if (nescq->cq_mem_size)1871pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size,1872nescq->hw_cq.cq_vbase, nescq->hw_cq.cq_pbase);1873kfree(nescq);18741875return ret;1876}18771878/**1879* root_2561880*/1881static u32 root_256(struct nes_device *nesdev,1882struct nes_root_vpbl *root_vpbl,1883struct nes_root_vpbl *new_root,1884u16 pbl_count_4k)1885{1886u64 leaf_pbl;1887int i, j, k;18881889if (pbl_count_4k == 1) {1890new_root->pbl_vbase = pci_alloc_consistent(nesdev->pcidev,1891512, &new_root->pbl_pbase);18921893if (new_root->pbl_vbase == NULL)1894return 0;18951896leaf_pbl = (u64)root_vpbl->pbl_pbase;1897for (i = 0; i < 16; i++) {1898new_root->pbl_vbase[i].pa_low =1899cpu_to_le32((u32)leaf_pbl);1900new_root->pbl_vbase[i].pa_high =1901cpu_to_le32((u32)((((u64)leaf_pbl) >> 32)));1902leaf_pbl += 256;1903}1904} else {1905for (i = 3; i >= 0; i--) {1906j = i * 16;1907root_vpbl->pbl_vbase[j] = root_vpbl->pbl_vbase[i];1908leaf_pbl = le32_to_cpu(root_vpbl->pbl_vbase[j].pa_low) +1909(((u64)le32_to_cpu(root_vpbl->pbl_vbase[j].pa_high))1910<< 32);1911for (k = 1; k < 16; k++) {1912leaf_pbl += 256;1913root_vpbl->pbl_vbase[j + k].pa_low =1914cpu_to_le32((u32)leaf_pbl);1915root_vpbl->pbl_vbase[j + k].pa_high =1916cpu_to_le32((u32)((((u64)leaf_pbl) >> 32)));1917}1918}1919}19201921return 1;1922}192319241925/**1926* nes_reg_mr1927*/1928static int nes_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd,1929u32 stag, u64 region_length, struct nes_root_vpbl *root_vpbl,1930dma_addr_t single_buffer, u16 pbl_count_4k,1931u16 residual_page_count_4k, int acc, u64 *iova_start,1932u16 *actual_pbl_cnt, u8 *used_4k_pbls)1933{1934struct nes_hw_cqp_wqe *cqp_wqe;1935struct nes_cqp_request *cqp_request;1936unsigned long flags;1937int ret;1938struct nes_adapter *nesadapter = nesdev->nesadapter;1939uint pg_cnt = 0;1940u16 pbl_count_256 = 0;1941u16 pbl_count = 0;1942u8 use_256_pbls = 0;1943u8 use_4k_pbls = 0;1944u16 use_two_level = (pbl_count_4k > 1) ? 1 : 0;1945struct nes_root_vpbl new_root = { 0, NULL, NULL };1946u32 opcode = 0;1947u16 major_code;19481949/* Register the region with the adapter */1950cqp_request = nes_get_cqp_request(nesdev);1951if (cqp_request == NULL) {1952nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n");1953return -ENOMEM;1954}1955cqp_request->waiting = 1;1956cqp_wqe = &cqp_request->cqp_wqe;19571958if (pbl_count_4k) {1959spin_lock_irqsave(&nesadapter->pbl_lock, flags);19601961pg_cnt = ((pbl_count_4k - 1) * 512) + residual_page_count_4k;1962pbl_count_256 = (pg_cnt + 31) / 32;1963if (pg_cnt <= 32) {1964if (pbl_count_256 <= nesadapter->free_256pbl)1965use_256_pbls = 1;1966else if (pbl_count_4k <= nesadapter->free_4kpbl)1967use_4k_pbls = 1;1968} else if (pg_cnt <= 2048) {1969if (((pbl_count_4k + use_two_level) <= nesadapter->free_4kpbl) &&1970(nesadapter->free_4kpbl > (nesadapter->max_4kpbl >> 1))) {1971use_4k_pbls = 1;1972} else if ((pbl_count_256 + 1) <= nesadapter->free_256pbl) {1973use_256_pbls = 1;1974use_two_level = 1;1975} else if ((pbl_count_4k + use_two_level) <= nesadapter->free_4kpbl) {1976use_4k_pbls = 1;1977}1978} else {1979if ((pbl_count_4k + 1) <= nesadapter->free_4kpbl)1980use_4k_pbls = 1;1981}19821983if (use_256_pbls) {1984pbl_count = pbl_count_256;1985nesadapter->free_256pbl -= pbl_count + use_two_level;1986} else if (use_4k_pbls) {1987pbl_count = pbl_count_4k;1988nesadapter->free_4kpbl -= pbl_count + use_two_level;1989} else {1990spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);1991nes_debug(NES_DBG_MR, "Out of Pbls\n");1992nes_free_cqp_request(nesdev, cqp_request);1993return -ENOMEM;1994}19951996spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);1997}19981999if (use_256_pbls && use_two_level) {2000if (root_256(nesdev, root_vpbl, &new_root, pbl_count_4k) == 1) {2001if (new_root.pbl_pbase != 0)2002root_vpbl = &new_root;2003} else {2004spin_lock_irqsave(&nesadapter->pbl_lock, flags);2005nesadapter->free_256pbl += pbl_count_256 + use_two_level;2006use_256_pbls = 0;20072008if (pbl_count_4k == 1)2009use_two_level = 0;2010pbl_count = pbl_count_4k;20112012if ((pbl_count_4k + use_two_level) <= nesadapter->free_4kpbl) {2013nesadapter->free_4kpbl -= pbl_count + use_two_level;2014use_4k_pbls = 1;2015}2016spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);20172018if (use_4k_pbls == 0)2019return -ENOMEM;2020}2021}20222023opcode = NES_CQP_REGISTER_STAG | NES_CQP_STAG_RIGHTS_LOCAL_READ |2024NES_CQP_STAG_VA_TO | NES_CQP_STAG_MR;2025if (acc & IB_ACCESS_LOCAL_WRITE)2026opcode |= NES_CQP_STAG_RIGHTS_LOCAL_WRITE;2027if (acc & IB_ACCESS_REMOTE_WRITE)2028opcode |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_REM_ACC_EN;2029if (acc & IB_ACCESS_REMOTE_READ)2030opcode |= NES_CQP_STAG_RIGHTS_REMOTE_READ | NES_CQP_STAG_REM_ACC_EN;2031if (acc & IB_ACCESS_MW_BIND)2032opcode |= NES_CQP_STAG_RIGHTS_WINDOW_BIND | NES_CQP_STAG_REM_ACC_EN;20332034nes_fill_init_cqp_wqe(cqp_wqe, nesdev);2035set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);2036set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_VA_LOW_IDX, *iova_start);2037set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_LOW_IDX, region_length);20382039cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] =2040cpu_to_le32((u32)(region_length >> 8) & 0xff000000);2041cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] |=2042cpu_to_le32(nespd->pd_id & 0x00007fff);2043set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag);20442045if (pbl_count == 0) {2046set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PA_LOW_IDX, single_buffer);2047} else {2048set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PA_LOW_IDX, root_vpbl->pbl_pbase);2049set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX, pbl_count);2050set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_LEN_IDX, (pg_cnt * 8));20512052if (use_4k_pbls)2053cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_STAG_PBL_BLK_SIZE);2054}2055barrier();20562057atomic_set(&cqp_request->refcount, 2);2058nes_post_cqp_request(nesdev, cqp_request);20592060/* Wait for CQP */2061ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done),2062NES_EVENT_TIMEOUT);2063nes_debug(NES_DBG_MR, "Register STag 0x%08X completed, wait_event_timeout ret = %u,"2064" CQP Major:Minor codes = 0x%04X:0x%04X.\n",2065stag, ret, cqp_request->major_code, cqp_request->minor_code);2066major_code = cqp_request->major_code;2067nes_put_cqp_request(nesdev, cqp_request);20682069if ((!ret || major_code) && pbl_count != 0) {2070spin_lock_irqsave(&nesadapter->pbl_lock, flags);2071if (use_256_pbls)2072nesadapter->free_256pbl += pbl_count + use_two_level;2073else if (use_4k_pbls)2074nesadapter->free_4kpbl += pbl_count + use_two_level;2075spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);2076}2077if (new_root.pbl_pbase)2078pci_free_consistent(nesdev->pcidev, 512, new_root.pbl_vbase,2079new_root.pbl_pbase);20802081if (!ret)2082return -ETIME;2083else if (major_code)2084return -EIO;20852086*actual_pbl_cnt = pbl_count + use_two_level;2087*used_4k_pbls = use_4k_pbls;2088return 0;2089}209020912092/**2093* nes_reg_phys_mr2094*/2095static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,2096struct ib_phys_buf *buffer_list, int num_phys_buf, int acc,2097u64 * iova_start)2098{2099u64 region_length;2100struct nes_pd *nespd = to_nespd(ib_pd);2101struct nes_vnic *nesvnic = to_nesvnic(ib_pd->device);2102struct nes_device *nesdev = nesvnic->nesdev;2103struct nes_adapter *nesadapter = nesdev->nesadapter;2104struct nes_mr *nesmr;2105struct ib_mr *ibmr;2106struct nes_vpbl vpbl;2107struct nes_root_vpbl root_vpbl;2108u32 stag;2109u32 i;2110unsigned long mask;2111u32 stag_index = 0;2112u32 next_stag_index = 0;2113u32 driver_key = 0;2114u32 root_pbl_index = 0;2115u32 cur_pbl_index = 0;2116int err = 0;2117int ret = 0;2118u16 pbl_count = 0;2119u8 single_page = 1;2120u8 stag_key = 0;21212122region_length = 0;2123vpbl.pbl_vbase = NULL;2124root_vpbl.pbl_vbase = NULL;2125root_vpbl.pbl_pbase = 0;21262127get_random_bytes(&next_stag_index, sizeof(next_stag_index));2128stag_key = (u8)next_stag_index;21292130driver_key = 0;21312132next_stag_index >>= 8;2133next_stag_index %= nesadapter->max_mr;2134if (num_phys_buf > (1024*512)) {2135return ERR_PTR(-E2BIG);2136}21372138if ((buffer_list[0].addr ^ *iova_start) & ~PAGE_MASK)2139return ERR_PTR(-EINVAL);21402141err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs, nesadapter->max_mr,2142&stag_index, &next_stag_index);2143if (err) {2144return ERR_PTR(err);2145}21462147nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);2148if (!nesmr) {2149nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);2150return ERR_PTR(-ENOMEM);2151}21522153for (i = 0; i < num_phys_buf; i++) {21542155if ((i & 0x01FF) == 0) {2156if (root_pbl_index == 1) {2157/* Allocate the root PBL */2158root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 8192,2159&root_vpbl.pbl_pbase);2160nes_debug(NES_DBG_MR, "Allocating root PBL, va = %p, pa = 0x%08X\n",2161root_vpbl.pbl_vbase, (unsigned int)root_vpbl.pbl_pbase);2162if (!root_vpbl.pbl_vbase) {2163pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,2164vpbl.pbl_pbase);2165nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);2166kfree(nesmr);2167return ERR_PTR(-ENOMEM);2168}2169root_vpbl.leaf_vpbl = kzalloc(sizeof(*root_vpbl.leaf_vpbl)*1024, GFP_KERNEL);2170if (!root_vpbl.leaf_vpbl) {2171pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase,2172root_vpbl.pbl_pbase);2173pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,2174vpbl.pbl_pbase);2175nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);2176kfree(nesmr);2177return ERR_PTR(-ENOMEM);2178}2179root_vpbl.pbl_vbase[0].pa_low = cpu_to_le32((u32)vpbl.pbl_pbase);2180root_vpbl.pbl_vbase[0].pa_high =2181cpu_to_le32((u32)((((u64)vpbl.pbl_pbase) >> 32)));2182root_vpbl.leaf_vpbl[0] = vpbl;2183}2184/* Allocate a 4K buffer for the PBL */2185vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096,2186&vpbl.pbl_pbase);2187nes_debug(NES_DBG_MR, "Allocating leaf PBL, va = %p, pa = 0x%016lX\n",2188vpbl.pbl_vbase, (unsigned long)vpbl.pbl_pbase);2189if (!vpbl.pbl_vbase) {2190nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);2191ibmr = ERR_PTR(-ENOMEM);2192kfree(nesmr);2193goto reg_phys_err;2194}2195/* Fill in the root table */2196if (1 <= root_pbl_index) {2197root_vpbl.pbl_vbase[root_pbl_index].pa_low =2198cpu_to_le32((u32)vpbl.pbl_pbase);2199root_vpbl.pbl_vbase[root_pbl_index].pa_high =2200cpu_to_le32((u32)((((u64)vpbl.pbl_pbase) >> 32)));2201root_vpbl.leaf_vpbl[root_pbl_index] = vpbl;2202}2203root_pbl_index++;2204cur_pbl_index = 0;2205}22062207mask = !buffer_list[i].size;2208if (i != 0)2209mask |= buffer_list[i].addr;2210if (i != num_phys_buf - 1)2211mask |= buffer_list[i].addr + buffer_list[i].size;22122213if (mask & ~PAGE_MASK) {2214nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);2215nes_debug(NES_DBG_MR, "Invalid buffer addr or size\n");2216ibmr = ERR_PTR(-EINVAL);2217kfree(nesmr);2218goto reg_phys_err;2219}22202221region_length += buffer_list[i].size;2222if ((i != 0) && (single_page)) {2223if ((buffer_list[i-1].addr+PAGE_SIZE) != buffer_list[i].addr)2224single_page = 0;2225}2226vpbl.pbl_vbase[cur_pbl_index].pa_low = cpu_to_le32((u32)buffer_list[i].addr & PAGE_MASK);2227vpbl.pbl_vbase[cur_pbl_index++].pa_high =2228cpu_to_le32((u32)((((u64)buffer_list[i].addr) >> 32)));2229}22302231stag = stag_index << 8;2232stag |= driver_key;2233stag += (u32)stag_key;22342235nes_debug(NES_DBG_MR, "Registering STag 0x%08X, VA = 0x%016lX,"2236" length = 0x%016lX, index = 0x%08X\n",2237stag, (unsigned long)*iova_start, (unsigned long)region_length, stag_index);22382239/* Make the leaf PBL the root if only one PBL */2240if (root_pbl_index == 1) {2241root_vpbl.pbl_pbase = vpbl.pbl_pbase;2242}22432244if (single_page) {2245pbl_count = 0;2246} else {2247pbl_count = root_pbl_index;2248}2249ret = nes_reg_mr(nesdev, nespd, stag, region_length, &root_vpbl,2250buffer_list[0].addr, pbl_count, (u16)cur_pbl_index, acc, iova_start,2251&nesmr->pbls_used, &nesmr->pbl_4k);22522253if (ret == 0) {2254nesmr->ibmr.rkey = stag;2255nesmr->ibmr.lkey = stag;2256nesmr->mode = IWNES_MEMREG_TYPE_MEM;2257ibmr = &nesmr->ibmr;2258} else {2259kfree(nesmr);2260ibmr = ERR_PTR(-ENOMEM);2261}22622263reg_phys_err:2264/* free the resources */2265if (root_pbl_index == 1) {2266/* single PBL case */2267pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, vpbl.pbl_pbase);2268} else {2269for (i=0; i<root_pbl_index; i++) {2270pci_free_consistent(nesdev->pcidev, 4096, root_vpbl.leaf_vpbl[i].pbl_vbase,2271root_vpbl.leaf_vpbl[i].pbl_pbase);2272}2273kfree(root_vpbl.leaf_vpbl);2274pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase,2275root_vpbl.pbl_pbase);2276}22772278return ibmr;2279}228022812282/**2283* nes_get_dma_mr2284*/2285static struct ib_mr *nes_get_dma_mr(struct ib_pd *pd, int acc)2286{2287struct ib_phys_buf bl;2288u64 kva = 0;22892290nes_debug(NES_DBG_MR, "\n");22912292bl.size = (u64)0xffffffffffULL;2293bl.addr = 0;2294return nes_reg_phys_mr(pd, &bl, 1, acc, &kva);2295}229622972298/**2299* nes_reg_user_mr2300*/2301static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,2302u64 virt, int acc, struct ib_udata *udata)2303{2304u64 iova_start;2305__le64 *pbl;2306u64 region_length;2307dma_addr_t last_dma_addr = 0;2308dma_addr_t first_dma_addr = 0;2309struct nes_pd *nespd = to_nespd(pd);2310struct nes_vnic *nesvnic = to_nesvnic(pd->device);2311struct nes_device *nesdev = nesvnic->nesdev;2312struct nes_adapter *nesadapter = nesdev->nesadapter;2313struct ib_mr *ibmr = ERR_PTR(-EINVAL);2314struct ib_umem_chunk *chunk;2315struct nes_ucontext *nes_ucontext;2316struct nes_pbl *nespbl;2317struct nes_mr *nesmr;2318struct ib_umem *region;2319struct nes_mem_reg_req req;2320struct nes_vpbl vpbl;2321struct nes_root_vpbl root_vpbl;2322int nmap_index, page_index;2323int page_count = 0;2324int err, pbl_depth = 0;2325int chunk_pages;2326int ret;2327u32 stag;2328u32 stag_index = 0;2329u32 next_stag_index;2330u32 driver_key;2331u32 root_pbl_index = 0;2332u32 cur_pbl_index = 0;2333u32 skip_pages;2334u16 pbl_count;2335u8 single_page = 1;2336u8 stag_key;23372338region = ib_umem_get(pd->uobject->context, start, length, acc, 0);2339if (IS_ERR(region)) {2340return (struct ib_mr *)region;2341}23422343nes_debug(NES_DBG_MR, "User base = 0x%lX, Virt base = 0x%lX, length = %u,"2344" offset = %u, page size = %u.\n",2345(unsigned long int)start, (unsigned long int)virt, (u32)length,2346region->offset, region->page_size);23472348skip_pages = ((u32)region->offset) >> 12;23492350if (ib_copy_from_udata(&req, udata, sizeof(req)))2351return ERR_PTR(-EFAULT);2352nes_debug(NES_DBG_MR, "Memory Registration type = %08X.\n", req.reg_type);23532354switch (req.reg_type) {2355case IWNES_MEMREG_TYPE_MEM:2356pbl_depth = 0;2357region_length = 0;2358vpbl.pbl_vbase = NULL;2359root_vpbl.pbl_vbase = NULL;2360root_vpbl.pbl_pbase = 0;23612362get_random_bytes(&next_stag_index, sizeof(next_stag_index));2363stag_key = (u8)next_stag_index;23642365driver_key = next_stag_index & 0x70000000;23662367next_stag_index >>= 8;2368next_stag_index %= nesadapter->max_mr;23692370err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,2371nesadapter->max_mr, &stag_index, &next_stag_index);2372if (err) {2373ib_umem_release(region);2374return ERR_PTR(err);2375}23762377nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);2378if (!nesmr) {2379ib_umem_release(region);2380nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);2381return ERR_PTR(-ENOMEM);2382}2383nesmr->region = region;23842385list_for_each_entry(chunk, ®ion->chunk_list, list) {2386nes_debug(NES_DBG_MR, "Chunk: nents = %u, nmap = %u .\n",2387chunk->nents, chunk->nmap);2388for (nmap_index = 0; nmap_index < chunk->nmap; ++nmap_index) {2389if (sg_dma_address(&chunk->page_list[nmap_index]) & ~PAGE_MASK) {2390ib_umem_release(region);2391nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);2392nes_debug(NES_DBG_MR, "Unaligned Memory Buffer: 0x%x\n",2393(unsigned int) sg_dma_address(&chunk->page_list[nmap_index]));2394ibmr = ERR_PTR(-EINVAL);2395kfree(nesmr);2396goto reg_user_mr_err;2397}23982399if (!sg_dma_len(&chunk->page_list[nmap_index])) {2400ib_umem_release(region);2401nes_free_resource(nesadapter, nesadapter->allocated_mrs,2402stag_index);2403nes_debug(NES_DBG_MR, "Invalid Buffer Size\n");2404ibmr = ERR_PTR(-EINVAL);2405kfree(nesmr);2406goto reg_user_mr_err;2407}24082409region_length += sg_dma_len(&chunk->page_list[nmap_index]);2410chunk_pages = sg_dma_len(&chunk->page_list[nmap_index]) >> 12;2411region_length -= skip_pages << 12;2412for (page_index=skip_pages; page_index < chunk_pages; page_index++) {2413skip_pages = 0;2414if ((page_count!=0)&&(page_count<<12)-(region->offset&(4096-1))>=region->length)2415goto enough_pages;2416if ((page_count&0x01FF) == 0) {2417if (page_count >= 1024 * 512) {2418ib_umem_release(region);2419nes_free_resource(nesadapter,2420nesadapter->allocated_mrs, stag_index);2421kfree(nesmr);2422ibmr = ERR_PTR(-E2BIG);2423goto reg_user_mr_err;2424}2425if (root_pbl_index == 1) {2426root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev,24278192, &root_vpbl.pbl_pbase);2428nes_debug(NES_DBG_MR, "Allocating root PBL, va = %p, pa = 0x%08X\n",2429root_vpbl.pbl_vbase, (unsigned int)root_vpbl.pbl_pbase);2430if (!root_vpbl.pbl_vbase) {2431ib_umem_release(region);2432pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,2433vpbl.pbl_pbase);2434nes_free_resource(nesadapter, nesadapter->allocated_mrs,2435stag_index);2436kfree(nesmr);2437ibmr = ERR_PTR(-ENOMEM);2438goto reg_user_mr_err;2439}2440root_vpbl.leaf_vpbl = kzalloc(sizeof(*root_vpbl.leaf_vpbl)*1024,2441GFP_KERNEL);2442if (!root_vpbl.leaf_vpbl) {2443ib_umem_release(region);2444pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase,2445root_vpbl.pbl_pbase);2446pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,2447vpbl.pbl_pbase);2448nes_free_resource(nesadapter, nesadapter->allocated_mrs,2449stag_index);2450kfree(nesmr);2451ibmr = ERR_PTR(-ENOMEM);2452goto reg_user_mr_err;2453}2454root_vpbl.pbl_vbase[0].pa_low =2455cpu_to_le32((u32)vpbl.pbl_pbase);2456root_vpbl.pbl_vbase[0].pa_high =2457cpu_to_le32((u32)((((u64)vpbl.pbl_pbase) >> 32)));2458root_vpbl.leaf_vpbl[0] = vpbl;2459}2460vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096,2461&vpbl.pbl_pbase);2462nes_debug(NES_DBG_MR, "Allocating leaf PBL, va = %p, pa = 0x%08X\n",2463vpbl.pbl_vbase, (unsigned int)vpbl.pbl_pbase);2464if (!vpbl.pbl_vbase) {2465ib_umem_release(region);2466nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);2467ibmr = ERR_PTR(-ENOMEM);2468kfree(nesmr);2469goto reg_user_mr_err;2470}2471if (1 <= root_pbl_index) {2472root_vpbl.pbl_vbase[root_pbl_index].pa_low =2473cpu_to_le32((u32)vpbl.pbl_pbase);2474root_vpbl.pbl_vbase[root_pbl_index].pa_high =2475cpu_to_le32((u32)((((u64)vpbl.pbl_pbase)>>32)));2476root_vpbl.leaf_vpbl[root_pbl_index] = vpbl;2477}2478root_pbl_index++;2479cur_pbl_index = 0;2480}2481if (single_page) {2482if (page_count != 0) {2483if ((last_dma_addr+4096) !=2484(sg_dma_address(&chunk->page_list[nmap_index])+2485(page_index*4096)))2486single_page = 0;2487last_dma_addr = sg_dma_address(&chunk->page_list[nmap_index])+2488(page_index*4096);2489} else {2490first_dma_addr = sg_dma_address(&chunk->page_list[nmap_index])+2491(page_index*4096);2492last_dma_addr = first_dma_addr;2493}2494}24952496vpbl.pbl_vbase[cur_pbl_index].pa_low =2497cpu_to_le32((u32)(sg_dma_address(&chunk->page_list[nmap_index])+2498(page_index*4096)));2499vpbl.pbl_vbase[cur_pbl_index].pa_high =2500cpu_to_le32((u32)((((u64)(sg_dma_address(&chunk->page_list[nmap_index])+2501(page_index*4096))) >> 32)));2502cur_pbl_index++;2503page_count++;2504}2505}2506}2507enough_pages:2508nes_debug(NES_DBG_MR, "calculating stag, stag_index=0x%08x, driver_key=0x%08x,"2509" stag_key=0x%08x\n",2510stag_index, driver_key, stag_key);2511stag = stag_index << 8;2512stag |= driver_key;2513stag += (u32)stag_key;25142515iova_start = virt;2516/* Make the leaf PBL the root if only one PBL */2517if (root_pbl_index == 1) {2518root_vpbl.pbl_pbase = vpbl.pbl_pbase;2519}25202521if (single_page) {2522pbl_count = 0;2523} else {2524pbl_count = root_pbl_index;2525first_dma_addr = 0;2526}2527nes_debug(NES_DBG_MR, "Registering STag 0x%08X, VA = 0x%08X, length = 0x%08X,"2528" index = 0x%08X, region->length=0x%08llx, pbl_count = %u\n",2529stag, (unsigned int)iova_start,2530(unsigned int)region_length, stag_index,2531(unsigned long long)region->length, pbl_count);2532ret = nes_reg_mr(nesdev, nespd, stag, region->length, &root_vpbl,2533first_dma_addr, pbl_count, (u16)cur_pbl_index, acc,2534&iova_start, &nesmr->pbls_used, &nesmr->pbl_4k);25352536nes_debug(NES_DBG_MR, "ret=%d\n", ret);25372538if (ret == 0) {2539nesmr->ibmr.rkey = stag;2540nesmr->ibmr.lkey = stag;2541nesmr->mode = IWNES_MEMREG_TYPE_MEM;2542ibmr = &nesmr->ibmr;2543} else {2544ib_umem_release(region);2545kfree(nesmr);2546ibmr = ERR_PTR(-ENOMEM);2547}25482549reg_user_mr_err:2550/* free the resources */2551if (root_pbl_index == 1) {2552pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,2553vpbl.pbl_pbase);2554} else {2555for (page_index=0; page_index<root_pbl_index; page_index++) {2556pci_free_consistent(nesdev->pcidev, 4096,2557root_vpbl.leaf_vpbl[page_index].pbl_vbase,2558root_vpbl.leaf_vpbl[page_index].pbl_pbase);2559}2560kfree(root_vpbl.leaf_vpbl);2561pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase,2562root_vpbl.pbl_pbase);2563}25642565nes_debug(NES_DBG_MR, "Leaving, ibmr=%p", ibmr);25662567return ibmr;2568case IWNES_MEMREG_TYPE_QP:2569case IWNES_MEMREG_TYPE_CQ:2570nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL);2571if (!nespbl) {2572nes_debug(NES_DBG_MR, "Unable to allocate PBL\n");2573ib_umem_release(region);2574return ERR_PTR(-ENOMEM);2575}2576nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);2577if (!nesmr) {2578ib_umem_release(region);2579kfree(nespbl);2580nes_debug(NES_DBG_MR, "Unable to allocate nesmr\n");2581return ERR_PTR(-ENOMEM);2582}2583nesmr->region = region;2584nes_ucontext = to_nesucontext(pd->uobject->context);2585pbl_depth = region->length >> 12;2586pbl_depth += (region->length & (4096-1)) ? 1 : 0;2587nespbl->pbl_size = pbl_depth*sizeof(u64);2588if (req.reg_type == IWNES_MEMREG_TYPE_QP) {2589nes_debug(NES_DBG_MR, "Attempting to allocate QP PBL memory");2590} else {2591nes_debug(NES_DBG_MR, "Attempting to allocate CP PBL memory");2592}25932594nes_debug(NES_DBG_MR, " %u bytes, %u entries.\n",2595nespbl->pbl_size, pbl_depth);2596pbl = pci_alloc_consistent(nesdev->pcidev, nespbl->pbl_size,2597&nespbl->pbl_pbase);2598if (!pbl) {2599ib_umem_release(region);2600kfree(nesmr);2601kfree(nespbl);2602nes_debug(NES_DBG_MR, "Unable to allocate PBL memory\n");2603return ERR_PTR(-ENOMEM);2604}26052606nespbl->pbl_vbase = (u64 *)pbl;2607nespbl->user_base = start;2608nes_debug(NES_DBG_MR, "Allocated PBL memory, %u bytes, pbl_pbase=%lx,"2609" pbl_vbase=%p user_base=0x%lx\n",2610nespbl->pbl_size, (unsigned long) nespbl->pbl_pbase,2611(void *) nespbl->pbl_vbase, nespbl->user_base);26122613list_for_each_entry(chunk, ®ion->chunk_list, list) {2614for (nmap_index = 0; nmap_index < chunk->nmap; ++nmap_index) {2615chunk_pages = sg_dma_len(&chunk->page_list[nmap_index]) >> 12;2616chunk_pages += (sg_dma_len(&chunk->page_list[nmap_index]) & (4096-1)) ? 1 : 0;2617nespbl->page = sg_page(&chunk->page_list[0]);2618for (page_index=0; page_index<chunk_pages; page_index++) {2619((__le32 *)pbl)[0] = cpu_to_le32((u32)2620(sg_dma_address(&chunk->page_list[nmap_index])+2621(page_index*4096)));2622((__le32 *)pbl)[1] = cpu_to_le32(((u64)2623(sg_dma_address(&chunk->page_list[nmap_index])+2624(page_index*4096)))>>32);2625nes_debug(NES_DBG_MR, "pbl=%p, *pbl=0x%016llx, 0x%08x%08x\n", pbl,2626(unsigned long long)*pbl,2627le32_to_cpu(((__le32 *)pbl)[1]), le32_to_cpu(((__le32 *)pbl)[0]));2628pbl++;2629}2630}2631}2632if (req.reg_type == IWNES_MEMREG_TYPE_QP) {2633list_add_tail(&nespbl->list, &nes_ucontext->qp_reg_mem_list);2634} else {2635list_add_tail(&nespbl->list, &nes_ucontext->cq_reg_mem_list);2636}2637nesmr->ibmr.rkey = -1;2638nesmr->ibmr.lkey = -1;2639nesmr->mode = req.reg_type;2640return &nesmr->ibmr;2641}26422643return ERR_PTR(-ENOSYS);2644}264526462647/**2648* nes_dereg_mr2649*/2650static int nes_dereg_mr(struct ib_mr *ib_mr)2651{2652struct nes_mr *nesmr = to_nesmr(ib_mr);2653struct nes_vnic *nesvnic = to_nesvnic(ib_mr->device);2654struct nes_device *nesdev = nesvnic->nesdev;2655struct nes_adapter *nesadapter = nesdev->nesadapter;2656struct nes_hw_cqp_wqe *cqp_wqe;2657struct nes_cqp_request *cqp_request;2658unsigned long flags;2659int ret;2660u16 major_code;2661u16 minor_code;26622663if (nesmr->region) {2664ib_umem_release(nesmr->region);2665}2666if (nesmr->mode != IWNES_MEMREG_TYPE_MEM) {2667kfree(nesmr);2668return 0;2669}26702671/* Deallocate the region with the adapter */26722673cqp_request = nes_get_cqp_request(nesdev);2674if (cqp_request == NULL) {2675nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n");2676return -ENOMEM;2677}2678cqp_request->waiting = 1;2679cqp_wqe = &cqp_request->cqp_wqe;26802681nes_fill_init_cqp_wqe(cqp_wqe, nesdev);2682set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,2683NES_CQP_DEALLOCATE_STAG | NES_CQP_STAG_VA_TO |2684NES_CQP_STAG_DEALLOC_PBLS | NES_CQP_STAG_MR);2685set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, ib_mr->rkey);26862687atomic_set(&cqp_request->refcount, 2);2688nes_post_cqp_request(nesdev, cqp_request);26892690/* Wait for CQP */2691nes_debug(NES_DBG_MR, "Waiting for deallocate STag 0x%08X completed\n", ib_mr->rkey);2692ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),2693NES_EVENT_TIMEOUT);2694nes_debug(NES_DBG_MR, "Deallocate STag 0x%08X completed, wait_event_timeout ret = %u,"2695" CQP Major:Minor codes = 0x%04X:0x%04X\n",2696ib_mr->rkey, ret, cqp_request->major_code, cqp_request->minor_code);26972698major_code = cqp_request->major_code;2699minor_code = cqp_request->minor_code;27002701nes_put_cqp_request(nesdev, cqp_request);27022703if (!ret) {2704nes_debug(NES_DBG_MR, "Timeout waiting to destroy STag,"2705" ib_mr=%p, rkey = 0x%08X\n",2706ib_mr, ib_mr->rkey);2707return -ETIME;2708} else if (major_code) {2709nes_debug(NES_DBG_MR, "Error (0x%04X:0x%04X) while attempting"2710" to destroy STag, ib_mr=%p, rkey = 0x%08X\n",2711major_code, minor_code, ib_mr, ib_mr->rkey);2712return -EIO;2713}27142715if (nesmr->pbls_used != 0) {2716spin_lock_irqsave(&nesadapter->pbl_lock, flags);2717if (nesmr->pbl_4k) {2718nesadapter->free_4kpbl += nesmr->pbls_used;2719if (nesadapter->free_4kpbl > nesadapter->max_4kpbl)2720printk(KERN_ERR PFX "free 4KB PBLs(%u) has "2721"exceeded the max(%u)\n",2722nesadapter->free_4kpbl,2723nesadapter->max_4kpbl);2724} else {2725nesadapter->free_256pbl += nesmr->pbls_used;2726if (nesadapter->free_256pbl > nesadapter->max_256pbl)2727printk(KERN_ERR PFX "free 256B PBLs(%u) has "2728"exceeded the max(%u)\n",2729nesadapter->free_256pbl,2730nesadapter->max_256pbl);2731}2732spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);2733}2734nes_free_resource(nesadapter, nesadapter->allocated_mrs,2735(ib_mr->rkey & 0x0fffff00) >> 8);27362737kfree(nesmr);27382739return 0;2740}274127422743/**2744* show_rev2745*/2746static ssize_t show_rev(struct device *dev, struct device_attribute *attr,2747char *buf)2748{2749struct nes_ib_device *nesibdev =2750container_of(dev, struct nes_ib_device, ibdev.dev);2751struct nes_vnic *nesvnic = nesibdev->nesvnic;27522753nes_debug(NES_DBG_INIT, "\n");2754return sprintf(buf, "%x\n", nesvnic->nesdev->nesadapter->hw_rev);2755}275627572758/**2759* show_fw_ver2760*/2761static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr,2762char *buf)2763{2764struct nes_ib_device *nesibdev =2765container_of(dev, struct nes_ib_device, ibdev.dev);2766struct nes_vnic *nesvnic = nesibdev->nesvnic;27672768nes_debug(NES_DBG_INIT, "\n");2769return sprintf(buf, "%u.%u\n",2770(nesvnic->nesdev->nesadapter->firmware_version >> 16),2771(nesvnic->nesdev->nesadapter->firmware_version & 0x000000ff));2772}277327742775/**2776* show_hca2777*/2778static ssize_t show_hca(struct device *dev, struct device_attribute *attr,2779char *buf)2780{2781nes_debug(NES_DBG_INIT, "\n");2782return sprintf(buf, "NES020\n");2783}278427852786/**2787* show_board2788*/2789static ssize_t show_board(struct device *dev, struct device_attribute *attr,2790char *buf)2791{2792nes_debug(NES_DBG_INIT, "\n");2793return sprintf(buf, "%.*s\n", 32, "NES020 Board ID");2794}279527962797static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);2798static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);2799static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);2800static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);28012802static struct device_attribute *nes_dev_attributes[] = {2803&dev_attr_hw_rev,2804&dev_attr_fw_ver,2805&dev_attr_hca_type,2806&dev_attr_board_id2807};280828092810/**2811* nes_query_qp2812*/2813static int nes_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,2814int attr_mask, struct ib_qp_init_attr *init_attr)2815{2816struct nes_qp *nesqp = to_nesqp(ibqp);28172818nes_debug(NES_DBG_QP, "\n");28192820attr->qp_access_flags = 0;2821attr->cap.max_send_wr = nesqp->hwqp.sq_size;2822attr->cap.max_recv_wr = nesqp->hwqp.rq_size;2823attr->cap.max_recv_sge = 1;2824if (nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA)2825attr->cap.max_inline_data = 0;2826else2827attr->cap.max_inline_data = 64;28282829init_attr->event_handler = nesqp->ibqp.event_handler;2830init_attr->qp_context = nesqp->ibqp.qp_context;2831init_attr->send_cq = nesqp->ibqp.send_cq;2832init_attr->recv_cq = nesqp->ibqp.recv_cq;2833init_attr->srq = nesqp->ibqp.srq = nesqp->ibqp.srq;2834init_attr->cap = attr->cap;28352836return 0;2837}283828392840/**2841* nes_hw_modify_qp2842*/2843int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp,2844u32 next_iwarp_state, u32 termlen, u32 wait_completion)2845{2846struct nes_hw_cqp_wqe *cqp_wqe;2847/* struct iw_cm_id *cm_id = nesqp->cm_id; */2848/* struct iw_cm_event cm_event; */2849struct nes_cqp_request *cqp_request;2850int ret;2851u16 major_code;28522853nes_debug(NES_DBG_MOD_QP, "QP%u, refcount=%d\n",2854nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount));28552856cqp_request = nes_get_cqp_request(nesdev);2857if (cqp_request == NULL) {2858nes_debug(NES_DBG_MOD_QP, "Failed to get a cqp_request.\n");2859return -ENOMEM;2860}2861if (wait_completion) {2862cqp_request->waiting = 1;2863} else {2864cqp_request->waiting = 0;2865}2866cqp_wqe = &cqp_request->cqp_wqe;28672868set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,2869NES_CQP_MODIFY_QP | NES_CQP_QP_TYPE_IWARP | next_iwarp_state);2870nes_debug(NES_DBG_MOD_QP, "using next_iwarp_state=%08x, wqe_words=%08x\n",2871next_iwarp_state, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]));2872nes_fill_init_cqp_wqe(cqp_wqe, nesdev);2873set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);2874set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, (u64)nesqp->nesqp_context_pbase);28752876/* If sending a terminate message, fill in the length (in words) */2877if (((next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK) == NES_CQP_QP_IWARP_STATE_TERMINATE) &&2878!(next_iwarp_state & NES_CQP_QP_TERM_DONT_SEND_TERM_MSG)) {2879termlen = ((termlen + 3) >> 2) << NES_CQP_OP_TERMLEN_SHIFT;2880set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_NEW_MSS_IDX, termlen);2881}28822883atomic_set(&cqp_request->refcount, 2);2884nes_post_cqp_request(nesdev, cqp_request);28852886/* Wait for CQP */2887if (wait_completion) {2888/* nes_debug(NES_DBG_MOD_QP, "Waiting for modify iWARP QP%u to complete.\n",2889nesqp->hwqp.qp_id); */2890ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),2891NES_EVENT_TIMEOUT);2892nes_debug(NES_DBG_MOD_QP, "Modify iwarp QP%u completed, wait_event_timeout ret=%u, "2893"CQP Major:Minor codes = 0x%04X:0x%04X.\n",2894nesqp->hwqp.qp_id, ret, cqp_request->major_code, cqp_request->minor_code);2895major_code = cqp_request->major_code;2896if (major_code) {2897nes_debug(NES_DBG_MOD_QP, "Modify iwarp QP%u failed"2898"CQP Major:Minor codes = 0x%04X:0x%04X, intended next state = 0x%08X.\n",2899nesqp->hwqp.qp_id, cqp_request->major_code,2900cqp_request->minor_code, next_iwarp_state);2901}29022903nes_put_cqp_request(nesdev, cqp_request);29042905if (!ret)2906return -ETIME;2907else if (major_code)2908return -EIO;2909else2910return 0;2911} else {2912return 0;2913}2914}291529162917/**2918* nes_modify_qp2919*/2920int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,2921int attr_mask, struct ib_udata *udata)2922{2923struct nes_qp *nesqp = to_nesqp(ibqp);2924struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);2925struct nes_device *nesdev = nesvnic->nesdev;2926/* u32 cqp_head; */2927/* u32 counter; */2928u32 next_iwarp_state = 0;2929int err;2930unsigned long qplockflags;2931int ret;2932u16 original_last_aeq;2933u8 issue_modify_qp = 0;2934u8 dont_wait = 0;29352936nes_debug(NES_DBG_MOD_QP, "QP%u: QP State=%u, cur QP State=%u,"2937" iwarp_state=0x%X, refcount=%d\n",2938nesqp->hwqp.qp_id, attr->qp_state, nesqp->ibqp_state,2939nesqp->iwarp_state, atomic_read(&nesqp->refcount));29402941spin_lock_irqsave(&nesqp->lock, qplockflags);29422943nes_debug(NES_DBG_MOD_QP, "QP%u: hw_iwarp_state=0x%X, hw_tcp_state=0x%X,"2944" QP Access Flags=0x%X, attr_mask = 0x%0x\n",2945nesqp->hwqp.qp_id, nesqp->hw_iwarp_state,2946nesqp->hw_tcp_state, attr->qp_access_flags, attr_mask);29472948if (attr_mask & IB_QP_STATE) {2949switch (attr->qp_state) {2950case IB_QPS_INIT:2951nes_debug(NES_DBG_MOD_QP, "QP%u: new state = init\n",2952nesqp->hwqp.qp_id);2953if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_IDLE) {2954spin_unlock_irqrestore(&nesqp->lock, qplockflags);2955return -EINVAL;2956}2957next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE;2958issue_modify_qp = 1;2959break;2960case IB_QPS_RTR:2961nes_debug(NES_DBG_MOD_QP, "QP%u: new state = rtr\n",2962nesqp->hwqp.qp_id);2963if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_IDLE) {2964spin_unlock_irqrestore(&nesqp->lock, qplockflags);2965return -EINVAL;2966}2967next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE;2968issue_modify_qp = 1;2969break;2970case IB_QPS_RTS:2971nes_debug(NES_DBG_MOD_QP, "QP%u: new state = rts\n",2972nesqp->hwqp.qp_id);2973if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_RTS) {2974spin_unlock_irqrestore(&nesqp->lock, qplockflags);2975return -EINVAL;2976}2977if (nesqp->cm_id == NULL) {2978nes_debug(NES_DBG_MOD_QP, "QP%u: Failing attempt to move QP to RTS without a CM_ID. \n",2979nesqp->hwqp.qp_id );2980spin_unlock_irqrestore(&nesqp->lock, qplockflags);2981return -EINVAL;2982}2983next_iwarp_state = NES_CQP_QP_IWARP_STATE_RTS;2984if (nesqp->iwarp_state != NES_CQP_QP_IWARP_STATE_RTS)2985next_iwarp_state |= NES_CQP_QP_CONTEXT_VALID |2986NES_CQP_QP_ARP_VALID | NES_CQP_QP_ORD_VALID;2987issue_modify_qp = 1;2988nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_ESTABLISHED;2989nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_RTS;2990nesqp->hte_added = 1;2991break;2992case IB_QPS_SQD:2993issue_modify_qp = 1;2994nes_debug(NES_DBG_MOD_QP, "QP%u: new state=closing. SQ head=%u, SQ tail=%u\n",2995nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, nesqp->hwqp.sq_tail);2996if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_CLOSING) {2997spin_unlock_irqrestore(&nesqp->lock, qplockflags);2998return 0;2999} else {3000if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_CLOSING) {3001nes_debug(NES_DBG_MOD_QP, "QP%u: State change to closing"3002" ignored due to current iWARP state\n",3003nesqp->hwqp.qp_id);3004spin_unlock_irqrestore(&nesqp->lock, qplockflags);3005return -EINVAL;3006}3007if (nesqp->hw_iwarp_state != NES_AEQE_IWARP_STATE_RTS) {3008nes_debug(NES_DBG_MOD_QP, "QP%u: State change to closing"3009" already done based on hw state.\n",3010nesqp->hwqp.qp_id);3011issue_modify_qp = 0;3012}3013switch (nesqp->hw_iwarp_state) {3014case NES_AEQE_IWARP_STATE_CLOSING:3015next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;3016case NES_AEQE_IWARP_STATE_TERMINATE:3017next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE;3018break;3019case NES_AEQE_IWARP_STATE_ERROR:3020next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR;3021break;3022default:3023next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;3024nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;3025break;3026}3027}3028break;3029case IB_QPS_SQE:3030nes_debug(NES_DBG_MOD_QP, "QP%u: new state = terminate\n",3031nesqp->hwqp.qp_id);3032if (nesqp->iwarp_state>=(u32)NES_CQP_QP_IWARP_STATE_TERMINATE) {3033spin_unlock_irqrestore(&nesqp->lock, qplockflags);3034return -EINVAL;3035}3036/* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */3037next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE;3038nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_TERMINATE;3039issue_modify_qp = 1;3040break;3041case IB_QPS_ERR:3042case IB_QPS_RESET:3043if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_ERROR) {3044spin_unlock_irqrestore(&nesqp->lock, qplockflags);3045return -EINVAL;3046}3047nes_debug(NES_DBG_MOD_QP, "QP%u: new state = error\n",3048nesqp->hwqp.qp_id);3049if (nesqp->term_flags)3050del_timer(&nesqp->terminate_timer);30513052next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR;3053/* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */3054if (nesqp->hte_added) {3055nes_debug(NES_DBG_MOD_QP, "set CQP_QP_DEL_HTE\n");3056next_iwarp_state |= NES_CQP_QP_DEL_HTE;3057nesqp->hte_added = 0;3058}3059if ((nesqp->hw_tcp_state > NES_AEQE_TCP_STATE_CLOSED) &&3060(nesdev->iw_status) &&3061(nesqp->hw_tcp_state != NES_AEQE_TCP_STATE_TIME_WAIT)) {3062next_iwarp_state |= NES_CQP_QP_RESET;3063} else {3064nes_debug(NES_DBG_MOD_QP, "QP%u NOT setting NES_CQP_QP_RESET since TCP state = %u\n",3065nesqp->hwqp.qp_id, nesqp->hw_tcp_state);3066dont_wait = 1;3067}3068issue_modify_qp = 1;3069nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_ERROR;3070break;3071default:3072spin_unlock_irqrestore(&nesqp->lock, qplockflags);3073return -EINVAL;3074break;3075}30763077nesqp->ibqp_state = attr->qp_state;3078if (((nesqp->iwarp_state & NES_CQP_QP_IWARP_STATE_MASK) ==3079(u32)NES_CQP_QP_IWARP_STATE_RTS) &&3080((next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK) >3081(u32)NES_CQP_QP_IWARP_STATE_RTS)) {3082nesqp->iwarp_state = next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK;3083nes_debug(NES_DBG_MOD_QP, "Change nesqp->iwarp_state=%08x\n",3084nesqp->iwarp_state);3085} else {3086nesqp->iwarp_state = next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK;3087nes_debug(NES_DBG_MOD_QP, "Change nesqp->iwarp_state=%08x\n",3088nesqp->iwarp_state);3089}3090}30913092if (attr_mask & IB_QP_ACCESS_FLAGS) {3093if (attr->qp_access_flags & IB_ACCESS_LOCAL_WRITE) {3094nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_WRITE_EN |3095NES_QPCONTEXT_MISC_RDMA_READ_EN);3096issue_modify_qp = 1;3097}3098if (attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE) {3099nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_WRITE_EN);3100issue_modify_qp = 1;3101}3102if (attr->qp_access_flags & IB_ACCESS_REMOTE_READ) {3103nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_READ_EN);3104issue_modify_qp = 1;3105}3106if (attr->qp_access_flags & IB_ACCESS_MW_BIND) {3107nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WBIND_EN);3108issue_modify_qp = 1;3109}31103111if (nesqp->user_mode) {3112nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_WRITE_EN |3113NES_QPCONTEXT_MISC_RDMA_READ_EN);3114issue_modify_qp = 1;3115}3116}31173118original_last_aeq = nesqp->last_aeq;3119spin_unlock_irqrestore(&nesqp->lock, qplockflags);31203121nes_debug(NES_DBG_MOD_QP, "issue_modify_qp=%u\n", issue_modify_qp);31223123ret = 0;312431253126if (issue_modify_qp) {3127nes_debug(NES_DBG_MOD_QP, "call nes_hw_modify_qp\n");3128ret = nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 1);3129if (ret)3130nes_debug(NES_DBG_MOD_QP, "nes_hw_modify_qp (next_iwarp_state = 0x%08X)"3131" failed for QP%u.\n",3132next_iwarp_state, nesqp->hwqp.qp_id);31333134}31353136if ((issue_modify_qp) && (nesqp->ibqp_state > IB_QPS_RTS)) {3137nes_debug(NES_DBG_MOD_QP, "QP%u Issued ModifyQP refcount (%d),"3138" original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",3139nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),3140original_last_aeq, nesqp->last_aeq);3141if ((!ret) ||3142((original_last_aeq != NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) &&3143(ret))) {3144if (dont_wait) {3145if (nesqp->cm_id && nesqp->hw_tcp_state != 0) {3146nes_debug(NES_DBG_MOD_QP, "QP%u Queuing fake disconnect for QP refcount (%d),"3147" original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",3148nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),3149original_last_aeq, nesqp->last_aeq);3150/* this one is for the cm_disconnect thread */3151spin_lock_irqsave(&nesqp->lock, qplockflags);3152nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;3153nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;3154spin_unlock_irqrestore(&nesqp->lock, qplockflags);3155nes_cm_disconn(nesqp);3156} else {3157nes_debug(NES_DBG_MOD_QP, "QP%u No fake disconnect, QP refcount=%d\n",3158nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount));3159}3160} else {3161spin_lock_irqsave(&nesqp->lock, qplockflags);3162if (nesqp->cm_id) {3163/* These two are for the timer thread */3164if (atomic_inc_return(&nesqp->close_timer_started) == 1) {3165nesqp->cm_id->add_ref(nesqp->cm_id);3166nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d),"3167" need ae to finish up, original_last_aeq = 0x%04X."3168" last_aeq = 0x%04X, scheduling timer.\n",3169nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),3170original_last_aeq, nesqp->last_aeq);3171schedule_nes_timer(nesqp->cm_node, (struct sk_buff *) nesqp, NES_TIMER_TYPE_CLOSE, 1, 0);3172}3173spin_unlock_irqrestore(&nesqp->lock, qplockflags);3174} else {3175spin_unlock_irqrestore(&nesqp->lock, qplockflags);3176nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d),"3177" need ae to finish up, original_last_aeq = 0x%04X."3178" last_aeq = 0x%04X.\n",3179nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),3180original_last_aeq, nesqp->last_aeq);3181}3182}3183} else {3184nes_debug(NES_DBG_MOD_QP, "QP%u Decrementing QP refcount (%d), No ae to finish up,"3185" original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",3186nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),3187original_last_aeq, nesqp->last_aeq);3188}3189} else {3190nes_debug(NES_DBG_MOD_QP, "QP%u Decrementing QP refcount (%d), No ae to finish up,"3191" original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",3192nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),3193original_last_aeq, nesqp->last_aeq);3194}31953196err = 0;31973198nes_debug(NES_DBG_MOD_QP, "QP%u Leaving, refcount=%d\n",3199nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount));32003201return err;3202}320332043205/**3206* nes_muticast_attach3207*/3208static int nes_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)3209{3210nes_debug(NES_DBG_INIT, "\n");3211return -ENOSYS;3212}321332143215/**3216* nes_multicast_detach3217*/3218static int nes_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)3219{3220nes_debug(NES_DBG_INIT, "\n");3221return -ENOSYS;3222}322332243225/**3226* nes_process_mad3227*/3228static int nes_process_mad(struct ib_device *ibdev, int mad_flags,3229u8 port_num, struct ib_wc *in_wc, struct ib_grh *in_grh,3230struct ib_mad *in_mad, struct ib_mad *out_mad)3231{3232nes_debug(NES_DBG_INIT, "\n");3233return -ENOSYS;3234}32353236static inline void3237fill_wqe_sg_send(struct nes_hw_qp_wqe *wqe, struct ib_send_wr *ib_wr, u32 uselkey)3238{3239int sge_index;3240int total_payload_length = 0;3241for (sge_index = 0; sge_index < ib_wr->num_sge; sge_index++) {3242set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_FRAG0_LOW_IDX+(sge_index*4),3243ib_wr->sg_list[sge_index].addr);3244set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_LENGTH0_IDX + (sge_index*4),3245ib_wr->sg_list[sge_index].length);3246if (uselkey)3247set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX + (sge_index*4),3248(ib_wr->sg_list[sge_index].lkey));3249else3250set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX + (sge_index*4), 0);32513252total_payload_length += ib_wr->sg_list[sge_index].length;3253}3254nes_debug(NES_DBG_IW_TX, "UC UC UC, sending total_payload_length=%u \n",3255total_payload_length);3256set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX,3257total_payload_length);3258}32593260/**3261* nes_post_send3262*/3263static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,3264struct ib_send_wr **bad_wr)3265{3266u64 u64temp;3267unsigned long flags = 0;3268struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);3269struct nes_device *nesdev = nesvnic->nesdev;3270struct nes_qp *nesqp = to_nesqp(ibqp);3271struct nes_hw_qp_wqe *wqe;3272int err = 0;3273u32 qsize = nesqp->hwqp.sq_size;3274u32 head;3275u32 wqe_misc = 0;3276u32 wqe_count = 0;3277u32 counter;32783279if (nesqp->ibqp_state > IB_QPS_RTS) {3280err = -EINVAL;3281goto out;3282}32833284spin_lock_irqsave(&nesqp->lock, flags);32853286head = nesqp->hwqp.sq_head;32873288while (ib_wr) {3289/* Check for QP error */3290if (nesqp->term_flags) {3291err = -EINVAL;3292break;3293}32943295/* Check for SQ overflow */3296if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) {3297err = -ENOMEM;3298break;3299}33003301wqe = &nesqp->hwqp.sq_vbase[head];3302/* nes_debug(NES_DBG_IW_TX, "processing sq wqe for QP%u at %p, head = %u.\n",3303nesqp->hwqp.qp_id, wqe, head); */3304nes_fill_init_qp_wqe(wqe, nesqp, head);3305u64temp = (u64)(ib_wr->wr_id);3306set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX,3307u64temp);3308switch (ib_wr->opcode) {3309case IB_WR_SEND:3310case IB_WR_SEND_WITH_INV:3311if (IB_WR_SEND == ib_wr->opcode) {3312if (ib_wr->send_flags & IB_SEND_SOLICITED)3313wqe_misc = NES_IWARP_SQ_OP_SENDSE;3314else3315wqe_misc = NES_IWARP_SQ_OP_SEND;3316} else {3317if (ib_wr->send_flags & IB_SEND_SOLICITED)3318wqe_misc = NES_IWARP_SQ_OP_SENDSEINV;3319else3320wqe_misc = NES_IWARP_SQ_OP_SENDINV;33213322set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_INV_STAG_LOW_IDX,3323ib_wr->ex.invalidate_rkey);3324}33253326if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {3327err = -EINVAL;3328break;3329}33303331if (ib_wr->send_flags & IB_SEND_FENCE)3332wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;33333334if ((ib_wr->send_flags & IB_SEND_INLINE) &&3335((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) &&3336(ib_wr->sg_list[0].length <= 64)) {3337memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX],3338(void *)(unsigned long)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length);3339set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX,3340ib_wr->sg_list[0].length);3341wqe_misc |= NES_IWARP_SQ_WQE_IMM_DATA;3342} else {3343fill_wqe_sg_send(wqe, ib_wr, 1);3344}33453346break;3347case IB_WR_RDMA_WRITE:3348wqe_misc = NES_IWARP_SQ_OP_RDMAW;3349if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {3350nes_debug(NES_DBG_IW_TX, "Exceeded max sge, ib_wr=%u, max=%u\n",3351ib_wr->num_sge, nesdev->nesadapter->max_sge);3352err = -EINVAL;3353break;3354}33553356if (ib_wr->send_flags & IB_SEND_FENCE)3357wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;33583359set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX,3360ib_wr->wr.rdma.rkey);3361set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX,3362ib_wr->wr.rdma.remote_addr);33633364if ((ib_wr->send_flags & IB_SEND_INLINE) &&3365((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) &&3366(ib_wr->sg_list[0].length <= 64)) {3367memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX],3368(void *)(unsigned long)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length);3369set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX,3370ib_wr->sg_list[0].length);3371wqe_misc |= NES_IWARP_SQ_WQE_IMM_DATA;3372} else {3373fill_wqe_sg_send(wqe, ib_wr, 1);3374}33753376wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] =3377wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX];3378break;3379case IB_WR_RDMA_READ:3380case IB_WR_RDMA_READ_WITH_INV:3381/* iWARP only supports 1 sge for RDMA reads */3382if (ib_wr->num_sge > 1) {3383nes_debug(NES_DBG_IW_TX, "Exceeded max sge, ib_wr=%u, max=1\n",3384ib_wr->num_sge);3385err = -EINVAL;3386break;3387}3388if (ib_wr->opcode == IB_WR_RDMA_READ) {3389wqe_misc = NES_IWARP_SQ_OP_RDMAR;3390} else {3391wqe_misc = NES_IWARP_SQ_OP_RDMAR_LOCINV;3392set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_INV_STAG_LOW_IDX,3393ib_wr->ex.invalidate_rkey);3394}33953396set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX,3397ib_wr->wr.rdma.remote_addr);3398set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX,3399ib_wr->wr.rdma.rkey);3400set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX,3401ib_wr->sg_list->length);3402set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,3403ib_wr->sg_list->addr);3404set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX,3405ib_wr->sg_list->lkey);3406break;3407case IB_WR_LOCAL_INV:3408wqe_misc = NES_IWARP_SQ_OP_LOCINV;3409set_wqe_32bit_value(wqe->wqe_words,3410NES_IWARP_SQ_LOCINV_WQE_INV_STAG_IDX,3411ib_wr->ex.invalidate_rkey);3412break;3413case IB_WR_FAST_REG_MR:3414{3415int i;3416int flags = ib_wr->wr.fast_reg.access_flags;3417struct nes_ib_fast_reg_page_list *pnesfrpl =3418container_of(ib_wr->wr.fast_reg.page_list,3419struct nes_ib_fast_reg_page_list,3420ibfrpl);3421u64 *src_page_list = pnesfrpl->ibfrpl.page_list;3422u64 *dst_page_list = pnesfrpl->nes_wqe_pbl.kva;34233424if (ib_wr->wr.fast_reg.page_list_len >3425(NES_4K_PBL_CHUNK_SIZE / sizeof(u64))) {3426nes_debug(NES_DBG_IW_TX, "SQ_FMR: bad page_list_len\n");3427err = -EINVAL;3428break;3429}3430wqe_misc = NES_IWARP_SQ_OP_FAST_REG;3431set_wqe_64bit_value(wqe->wqe_words,3432NES_IWARP_SQ_FMR_WQE_VA_FBO_LOW_IDX,3433ib_wr->wr.fast_reg.iova_start);3434set_wqe_32bit_value(wqe->wqe_words,3435NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX,3436ib_wr->wr.fast_reg.length);3437set_wqe_32bit_value(wqe->wqe_words,3438NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX,3439ib_wr->wr.fast_reg.rkey);3440/* Set page size: */3441if (ib_wr->wr.fast_reg.page_shift == 12) {3442wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_4K;3443} else if (ib_wr->wr.fast_reg.page_shift == 21) {3444wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_2M;3445} else {3446nes_debug(NES_DBG_IW_TX, "Invalid page shift,"3447" ib_wr=%u, max=1\n", ib_wr->num_sge);3448err = -EINVAL;3449break;3450}3451/* Set access_flags */3452wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_LOCAL_READ;3453if (flags & IB_ACCESS_LOCAL_WRITE)3454wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_LOCAL_WRITE;34553456if (flags & IB_ACCESS_REMOTE_WRITE)3457wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_REMOTE_WRITE;34583459if (flags & IB_ACCESS_REMOTE_READ)3460wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_REMOTE_READ;34613462if (flags & IB_ACCESS_MW_BIND)3463wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_WINDOW_BIND;34643465/* Fill in PBL info: */3466if (ib_wr->wr.fast_reg.page_list_len >3467pnesfrpl->ibfrpl.max_page_list_len) {3468nes_debug(NES_DBG_IW_TX, "Invalid page list length,"3469" ib_wr=%p, value=%u, max=%u\n",3470ib_wr, ib_wr->wr.fast_reg.page_list_len,3471pnesfrpl->ibfrpl.max_page_list_len);3472err = -EINVAL;3473break;3474}34753476set_wqe_64bit_value(wqe->wqe_words,3477NES_IWARP_SQ_FMR_WQE_PBL_ADDR_LOW_IDX,3478pnesfrpl->nes_wqe_pbl.paddr);34793480set_wqe_32bit_value(wqe->wqe_words,3481NES_IWARP_SQ_FMR_WQE_PBL_LENGTH_IDX,3482ib_wr->wr.fast_reg.page_list_len * 8);34833484for (i = 0; i < ib_wr->wr.fast_reg.page_list_len; i++)3485dst_page_list[i] = cpu_to_le64(src_page_list[i]);34863487nes_debug(NES_DBG_IW_TX, "SQ_FMR: iova_start: %llx, "3488"length: %d, rkey: %0x, pgl_paddr: %llx, "3489"page_list_len: %u, wqe_misc: %x\n",3490(unsigned long long) ib_wr->wr.fast_reg.iova_start,3491ib_wr->wr.fast_reg.length,3492ib_wr->wr.fast_reg.rkey,3493(unsigned long long) pnesfrpl->nes_wqe_pbl.paddr,3494ib_wr->wr.fast_reg.page_list_len,3495wqe_misc);3496break;3497}3498default:3499/* error */3500err = -EINVAL;3501break;3502}35033504if (err)3505break;35063507if ((ib_wr->send_flags & IB_SEND_SIGNALED) || nesqp->sig_all)3508wqe_misc |= NES_IWARP_SQ_WQE_SIGNALED_COMPL;35093510wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = cpu_to_le32(wqe_misc);35113512ib_wr = ib_wr->next;3513head++;3514wqe_count++;3515if (head >= qsize)3516head = 0;35173518}35193520nesqp->hwqp.sq_head = head;3521barrier();3522while (wqe_count) {3523counter = min(wqe_count, ((u32)255));3524wqe_count -= counter;3525nes_write32(nesdev->regs + NES_WQE_ALLOC,3526(counter << 24) | 0x00800000 | nesqp->hwqp.qp_id);3527}35283529spin_unlock_irqrestore(&nesqp->lock, flags);35303531out:3532if (err)3533*bad_wr = ib_wr;3534return err;3535}353635373538/**3539* nes_post_recv3540*/3541static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr,3542struct ib_recv_wr **bad_wr)3543{3544u64 u64temp;3545unsigned long flags = 0;3546struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);3547struct nes_device *nesdev = nesvnic->nesdev;3548struct nes_qp *nesqp = to_nesqp(ibqp);3549struct nes_hw_qp_wqe *wqe;3550int err = 0;3551int sge_index;3552u32 qsize = nesqp->hwqp.rq_size;3553u32 head;3554u32 wqe_count = 0;3555u32 counter;3556u32 total_payload_length;35573558if (nesqp->ibqp_state > IB_QPS_RTS) {3559err = -EINVAL;3560goto out;3561}35623563spin_lock_irqsave(&nesqp->lock, flags);35643565head = nesqp->hwqp.rq_head;35663567while (ib_wr) {3568/* Check for QP error */3569if (nesqp->term_flags) {3570err = -EINVAL;3571break;3572}35733574if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {3575err = -EINVAL;3576break;3577}3578/* Check for RQ overflow */3579if (((head + (2 * qsize) - nesqp->hwqp.rq_tail) % qsize) == (qsize - 1)) {3580err = -ENOMEM;3581break;3582}35833584nes_debug(NES_DBG_IW_RX, "ibwr sge count = %u.\n", ib_wr->num_sge);3585wqe = &nesqp->hwqp.rq_vbase[head];35863587/* nes_debug(NES_DBG_IW_RX, "QP%u:processing rq wqe at %p, head = %u.\n",3588nesqp->hwqp.qp_id, wqe, head); */3589nes_fill_init_qp_wqe(wqe, nesqp, head);3590u64temp = (u64)(ib_wr->wr_id);3591set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX,3592u64temp);3593total_payload_length = 0;3594for (sge_index=0; sge_index < ib_wr->num_sge; sge_index++) {3595set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_RQ_WQE_FRAG0_LOW_IDX+(sge_index*4),3596ib_wr->sg_list[sge_index].addr);3597set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_RQ_WQE_LENGTH0_IDX+(sge_index*4),3598ib_wr->sg_list[sge_index].length);3599set_wqe_32bit_value(wqe->wqe_words,NES_IWARP_RQ_WQE_STAG0_IDX+(sge_index*4),3600ib_wr->sg_list[sge_index].lkey);36013602total_payload_length += ib_wr->sg_list[sge_index].length;3603}3604set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_RQ_WQE_TOTAL_PAYLOAD_IDX,3605total_payload_length);36063607ib_wr = ib_wr->next;3608head++;3609wqe_count++;3610if (head >= qsize)3611head = 0;3612}36133614nesqp->hwqp.rq_head = head;3615barrier();3616while (wqe_count) {3617counter = min(wqe_count, ((u32)255));3618wqe_count -= counter;3619nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter<<24) | nesqp->hwqp.qp_id);3620}36213622spin_unlock_irqrestore(&nesqp->lock, flags);36233624out:3625if (err)3626*bad_wr = ib_wr;3627return err;3628}362936303631/**3632* nes_poll_cq3633*/3634static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)3635{3636u64 u64temp;3637u64 wrid;3638unsigned long flags = 0;3639struct nes_vnic *nesvnic = to_nesvnic(ibcq->device);3640struct nes_device *nesdev = nesvnic->nesdev;3641struct nes_cq *nescq = to_nescq(ibcq);3642struct nes_qp *nesqp;3643struct nes_hw_cqe cqe;3644u32 head;3645u32 wq_tail = 0;3646u32 cq_size;3647u32 cqe_count = 0;3648u32 wqe_index;3649u32 u32temp;3650u32 move_cq_head = 1;3651u32 err_code;36523653nes_debug(NES_DBG_CQ, "\n");36543655spin_lock_irqsave(&nescq->lock, flags);36563657head = nescq->hw_cq.cq_head;3658cq_size = nescq->hw_cq.cq_size;36593660while (cqe_count < num_entries) {3661if ((le32_to_cpu(nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) &3662NES_CQE_VALID) == 0)3663break;36643665/*3666* Make sure we read CQ entry contents *after*3667* we've checked the valid bit.3668*/3669rmb();36703671cqe = nescq->hw_cq.cq_vbase[head];3672u32temp = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]);3673wqe_index = u32temp & (nesdev->nesadapter->max_qp_wr - 1);3674u32temp &= ~(NES_SW_CONTEXT_ALIGN-1);3675/* parse CQE, get completion context from WQE (either rq or sq) */3676u64temp = (((u64)(le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) |3677((u64)u32temp);36783679if (u64temp) {3680nesqp = (struct nes_qp *)(unsigned long)u64temp;3681memset(entry, 0, sizeof *entry);3682if (cqe.cqe_words[NES_CQE_ERROR_CODE_IDX] == 0) {3683entry->status = IB_WC_SUCCESS;3684} else {3685err_code = le32_to_cpu(cqe.cqe_words[NES_CQE_ERROR_CODE_IDX]);3686if (NES_IWARP_CQE_MAJOR_DRV == (err_code >> 16)) {3687entry->status = err_code & 0x0000ffff;36883689/* The rest of the cqe's will be marked as flushed */3690nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX] =3691cpu_to_le32((NES_IWARP_CQE_MAJOR_FLUSH << 16) |3692NES_IWARP_CQE_MINOR_FLUSH);3693} else3694entry->status = IB_WC_WR_FLUSH_ERR;3695}36963697entry->qp = &nesqp->ibqp;3698entry->src_qp = nesqp->hwqp.qp_id;36993700if (le32_to_cpu(cqe.cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_SQ) {3701if (nesqp->skip_lsmm) {3702nesqp->skip_lsmm = 0;3703nesqp->hwqp.sq_tail++;3704}37053706/* Working on a SQ Completion*/3707wrid = (((u64)(cpu_to_le32((u32)nesqp->hwqp.sq_vbase[wqe_index].3708wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |3709((u64)(cpu_to_le32((u32)nesqp->hwqp.sq_vbase[wqe_index].3710wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX])));3711entry->byte_len = le32_to_cpu(nesqp->hwqp.sq_vbase[wqe_index].3712wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX]);37133714switch (le32_to_cpu(nesqp->hwqp.sq_vbase[wqe_index].3715wqe_words[NES_IWARP_SQ_WQE_MISC_IDX]) & 0x3f) {3716case NES_IWARP_SQ_OP_RDMAW:3717nes_debug(NES_DBG_CQ, "Operation = RDMA WRITE.\n");3718entry->opcode = IB_WC_RDMA_WRITE;3719break;3720case NES_IWARP_SQ_OP_RDMAR:3721nes_debug(NES_DBG_CQ, "Operation = RDMA READ.\n");3722entry->opcode = IB_WC_RDMA_READ;3723entry->byte_len = le32_to_cpu(nesqp->hwqp.sq_vbase[wqe_index].3724wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX]);3725break;3726case NES_IWARP_SQ_OP_SENDINV:3727case NES_IWARP_SQ_OP_SENDSEINV:3728case NES_IWARP_SQ_OP_SEND:3729case NES_IWARP_SQ_OP_SENDSE:3730nes_debug(NES_DBG_CQ, "Operation = Send.\n");3731entry->opcode = IB_WC_SEND;3732break;3733case NES_IWARP_SQ_OP_LOCINV:3734entry->opcode = IB_WR_LOCAL_INV;3735break;3736case NES_IWARP_SQ_OP_FAST_REG:3737entry->opcode = IB_WC_FAST_REG_MR;3738break;3739}37403741nesqp->hwqp.sq_tail = (wqe_index+1)&(nesqp->hwqp.sq_size - 1);3742if ((entry->status != IB_WC_SUCCESS) && (nesqp->hwqp.sq_tail != nesqp->hwqp.sq_head)) {3743move_cq_head = 0;3744wq_tail = nesqp->hwqp.sq_tail;3745}3746} else {3747/* Working on a RQ Completion*/3748entry->byte_len = le32_to_cpu(cqe.cqe_words[NES_CQE_PAYLOAD_LENGTH_IDX]);3749wrid = ((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wqe_index].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_LOW_IDX]))) |3750((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wqe_index].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_HIGH_IDX]))<<32);3751entry->opcode = IB_WC_RECV;37523753nesqp->hwqp.rq_tail = (wqe_index+1)&(nesqp->hwqp.rq_size - 1);3754if ((entry->status != IB_WC_SUCCESS) && (nesqp->hwqp.rq_tail != nesqp->hwqp.rq_head)) {3755move_cq_head = 0;3756wq_tail = nesqp->hwqp.rq_tail;3757}3758}37593760entry->wr_id = wrid;3761entry++;3762cqe_count++;3763}37643765if (move_cq_head) {3766nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;3767if (++head >= cq_size)3768head = 0;3769nescq->polled_completions++;37703771if ((nescq->polled_completions > (cq_size / 2)) ||3772(nescq->polled_completions == 255)) {3773nes_debug(NES_DBG_CQ, "CQ%u Issuing CQE Allocate since more than half of cqes"3774" are pending %u of %u.\n",3775nescq->hw_cq.cq_number, nescq->polled_completions, cq_size);3776nes_write32(nesdev->regs+NES_CQE_ALLOC,3777nescq->hw_cq.cq_number | (nescq->polled_completions << 16));3778nescq->polled_completions = 0;3779}3780} else {3781/* Update the wqe index and set status to flush */3782wqe_index = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]);3783wqe_index = (wqe_index & (~(nesdev->nesadapter->max_qp_wr - 1))) | wq_tail;3784nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX] =3785cpu_to_le32(wqe_index);3786move_cq_head = 1; /* ready for next pass */3787}3788}37893790if (nescq->polled_completions) {3791nes_write32(nesdev->regs+NES_CQE_ALLOC,3792nescq->hw_cq.cq_number | (nescq->polled_completions << 16));3793nescq->polled_completions = 0;3794}37953796nescq->hw_cq.cq_head = head;3797nes_debug(NES_DBG_CQ, "Reporting %u completions for CQ%u.\n",3798cqe_count, nescq->hw_cq.cq_number);37993800spin_unlock_irqrestore(&nescq->lock, flags);38013802return cqe_count;3803}380438053806/**3807* nes_req_notify_cq3808*/3809static int nes_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags notify_flags)3810{3811struct nes_vnic *nesvnic = to_nesvnic(ibcq->device);3812struct nes_device *nesdev = nesvnic->nesdev;3813struct nes_cq *nescq = to_nescq(ibcq);3814u32 cq_arm;38153816nes_debug(NES_DBG_CQ, "Requesting notification for CQ%u.\n",3817nescq->hw_cq.cq_number);38183819cq_arm = nescq->hw_cq.cq_number;3820if ((notify_flags & IB_CQ_SOLICITED_MASK) == IB_CQ_NEXT_COMP)3821cq_arm |= NES_CQE_ALLOC_NOTIFY_NEXT;3822else if ((notify_flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED)3823cq_arm |= NES_CQE_ALLOC_NOTIFY_SE;3824else3825return -EINVAL;38263827nes_write32(nesdev->regs+NES_CQE_ALLOC, cq_arm);3828nes_read32(nesdev->regs+NES_CQE_ALLOC);38293830return 0;3831}383238333834/**3835* nes_init_ofa_device3836*/3837struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev)3838{3839struct nes_ib_device *nesibdev;3840struct nes_vnic *nesvnic = netdev_priv(netdev);3841struct nes_device *nesdev = nesvnic->nesdev;38423843nesibdev = (struct nes_ib_device *)ib_alloc_device(sizeof(struct nes_ib_device));3844if (nesibdev == NULL) {3845return NULL;3846}3847strlcpy(nesibdev->ibdev.name, "nes%d", IB_DEVICE_NAME_MAX);3848nesibdev->ibdev.owner = THIS_MODULE;38493850nesibdev->ibdev.node_type = RDMA_NODE_RNIC;3851memset(&nesibdev->ibdev.node_guid, 0, sizeof(nesibdev->ibdev.node_guid));3852memcpy(&nesibdev->ibdev.node_guid, netdev->dev_addr, 6);38533854nesibdev->ibdev.uverbs_cmd_mask =3855(1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |3856(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) |3857(1ull << IB_USER_VERBS_CMD_QUERY_PORT) |3858(1ull << IB_USER_VERBS_CMD_ALLOC_PD) |3859(1ull << IB_USER_VERBS_CMD_DEALLOC_PD) |3860(1ull << IB_USER_VERBS_CMD_REG_MR) |3861(1ull << IB_USER_VERBS_CMD_DEREG_MR) |3862(1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |3863(1ull << IB_USER_VERBS_CMD_CREATE_CQ) |3864(1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |3865(1ull << IB_USER_VERBS_CMD_CREATE_AH) |3866(1ull << IB_USER_VERBS_CMD_DESTROY_AH) |3867(1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) |3868(1ull << IB_USER_VERBS_CMD_CREATE_QP) |3869(1ull << IB_USER_VERBS_CMD_MODIFY_QP) |3870(1ull << IB_USER_VERBS_CMD_POLL_CQ) |3871(1ull << IB_USER_VERBS_CMD_DESTROY_QP) |3872(1ull << IB_USER_VERBS_CMD_ALLOC_MW) |3873(1ull << IB_USER_VERBS_CMD_BIND_MW) |3874(1ull << IB_USER_VERBS_CMD_DEALLOC_MW) |3875(1ull << IB_USER_VERBS_CMD_POST_RECV) |3876(1ull << IB_USER_VERBS_CMD_POST_SEND);38773878nesibdev->ibdev.phys_port_cnt = 1;3879nesibdev->ibdev.num_comp_vectors = 1;3880nesibdev->ibdev.dma_device = &nesdev->pcidev->dev;3881nesibdev->ibdev.dev.parent = &nesdev->pcidev->dev;3882nesibdev->ibdev.query_device = nes_query_device;3883nesibdev->ibdev.query_port = nes_query_port;3884nesibdev->ibdev.modify_port = nes_modify_port;3885nesibdev->ibdev.query_pkey = nes_query_pkey;3886nesibdev->ibdev.query_gid = nes_query_gid;3887nesibdev->ibdev.alloc_ucontext = nes_alloc_ucontext;3888nesibdev->ibdev.dealloc_ucontext = nes_dealloc_ucontext;3889nesibdev->ibdev.mmap = nes_mmap;3890nesibdev->ibdev.alloc_pd = nes_alloc_pd;3891nesibdev->ibdev.dealloc_pd = nes_dealloc_pd;3892nesibdev->ibdev.create_ah = nes_create_ah;3893nesibdev->ibdev.destroy_ah = nes_destroy_ah;3894nesibdev->ibdev.create_qp = nes_create_qp;3895nesibdev->ibdev.modify_qp = nes_modify_qp;3896nesibdev->ibdev.query_qp = nes_query_qp;3897nesibdev->ibdev.destroy_qp = nes_destroy_qp;3898nesibdev->ibdev.create_cq = nes_create_cq;3899nesibdev->ibdev.destroy_cq = nes_destroy_cq;3900nesibdev->ibdev.poll_cq = nes_poll_cq;3901nesibdev->ibdev.get_dma_mr = nes_get_dma_mr;3902nesibdev->ibdev.reg_phys_mr = nes_reg_phys_mr;3903nesibdev->ibdev.reg_user_mr = nes_reg_user_mr;3904nesibdev->ibdev.dereg_mr = nes_dereg_mr;3905nesibdev->ibdev.alloc_mw = nes_alloc_mw;3906nesibdev->ibdev.dealloc_mw = nes_dealloc_mw;3907nesibdev->ibdev.bind_mw = nes_bind_mw;39083909nesibdev->ibdev.alloc_fast_reg_mr = nes_alloc_fast_reg_mr;3910nesibdev->ibdev.alloc_fast_reg_page_list = nes_alloc_fast_reg_page_list;3911nesibdev->ibdev.free_fast_reg_page_list = nes_free_fast_reg_page_list;39123913nesibdev->ibdev.attach_mcast = nes_multicast_attach;3914nesibdev->ibdev.detach_mcast = nes_multicast_detach;3915nesibdev->ibdev.process_mad = nes_process_mad;39163917nesibdev->ibdev.req_notify_cq = nes_req_notify_cq;3918nesibdev->ibdev.post_send = nes_post_send;3919nesibdev->ibdev.post_recv = nes_post_recv;39203921nesibdev->ibdev.iwcm = kzalloc(sizeof(*nesibdev->ibdev.iwcm), GFP_KERNEL);3922if (nesibdev->ibdev.iwcm == NULL) {3923ib_dealloc_device(&nesibdev->ibdev);3924return NULL;3925}3926nesibdev->ibdev.iwcm->add_ref = nes_add_ref;3927nesibdev->ibdev.iwcm->rem_ref = nes_rem_ref;3928nesibdev->ibdev.iwcm->get_qp = nes_get_qp;3929nesibdev->ibdev.iwcm->connect = nes_connect;3930nesibdev->ibdev.iwcm->accept = nes_accept;3931nesibdev->ibdev.iwcm->reject = nes_reject;3932nesibdev->ibdev.iwcm->create_listen = nes_create_listen;3933nesibdev->ibdev.iwcm->destroy_listen = nes_destroy_listen;39343935return nesibdev;3936}393739383939/**3940* nes_handle_delayed_event3941*/3942static void nes_handle_delayed_event(unsigned long data)3943{3944struct nes_vnic *nesvnic = (void *) data;39453946if (nesvnic->delayed_event != nesvnic->last_dispatched_event) {3947struct ib_event event;39483949event.device = &nesvnic->nesibdev->ibdev;3950if (!event.device)3951goto stop_timer;3952event.event = nesvnic->delayed_event;3953event.element.port_num = nesvnic->logical_port + 1;3954ib_dispatch_event(&event);3955}39563957stop_timer:3958nesvnic->event_timer.function = NULL;3959}396039613962void nes_port_ibevent(struct nes_vnic *nesvnic)3963{3964struct nes_ib_device *nesibdev = nesvnic->nesibdev;3965struct nes_device *nesdev = nesvnic->nesdev;3966struct ib_event event;3967event.device = &nesibdev->ibdev;3968event.element.port_num = nesvnic->logical_port + 1;3969event.event = nesdev->iw_status ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;39703971if (!nesvnic->event_timer.function) {3972ib_dispatch_event(&event);3973nesvnic->last_dispatched_event = event.event;3974nesvnic->event_timer.function = nes_handle_delayed_event;3975nesvnic->event_timer.data = (unsigned long) nesvnic;3976nesvnic->event_timer.expires = jiffies + NES_EVENT_DELAY;3977add_timer(&nesvnic->event_timer);3978} else {3979mod_timer(&nesvnic->event_timer, jiffies + NES_EVENT_DELAY);3980}3981nesvnic->delayed_event = event.event;3982}398339843985/**3986* nes_destroy_ofa_device3987*/3988void nes_destroy_ofa_device(struct nes_ib_device *nesibdev)3989{3990if (nesibdev == NULL)3991return;39923993nes_unregister_ofa_device(nesibdev);39943995kfree(nesibdev->ibdev.iwcm);3996ib_dealloc_device(&nesibdev->ibdev);3997}399839994000/**4001* nes_register_ofa_device4002*/4003int nes_register_ofa_device(struct nes_ib_device *nesibdev)4004{4005struct nes_vnic *nesvnic = nesibdev->nesvnic;4006struct nes_device *nesdev = nesvnic->nesdev;4007struct nes_adapter *nesadapter = nesdev->nesadapter;4008int i, ret;40094010ret = ib_register_device(&nesvnic->nesibdev->ibdev, NULL);4011if (ret) {4012return ret;4013}40144015/* Get the resources allocated to this device */4016nesibdev->max_cq = (nesadapter->max_cq-NES_FIRST_QPN) / nesadapter->port_count;4017nesibdev->max_mr = nesadapter->max_mr / nesadapter->port_count;4018nesibdev->max_qp = (nesadapter->max_qp-NES_FIRST_QPN) / nesadapter->port_count;4019nesibdev->max_pd = nesadapter->max_pd / nesadapter->port_count;40204021for (i = 0; i < ARRAY_SIZE(nes_dev_attributes); ++i) {4022ret = device_create_file(&nesibdev->ibdev.dev, nes_dev_attributes[i]);4023if (ret) {4024while (i > 0) {4025i--;4026device_remove_file(&nesibdev->ibdev.dev,4027nes_dev_attributes[i]);4028}4029ib_unregister_device(&nesibdev->ibdev);4030return ret;4031}4032}40334034nesvnic->of_device_registered = 1;40354036return 0;4037}403840394040/**4041* nes_unregister_ofa_device4042*/4043static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev)4044{4045struct nes_vnic *nesvnic = nesibdev->nesvnic;4046int i;40474048for (i = 0; i < ARRAY_SIZE(nes_dev_attributes); ++i) {4049device_remove_file(&nesibdev->ibdev.dev, nes_dev_attributes[i]);4050}40514052if (nesvnic->of_device_registered) {4053ib_unregister_device(&nesibdev->ibdev);4054}40554056nesvnic->of_device_registered = 0;4057}405840594060