Path: blob/master/drivers/infiniband/hw/cxgb3/cxio_hal.c
15112 views
/*1* Copyright (c) 2006 Chelsio, Inc. 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#include <asm/delay.h>3233#include <linux/mutex.h>34#include <linux/netdevice.h>35#include <linux/sched.h>36#include <linux/spinlock.h>37#include <linux/pci.h>38#include <linux/dma-mapping.h>39#include <linux/slab.h>40#include <net/net_namespace.h>4142#include "cxio_resource.h"43#include "cxio_hal.h"44#include "cxgb3_offload.h"45#include "sge_defs.h"4647static LIST_HEAD(rdev_list);48static cxio_hal_ev_callback_func_t cxio_ev_cb = NULL;4950static struct cxio_rdev *cxio_hal_find_rdev_by_name(char *dev_name)51{52struct cxio_rdev *rdev;5354list_for_each_entry(rdev, &rdev_list, entry)55if (!strcmp(rdev->dev_name, dev_name))56return rdev;57return NULL;58}5960static struct cxio_rdev *cxio_hal_find_rdev_by_t3cdev(struct t3cdev *tdev)61{62struct cxio_rdev *rdev;6364list_for_each_entry(rdev, &rdev_list, entry)65if (rdev->t3cdev_p == tdev)66return rdev;67return NULL;68}6970int cxio_hal_cq_op(struct cxio_rdev *rdev_p, struct t3_cq *cq,71enum t3_cq_opcode op, u32 credit)72{73int ret;74struct t3_cqe *cqe;75u32 rptr;7677struct rdma_cq_op setup;78setup.id = cq->cqid;79setup.credits = (op == CQ_CREDIT_UPDATE) ? credit : 0;80setup.op = op;81ret = rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_CQ_OP, &setup);8283if ((ret < 0) || (op == CQ_CREDIT_UPDATE))84return ret;8586/*87* If the rearm returned an index other than our current index,88* then there might be CQE's in flight (being DMA'd). We must wait89* here for them to complete or the consumer can miss a notification.90*/91if (Q_PTR2IDX((cq->rptr), cq->size_log2) != ret) {92int i=0;9394rptr = cq->rptr;9596/*97* Keep the generation correct by bumping rptr until it98* matches the index returned by the rearm - 1.99*/100while (Q_PTR2IDX((rptr+1), cq->size_log2) != ret)101rptr++;102103/*104* Now rptr is the index for the (last) cqe that was105* in-flight at the time the HW rearmed the CQ. We106* spin until that CQE is valid.107*/108cqe = cq->queue + Q_PTR2IDX(rptr, cq->size_log2);109while (!CQ_VLD_ENTRY(rptr, cq->size_log2, cqe)) {110udelay(1);111if (i++ > 1000000) {112printk(KERN_ERR "%s: stalled rnic\n",113rdev_p->dev_name);114return -EIO;115}116}117118return 1;119}120121return 0;122}123124static int cxio_hal_clear_cq_ctx(struct cxio_rdev *rdev_p, u32 cqid)125{126struct rdma_cq_setup setup;127setup.id = cqid;128setup.base_addr = 0; /* NULL address */129setup.size = 0; /* disaable the CQ */130setup.credits = 0;131setup.credit_thres = 0;132setup.ovfl_mode = 0;133return (rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_CQ_SETUP, &setup));134}135136static int cxio_hal_clear_qp_ctx(struct cxio_rdev *rdev_p, u32 qpid)137{138u64 sge_cmd;139struct t3_modify_qp_wr *wqe;140struct sk_buff *skb = alloc_skb(sizeof(*wqe), GFP_KERNEL);141if (!skb) {142PDBG("%s alloc_skb failed\n", __func__);143return -ENOMEM;144}145wqe = (struct t3_modify_qp_wr *) skb_put(skb, sizeof(*wqe));146memset(wqe, 0, sizeof(*wqe));147build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD,148T3_COMPLETION_FLAG | T3_NOTIFY_FLAG, 0, qpid, 7,149T3_SOPEOP);150wqe->flags = cpu_to_be32(MODQP_WRITE_EC);151sge_cmd = qpid << 8 | 3;152wqe->sge_cmd = cpu_to_be64(sge_cmd);153skb->priority = CPL_PRIORITY_CONTROL;154return iwch_cxgb3_ofld_send(rdev_p->t3cdev_p, skb);155}156157int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq, int kernel)158{159struct rdma_cq_setup setup;160int size = (1UL << (cq->size_log2)) * sizeof(struct t3_cqe);161162size += 1; /* one extra page for storing cq-in-err state */163cq->cqid = cxio_hal_get_cqid(rdev_p->rscp);164if (!cq->cqid)165return -ENOMEM;166if (kernel) {167cq->sw_queue = kzalloc(size, GFP_KERNEL);168if (!cq->sw_queue)169return -ENOMEM;170}171cq->queue = dma_alloc_coherent(&(rdev_p->rnic_info.pdev->dev), size,172&(cq->dma_addr), GFP_KERNEL);173if (!cq->queue) {174kfree(cq->sw_queue);175return -ENOMEM;176}177dma_unmap_addr_set(cq, mapping, cq->dma_addr);178memset(cq->queue, 0, size);179setup.id = cq->cqid;180setup.base_addr = (u64) (cq->dma_addr);181setup.size = 1UL << cq->size_log2;182setup.credits = 65535;183setup.credit_thres = 1;184if (rdev_p->t3cdev_p->type != T3A)185setup.ovfl_mode = 0;186else187setup.ovfl_mode = 1;188return (rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_CQ_SETUP, &setup));189}190191#ifdef notyet192int cxio_resize_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)193{194struct rdma_cq_setup setup;195setup.id = cq->cqid;196setup.base_addr = (u64) (cq->dma_addr);197setup.size = 1UL << cq->size_log2;198setup.credits = setup.size;199setup.credit_thres = setup.size; /* TBD: overflow recovery */200setup.ovfl_mode = 1;201return (rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_CQ_SETUP, &setup));202}203#endif204205static u32 get_qpid(struct cxio_rdev *rdev_p, struct cxio_ucontext *uctx)206{207struct cxio_qpid_list *entry;208u32 qpid;209int i;210211mutex_lock(&uctx->lock);212if (!list_empty(&uctx->qpids)) {213entry = list_entry(uctx->qpids.next, struct cxio_qpid_list,214entry);215list_del(&entry->entry);216qpid = entry->qpid;217kfree(entry);218} else {219qpid = cxio_hal_get_qpid(rdev_p->rscp);220if (!qpid)221goto out;222for (i = qpid+1; i & rdev_p->qpmask; i++) {223entry = kmalloc(sizeof *entry, GFP_KERNEL);224if (!entry)225break;226entry->qpid = i;227list_add_tail(&entry->entry, &uctx->qpids);228}229}230out:231mutex_unlock(&uctx->lock);232PDBG("%s qpid 0x%x\n", __func__, qpid);233return qpid;234}235236static void put_qpid(struct cxio_rdev *rdev_p, u32 qpid,237struct cxio_ucontext *uctx)238{239struct cxio_qpid_list *entry;240241entry = kmalloc(sizeof *entry, GFP_KERNEL);242if (!entry)243return;244PDBG("%s qpid 0x%x\n", __func__, qpid);245entry->qpid = qpid;246mutex_lock(&uctx->lock);247list_add_tail(&entry->entry, &uctx->qpids);248mutex_unlock(&uctx->lock);249}250251void cxio_release_ucontext(struct cxio_rdev *rdev_p, struct cxio_ucontext *uctx)252{253struct list_head *pos, *nxt;254struct cxio_qpid_list *entry;255256mutex_lock(&uctx->lock);257list_for_each_safe(pos, nxt, &uctx->qpids) {258entry = list_entry(pos, struct cxio_qpid_list, entry);259list_del_init(&entry->entry);260if (!(entry->qpid & rdev_p->qpmask))261cxio_hal_put_qpid(rdev_p->rscp, entry->qpid);262kfree(entry);263}264mutex_unlock(&uctx->lock);265}266267void cxio_init_ucontext(struct cxio_rdev *rdev_p, struct cxio_ucontext *uctx)268{269INIT_LIST_HEAD(&uctx->qpids);270mutex_init(&uctx->lock);271}272273int cxio_create_qp(struct cxio_rdev *rdev_p, u32 kernel_domain,274struct t3_wq *wq, struct cxio_ucontext *uctx)275{276int depth = 1UL << wq->size_log2;277int rqsize = 1UL << wq->rq_size_log2;278279wq->qpid = get_qpid(rdev_p, uctx);280if (!wq->qpid)281return -ENOMEM;282283wq->rq = kzalloc(depth * sizeof(struct t3_swrq), GFP_KERNEL);284if (!wq->rq)285goto err1;286287wq->rq_addr = cxio_hal_rqtpool_alloc(rdev_p, rqsize);288if (!wq->rq_addr)289goto err2;290291wq->sq = kzalloc(depth * sizeof(struct t3_swsq), GFP_KERNEL);292if (!wq->sq)293goto err3;294295wq->queue = dma_alloc_coherent(&(rdev_p->rnic_info.pdev->dev),296depth * sizeof(union t3_wr),297&(wq->dma_addr), GFP_KERNEL);298if (!wq->queue)299goto err4;300301memset(wq->queue, 0, depth * sizeof(union t3_wr));302dma_unmap_addr_set(wq, mapping, wq->dma_addr);303wq->doorbell = (void __iomem *)rdev_p->rnic_info.kdb_addr;304if (!kernel_domain)305wq->udb = (u64)rdev_p->rnic_info.udbell_physbase +306(wq->qpid << rdev_p->qpshift);307wq->rdev = rdev_p;308PDBG("%s qpid 0x%x doorbell 0x%p udb 0x%llx\n", __func__,309wq->qpid, wq->doorbell, (unsigned long long) wq->udb);310return 0;311err4:312kfree(wq->sq);313err3:314cxio_hal_rqtpool_free(rdev_p, wq->rq_addr, rqsize);315err2:316kfree(wq->rq);317err1:318put_qpid(rdev_p, wq->qpid, uctx);319return -ENOMEM;320}321322int cxio_destroy_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)323{324int err;325err = cxio_hal_clear_cq_ctx(rdev_p, cq->cqid);326kfree(cq->sw_queue);327dma_free_coherent(&(rdev_p->rnic_info.pdev->dev),328(1UL << (cq->size_log2))329* sizeof(struct t3_cqe), cq->queue,330dma_unmap_addr(cq, mapping));331cxio_hal_put_cqid(rdev_p->rscp, cq->cqid);332return err;333}334335int cxio_destroy_qp(struct cxio_rdev *rdev_p, struct t3_wq *wq,336struct cxio_ucontext *uctx)337{338dma_free_coherent(&(rdev_p->rnic_info.pdev->dev),339(1UL << (wq->size_log2))340* sizeof(union t3_wr), wq->queue,341dma_unmap_addr(wq, mapping));342kfree(wq->sq);343cxio_hal_rqtpool_free(rdev_p, wq->rq_addr, (1UL << wq->rq_size_log2));344kfree(wq->rq);345put_qpid(rdev_p, wq->qpid, uctx);346return 0;347}348349static void insert_recv_cqe(struct t3_wq *wq, struct t3_cq *cq)350{351struct t3_cqe cqe;352353PDBG("%s wq %p cq %p sw_rptr 0x%x sw_wptr 0x%x\n", __func__,354wq, cq, cq->sw_rptr, cq->sw_wptr);355memset(&cqe, 0, sizeof(cqe));356cqe.header = cpu_to_be32(V_CQE_STATUS(TPT_ERR_SWFLUSH) |357V_CQE_OPCODE(T3_SEND) |358V_CQE_TYPE(0) |359V_CQE_SWCQE(1) |360V_CQE_QPID(wq->qpid) |361V_CQE_GENBIT(Q_GENBIT(cq->sw_wptr,362cq->size_log2)));363*(cq->sw_queue + Q_PTR2IDX(cq->sw_wptr, cq->size_log2)) = cqe;364cq->sw_wptr++;365}366367int cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count)368{369u32 ptr;370int flushed = 0;371372PDBG("%s wq %p cq %p\n", __func__, wq, cq);373374/* flush RQ */375PDBG("%s rq_rptr %u rq_wptr %u skip count %u\n", __func__,376wq->rq_rptr, wq->rq_wptr, count);377ptr = wq->rq_rptr + count;378while (ptr++ != wq->rq_wptr) {379insert_recv_cqe(wq, cq);380flushed++;381}382return flushed;383}384385static void insert_sq_cqe(struct t3_wq *wq, struct t3_cq *cq,386struct t3_swsq *sqp)387{388struct t3_cqe cqe;389390PDBG("%s wq %p cq %p sw_rptr 0x%x sw_wptr 0x%x\n", __func__,391wq, cq, cq->sw_rptr, cq->sw_wptr);392memset(&cqe, 0, sizeof(cqe));393cqe.header = cpu_to_be32(V_CQE_STATUS(TPT_ERR_SWFLUSH) |394V_CQE_OPCODE(sqp->opcode) |395V_CQE_TYPE(1) |396V_CQE_SWCQE(1) |397V_CQE_QPID(wq->qpid) |398V_CQE_GENBIT(Q_GENBIT(cq->sw_wptr,399cq->size_log2)));400cqe.u.scqe.wrid_hi = sqp->sq_wptr;401402*(cq->sw_queue + Q_PTR2IDX(cq->sw_wptr, cq->size_log2)) = cqe;403cq->sw_wptr++;404}405406int cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count)407{408__u32 ptr;409int flushed = 0;410struct t3_swsq *sqp = wq->sq + Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2);411412ptr = wq->sq_rptr + count;413sqp = wq->sq + Q_PTR2IDX(ptr, wq->sq_size_log2);414while (ptr != wq->sq_wptr) {415sqp->signaled = 0;416insert_sq_cqe(wq, cq, sqp);417ptr++;418sqp = wq->sq + Q_PTR2IDX(ptr, wq->sq_size_log2);419flushed++;420}421return flushed;422}423424/*425* Move all CQEs from the HWCQ into the SWCQ.426*/427void cxio_flush_hw_cq(struct t3_cq *cq)428{429struct t3_cqe *cqe, *swcqe;430431PDBG("%s cq %p cqid 0x%x\n", __func__, cq, cq->cqid);432cqe = cxio_next_hw_cqe(cq);433while (cqe) {434PDBG("%s flushing hwcq rptr 0x%x to swcq wptr 0x%x\n",435__func__, cq->rptr, cq->sw_wptr);436swcqe = cq->sw_queue + Q_PTR2IDX(cq->sw_wptr, cq->size_log2);437*swcqe = *cqe;438swcqe->header |= cpu_to_be32(V_CQE_SWCQE(1));439cq->sw_wptr++;440cq->rptr++;441cqe = cxio_next_hw_cqe(cq);442}443}444445static int cqe_completes_wr(struct t3_cqe *cqe, struct t3_wq *wq)446{447if (CQE_OPCODE(*cqe) == T3_TERMINATE)448return 0;449450if ((CQE_OPCODE(*cqe) == T3_RDMA_WRITE) && RQ_TYPE(*cqe))451return 0;452453if ((CQE_OPCODE(*cqe) == T3_READ_RESP) && SQ_TYPE(*cqe))454return 0;455456if (CQE_SEND_OPCODE(*cqe) && RQ_TYPE(*cqe) &&457Q_EMPTY(wq->rq_rptr, wq->rq_wptr))458return 0;459460return 1;461}462463void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count)464{465struct t3_cqe *cqe;466u32 ptr;467468*count = 0;469ptr = cq->sw_rptr;470while (!Q_EMPTY(ptr, cq->sw_wptr)) {471cqe = cq->sw_queue + (Q_PTR2IDX(ptr, cq->size_log2));472if ((SQ_TYPE(*cqe) ||473((CQE_OPCODE(*cqe) == T3_READ_RESP) && wq->oldest_read)) &&474(CQE_QPID(*cqe) == wq->qpid))475(*count)++;476ptr++;477}478PDBG("%s cq %p count %d\n", __func__, cq, *count);479}480481void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count)482{483struct t3_cqe *cqe;484u32 ptr;485486*count = 0;487PDBG("%s count zero %d\n", __func__, *count);488ptr = cq->sw_rptr;489while (!Q_EMPTY(ptr, cq->sw_wptr)) {490cqe = cq->sw_queue + (Q_PTR2IDX(ptr, cq->size_log2));491if (RQ_TYPE(*cqe) && (CQE_OPCODE(*cqe) != T3_READ_RESP) &&492(CQE_QPID(*cqe) == wq->qpid) && cqe_completes_wr(cqe, wq))493(*count)++;494ptr++;495}496PDBG("%s cq %p count %d\n", __func__, cq, *count);497}498499static int cxio_hal_init_ctrl_cq(struct cxio_rdev *rdev_p)500{501struct rdma_cq_setup setup;502setup.id = 0;503setup.base_addr = 0; /* NULL address */504setup.size = 1; /* enable the CQ */505setup.credits = 0;506507/* force SGE to redirect to RspQ and interrupt */508setup.credit_thres = 0;509setup.ovfl_mode = 1;510return (rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_CQ_SETUP, &setup));511}512513static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)514{515int err;516u64 sge_cmd, ctx0, ctx1;517u64 base_addr;518struct t3_modify_qp_wr *wqe;519struct sk_buff *skb;520521skb = alloc_skb(sizeof(*wqe), GFP_KERNEL);522if (!skb) {523PDBG("%s alloc_skb failed\n", __func__);524return -ENOMEM;525}526err = cxio_hal_init_ctrl_cq(rdev_p);527if (err) {528PDBG("%s err %d initializing ctrl_cq\n", __func__, err);529goto err;530}531rdev_p->ctrl_qp.workq = dma_alloc_coherent(532&(rdev_p->rnic_info.pdev->dev),533(1 << T3_CTRL_QP_SIZE_LOG2) *534sizeof(union t3_wr),535&(rdev_p->ctrl_qp.dma_addr),536GFP_KERNEL);537if (!rdev_p->ctrl_qp.workq) {538PDBG("%s dma_alloc_coherent failed\n", __func__);539err = -ENOMEM;540goto err;541}542dma_unmap_addr_set(&rdev_p->ctrl_qp, mapping,543rdev_p->ctrl_qp.dma_addr);544rdev_p->ctrl_qp.doorbell = (void __iomem *)rdev_p->rnic_info.kdb_addr;545memset(rdev_p->ctrl_qp.workq, 0,546(1 << T3_CTRL_QP_SIZE_LOG2) * sizeof(union t3_wr));547548mutex_init(&rdev_p->ctrl_qp.lock);549init_waitqueue_head(&rdev_p->ctrl_qp.waitq);550551/* update HW Ctrl QP context */552base_addr = rdev_p->ctrl_qp.dma_addr;553base_addr >>= 12;554ctx0 = (V_EC_SIZE((1 << T3_CTRL_QP_SIZE_LOG2)) |555V_EC_BASE_LO((u32) base_addr & 0xffff));556ctx0 <<= 32;557ctx0 |= V_EC_CREDITS(FW_WR_NUM);558base_addr >>= 16;559ctx1 = (u32) base_addr;560base_addr >>= 32;561ctx1 |= ((u64) (V_EC_BASE_HI((u32) base_addr & 0xf) | V_EC_RESPQ(0) |562V_EC_TYPE(0) | V_EC_GEN(1) |563V_EC_UP_TOKEN(T3_CTL_QP_TID) | F_EC_VALID)) << 32;564wqe = (struct t3_modify_qp_wr *) skb_put(skb, sizeof(*wqe));565memset(wqe, 0, sizeof(*wqe));566build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 0, 0,567T3_CTL_QP_TID, 7, T3_SOPEOP);568wqe->flags = cpu_to_be32(MODQP_WRITE_EC);569sge_cmd = (3ULL << 56) | FW_RI_SGEEC_START << 8 | 3;570wqe->sge_cmd = cpu_to_be64(sge_cmd);571wqe->ctx1 = cpu_to_be64(ctx1);572wqe->ctx0 = cpu_to_be64(ctx0);573PDBG("CtrlQP dma_addr 0x%llx workq %p size %d\n",574(unsigned long long) rdev_p->ctrl_qp.dma_addr,575rdev_p->ctrl_qp.workq, 1 << T3_CTRL_QP_SIZE_LOG2);576skb->priority = CPL_PRIORITY_CONTROL;577return iwch_cxgb3_ofld_send(rdev_p->t3cdev_p, skb);578err:579kfree_skb(skb);580return err;581}582583static int cxio_hal_destroy_ctrl_qp(struct cxio_rdev *rdev_p)584{585dma_free_coherent(&(rdev_p->rnic_info.pdev->dev),586(1UL << T3_CTRL_QP_SIZE_LOG2)587* sizeof(union t3_wr), rdev_p->ctrl_qp.workq,588dma_unmap_addr(&rdev_p->ctrl_qp, mapping));589return cxio_hal_clear_qp_ctx(rdev_p, T3_CTRL_QP_ID);590}591592/* write len bytes of data into addr (32B aligned address)593* If data is NULL, clear len byte of memory to zero.594* caller acquires the ctrl_qp lock before the call595*/596static int cxio_hal_ctrl_qp_write_mem(struct cxio_rdev *rdev_p, u32 addr,597u32 len, void *data)598{599u32 i, nr_wqe, copy_len;600u8 *copy_data;601u8 wr_len, utx_len; /* length in 8 byte flit */602enum t3_wr_flags flag;603__be64 *wqe;604u64 utx_cmd;605addr &= 0x7FFFFFF;606nr_wqe = len % 96 ? len / 96 + 1 : len / 96; /* 96B max per WQE */607PDBG("%s wptr 0x%x rptr 0x%x len %d, nr_wqe %d data %p addr 0x%0x\n",608__func__, rdev_p->ctrl_qp.wptr, rdev_p->ctrl_qp.rptr, len,609nr_wqe, data, addr);610utx_len = 3; /* in 32B unit */611for (i = 0; i < nr_wqe; i++) {612if (Q_FULL(rdev_p->ctrl_qp.rptr, rdev_p->ctrl_qp.wptr,613T3_CTRL_QP_SIZE_LOG2)) {614PDBG("%s ctrl_qp full wtpr 0x%0x rptr 0x%0x, "615"wait for more space i %d\n", __func__,616rdev_p->ctrl_qp.wptr, rdev_p->ctrl_qp.rptr, i);617if (wait_event_interruptible(rdev_p->ctrl_qp.waitq,618!Q_FULL(rdev_p->ctrl_qp.rptr,619rdev_p->ctrl_qp.wptr,620T3_CTRL_QP_SIZE_LOG2))) {621PDBG("%s ctrl_qp workq interrupted\n",622__func__);623return -ERESTARTSYS;624}625PDBG("%s ctrl_qp wakeup, continue posting work request "626"i %d\n", __func__, i);627}628wqe = (__be64 *)(rdev_p->ctrl_qp.workq + (rdev_p->ctrl_qp.wptr %629(1 << T3_CTRL_QP_SIZE_LOG2)));630flag = 0;631if (i == (nr_wqe - 1)) {632/* last WQE */633flag = T3_COMPLETION_FLAG;634if (len % 32)635utx_len = len / 32 + 1;636else637utx_len = len / 32;638}639640/*641* Force a CQE to return the credit to the workq in case642* we posted more than half the max QP size of WRs643*/644if ((i != 0) &&645(i % (((1 << T3_CTRL_QP_SIZE_LOG2)) >> 1) == 0)) {646flag = T3_COMPLETION_FLAG;647PDBG("%s force completion at i %d\n", __func__, i);648}649650/* build the utx mem command */651wqe += (sizeof(struct t3_bypass_wr) >> 3);652utx_cmd = (T3_UTX_MEM_WRITE << 28) | (addr + i * 3);653utx_cmd <<= 32;654utx_cmd |= (utx_len << 28) | ((utx_len << 2) + 1);655*wqe = cpu_to_be64(utx_cmd);656wqe++;657copy_data = (u8 *) data + i * 96;658copy_len = len > 96 ? 96 : len;659660/* clear memory content if data is NULL */661if (data)662memcpy(wqe, copy_data, copy_len);663else664memset(wqe, 0, copy_len);665if (copy_len % 32)666memset(((u8 *) wqe) + copy_len, 0,66732 - (copy_len % 32));668wr_len = ((sizeof(struct t3_bypass_wr)) >> 3) + 1 +669(utx_len << 2);670wqe = (__be64 *)(rdev_p->ctrl_qp.workq + (rdev_p->ctrl_qp.wptr %671(1 << T3_CTRL_QP_SIZE_LOG2)));672673/* wptr in the WRID[31:0] */674((union t3_wrid *)(wqe+1))->id0.low = rdev_p->ctrl_qp.wptr;675676/*677* This must be the last write with a memory barrier678* for the genbit679*/680build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_BP, flag,681Q_GENBIT(rdev_p->ctrl_qp.wptr,682T3_CTRL_QP_SIZE_LOG2), T3_CTRL_QP_ID,683wr_len, T3_SOPEOP);684if (flag == T3_COMPLETION_FLAG)685ring_doorbell(rdev_p->ctrl_qp.doorbell, T3_CTRL_QP_ID);686len -= 96;687rdev_p->ctrl_qp.wptr++;688}689return 0;690}691692/* IN: stag key, pdid, perm, zbva, to, len, page_size, pbl_size and pbl_addr693* OUT: stag index694* TBD: shared memory region support695*/696static int __cxio_tpt_op(struct cxio_rdev *rdev_p, u32 reset_tpt_entry,697u32 *stag, u8 stag_state, u32 pdid,698enum tpt_mem_type type, enum tpt_mem_perm perm,699u32 zbva, u64 to, u32 len, u8 page_size,700u32 pbl_size, u32 pbl_addr)701{702int err;703struct tpt_entry tpt;704u32 stag_idx;705u32 wptr;706707if (cxio_fatal_error(rdev_p))708return -EIO;709710stag_state = stag_state > 0;711stag_idx = (*stag) >> 8;712713if ((!reset_tpt_entry) && !(*stag != T3_STAG_UNSET)) {714stag_idx = cxio_hal_get_stag(rdev_p->rscp);715if (!stag_idx)716return -ENOMEM;717*stag = (stag_idx << 8) | ((*stag) & 0xFF);718}719PDBG("%s stag_state 0x%0x type 0x%0x pdid 0x%0x, stag_idx 0x%x\n",720__func__, stag_state, type, pdid, stag_idx);721722mutex_lock(&rdev_p->ctrl_qp.lock);723724/* write TPT entry */725if (reset_tpt_entry)726memset(&tpt, 0, sizeof(tpt));727else {728tpt.valid_stag_pdid = cpu_to_be32(F_TPT_VALID |729V_TPT_STAG_KEY((*stag) & M_TPT_STAG_KEY) |730V_TPT_STAG_STATE(stag_state) |731V_TPT_STAG_TYPE(type) | V_TPT_PDID(pdid));732BUG_ON(page_size >= 28);733tpt.flags_pagesize_qpid = cpu_to_be32(V_TPT_PERM(perm) |734((perm & TPT_MW_BIND) ? F_TPT_MW_BIND_ENABLE : 0) |735V_TPT_ADDR_TYPE((zbva ? TPT_ZBTO : TPT_VATO)) |736V_TPT_PAGE_SIZE(page_size));737tpt.rsvd_pbl_addr = reset_tpt_entry ? 0 :738cpu_to_be32(V_TPT_PBL_ADDR(PBL_OFF(rdev_p, pbl_addr)>>3));739tpt.len = cpu_to_be32(len);740tpt.va_hi = cpu_to_be32((u32) (to >> 32));741tpt.va_low_or_fbo = cpu_to_be32((u32) (to & 0xFFFFFFFFULL));742tpt.rsvd_bind_cnt_or_pstag = 0;743tpt.rsvd_pbl_size = reset_tpt_entry ? 0 :744cpu_to_be32(V_TPT_PBL_SIZE(pbl_size >> 2));745}746err = cxio_hal_ctrl_qp_write_mem(rdev_p,747stag_idx +748(rdev_p->rnic_info.tpt_base >> 5),749sizeof(tpt), &tpt);750751/* release the stag index to free pool */752if (reset_tpt_entry)753cxio_hal_put_stag(rdev_p->rscp, stag_idx);754755wptr = rdev_p->ctrl_qp.wptr;756mutex_unlock(&rdev_p->ctrl_qp.lock);757if (!err)758if (wait_event_interruptible(rdev_p->ctrl_qp.waitq,759SEQ32_GE(rdev_p->ctrl_qp.rptr,760wptr)))761return -ERESTARTSYS;762return err;763}764765int cxio_write_pbl(struct cxio_rdev *rdev_p, __be64 *pbl,766u32 pbl_addr, u32 pbl_size)767{768u32 wptr;769int err;770771PDBG("%s *pdb_addr 0x%x, pbl_base 0x%x, pbl_size %d\n",772__func__, pbl_addr, rdev_p->rnic_info.pbl_base,773pbl_size);774775mutex_lock(&rdev_p->ctrl_qp.lock);776err = cxio_hal_ctrl_qp_write_mem(rdev_p, pbl_addr >> 5, pbl_size << 3,777pbl);778wptr = rdev_p->ctrl_qp.wptr;779mutex_unlock(&rdev_p->ctrl_qp.lock);780if (err)781return err;782783if (wait_event_interruptible(rdev_p->ctrl_qp.waitq,784SEQ32_GE(rdev_p->ctrl_qp.rptr,785wptr)))786return -ERESTARTSYS;787788return 0;789}790791int cxio_register_phys_mem(struct cxio_rdev *rdev_p, u32 *stag, u32 pdid,792enum tpt_mem_perm perm, u32 zbva, u64 to, u32 len,793u8 page_size, u32 pbl_size, u32 pbl_addr)794{795*stag = T3_STAG_UNSET;796return __cxio_tpt_op(rdev_p, 0, stag, 1, pdid, TPT_NON_SHARED_MR, perm,797zbva, to, len, page_size, pbl_size, pbl_addr);798}799800int cxio_reregister_phys_mem(struct cxio_rdev *rdev_p, u32 *stag, u32 pdid,801enum tpt_mem_perm perm, u32 zbva, u64 to, u32 len,802u8 page_size, u32 pbl_size, u32 pbl_addr)803{804return __cxio_tpt_op(rdev_p, 0, stag, 1, pdid, TPT_NON_SHARED_MR, perm,805zbva, to, len, page_size, pbl_size, pbl_addr);806}807808int cxio_dereg_mem(struct cxio_rdev *rdev_p, u32 stag, u32 pbl_size,809u32 pbl_addr)810{811return __cxio_tpt_op(rdev_p, 1, &stag, 0, 0, 0, 0, 0, 0ULL, 0, 0,812pbl_size, pbl_addr);813}814815int cxio_allocate_window(struct cxio_rdev *rdev_p, u32 * stag, u32 pdid)816{817*stag = T3_STAG_UNSET;818return __cxio_tpt_op(rdev_p, 0, stag, 0, pdid, TPT_MW, 0, 0, 0ULL, 0, 0,8190, 0);820}821822int cxio_deallocate_window(struct cxio_rdev *rdev_p, u32 stag)823{824return __cxio_tpt_op(rdev_p, 1, &stag, 0, 0, 0, 0, 0, 0ULL, 0, 0,8250, 0);826}827828int cxio_allocate_stag(struct cxio_rdev *rdev_p, u32 *stag, u32 pdid, u32 pbl_size, u32 pbl_addr)829{830*stag = T3_STAG_UNSET;831return __cxio_tpt_op(rdev_p, 0, stag, 0, pdid, TPT_NON_SHARED_MR,8320, 0, 0ULL, 0, 0, pbl_size, pbl_addr);833}834835int cxio_rdma_init(struct cxio_rdev *rdev_p, struct t3_rdma_init_attr *attr)836{837struct t3_rdma_init_wr *wqe;838struct sk_buff *skb = alloc_skb(sizeof(*wqe), GFP_ATOMIC);839if (!skb)840return -ENOMEM;841PDBG("%s rdev_p %p\n", __func__, rdev_p);842wqe = (struct t3_rdma_init_wr *) __skb_put(skb, sizeof(*wqe));843wqe->wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_INIT));844wqe->wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(attr->tid) |845V_FW_RIWR_LEN(sizeof(*wqe) >> 3));846wqe->wrid.id1 = 0;847wqe->qpid = cpu_to_be32(attr->qpid);848wqe->pdid = cpu_to_be32(attr->pdid);849wqe->scqid = cpu_to_be32(attr->scqid);850wqe->rcqid = cpu_to_be32(attr->rcqid);851wqe->rq_addr = cpu_to_be32(attr->rq_addr - rdev_p->rnic_info.rqt_base);852wqe->rq_size = cpu_to_be32(attr->rq_size);853wqe->mpaattrs = attr->mpaattrs;854wqe->qpcaps = attr->qpcaps;855wqe->ulpdu_size = cpu_to_be16(attr->tcp_emss);856wqe->rqe_count = cpu_to_be16(attr->rqe_count);857wqe->flags_rtr_type = cpu_to_be16(attr->flags |858V_RTR_TYPE(attr->rtr_type) |859V_CHAN(attr->chan));860wqe->ord = cpu_to_be32(attr->ord);861wqe->ird = cpu_to_be32(attr->ird);862wqe->qp_dma_addr = cpu_to_be64(attr->qp_dma_addr);863wqe->qp_dma_size = cpu_to_be32(attr->qp_dma_size);864wqe->irs = cpu_to_be32(attr->irs);865skb->priority = 0; /* 0=>ToeQ; 1=>CtrlQ */866return iwch_cxgb3_ofld_send(rdev_p->t3cdev_p, skb);867}868869void cxio_register_ev_cb(cxio_hal_ev_callback_func_t ev_cb)870{871cxio_ev_cb = ev_cb;872}873874void cxio_unregister_ev_cb(cxio_hal_ev_callback_func_t ev_cb)875{876cxio_ev_cb = NULL;877}878879static int cxio_hal_ev_handler(struct t3cdev *t3cdev_p, struct sk_buff *skb)880{881static int cnt;882struct cxio_rdev *rdev_p = NULL;883struct respQ_msg_t *rsp_msg = (struct respQ_msg_t *) skb->data;884PDBG("%d: %s cq_id 0x%x cq_ptr 0x%x genbit %0x overflow %0x an %0x"885" se %0x notify %0x cqbranch %0x creditth %0x\n",886cnt, __func__, RSPQ_CQID(rsp_msg), RSPQ_CQPTR(rsp_msg),887RSPQ_GENBIT(rsp_msg), RSPQ_OVERFLOW(rsp_msg), RSPQ_AN(rsp_msg),888RSPQ_SE(rsp_msg), RSPQ_NOTIFY(rsp_msg), RSPQ_CQBRANCH(rsp_msg),889RSPQ_CREDIT_THRESH(rsp_msg));890PDBG("CQE: QPID 0x%0x genbit %0x type 0x%0x status 0x%0x opcode %d "891"len 0x%0x wrid_hi_stag 0x%x wrid_low_msn 0x%x\n",892CQE_QPID(rsp_msg->cqe), CQE_GENBIT(rsp_msg->cqe),893CQE_TYPE(rsp_msg->cqe), CQE_STATUS(rsp_msg->cqe),894CQE_OPCODE(rsp_msg->cqe), CQE_LEN(rsp_msg->cqe),895CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));896rdev_p = (struct cxio_rdev *)t3cdev_p->ulp;897if (!rdev_p) {898PDBG("%s called by t3cdev %p with null ulp\n", __func__,899t3cdev_p);900return 0;901}902if (CQE_QPID(rsp_msg->cqe) == T3_CTRL_QP_ID) {903rdev_p->ctrl_qp.rptr = CQE_WRID_LOW(rsp_msg->cqe) + 1;904wake_up_interruptible(&rdev_p->ctrl_qp.waitq);905dev_kfree_skb_irq(skb);906} else if (CQE_QPID(rsp_msg->cqe) == 0xfff8)907dev_kfree_skb_irq(skb);908else if (cxio_ev_cb)909(*cxio_ev_cb) (rdev_p, skb);910else911dev_kfree_skb_irq(skb);912cnt++;913return 0;914}915916/* Caller takes care of locking if needed */917int cxio_rdev_open(struct cxio_rdev *rdev_p)918{919struct net_device *netdev_p = NULL;920int err = 0;921if (strlen(rdev_p->dev_name)) {922if (cxio_hal_find_rdev_by_name(rdev_p->dev_name)) {923return -EBUSY;924}925netdev_p = dev_get_by_name(&init_net, rdev_p->dev_name);926if (!netdev_p) {927return -EINVAL;928}929dev_put(netdev_p);930} else if (rdev_p->t3cdev_p) {931if (cxio_hal_find_rdev_by_t3cdev(rdev_p->t3cdev_p)) {932return -EBUSY;933}934netdev_p = rdev_p->t3cdev_p->lldev;935strncpy(rdev_p->dev_name, rdev_p->t3cdev_p->name,936T3_MAX_DEV_NAME_LEN);937} else {938PDBG("%s t3cdev_p or dev_name must be set\n", __func__);939return -EINVAL;940}941942list_add_tail(&rdev_p->entry, &rdev_list);943944PDBG("%s opening rnic dev %s\n", __func__, rdev_p->dev_name);945memset(&rdev_p->ctrl_qp, 0, sizeof(rdev_p->ctrl_qp));946if (!rdev_p->t3cdev_p)947rdev_p->t3cdev_p = dev2t3cdev(netdev_p);948rdev_p->t3cdev_p->ulp = (void *) rdev_p;949950err = rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, GET_EMBEDDED_INFO,951&(rdev_p->fw_info));952if (err) {953printk(KERN_ERR "%s t3cdev_p(%p)->ctl returned error %d.\n",954__func__, rdev_p->t3cdev_p, err);955goto err1;956}957if (G_FW_VERSION_MAJOR(rdev_p->fw_info.fw_vers) != CXIO_FW_MAJ) {958printk(KERN_ERR MOD "fatal firmware version mismatch: "959"need version %u but adapter has version %u\n",960CXIO_FW_MAJ,961G_FW_VERSION_MAJOR(rdev_p->fw_info.fw_vers));962err = -EINVAL;963goto err1;964}965966err = rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_GET_PARAMS,967&(rdev_p->rnic_info));968if (err) {969printk(KERN_ERR "%s t3cdev_p(%p)->ctl returned error %d.\n",970__func__, rdev_p->t3cdev_p, err);971goto err1;972}973err = rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, GET_PORTS,974&(rdev_p->port_info));975if (err) {976printk(KERN_ERR "%s t3cdev_p(%p)->ctl returned error %d.\n",977__func__, rdev_p->t3cdev_p, err);978goto err1;979}980981/*982* qpshift is the number of bits to shift the qpid left in order983* to get the correct address of the doorbell for that qp.984*/985cxio_init_ucontext(rdev_p, &rdev_p->uctx);986rdev_p->qpshift = PAGE_SHIFT -987ilog2(65536 >>988ilog2(rdev_p->rnic_info.udbell_len >>989PAGE_SHIFT));990rdev_p->qpnr = rdev_p->rnic_info.udbell_len >> PAGE_SHIFT;991rdev_p->qpmask = (65536 >> ilog2(rdev_p->qpnr)) - 1;992PDBG("%s rnic %s info: tpt_base 0x%0x tpt_top 0x%0x num stags %d "993"pbl_base 0x%0x pbl_top 0x%0x rqt_base 0x%0x, rqt_top 0x%0x\n",994__func__, rdev_p->dev_name, rdev_p->rnic_info.tpt_base,995rdev_p->rnic_info.tpt_top, cxio_num_stags(rdev_p),996rdev_p->rnic_info.pbl_base,997rdev_p->rnic_info.pbl_top, rdev_p->rnic_info.rqt_base,998rdev_p->rnic_info.rqt_top);999PDBG("udbell_len 0x%0x udbell_physbase 0x%lx kdb_addr %p qpshift %lu "1000"qpnr %d qpmask 0x%x\n",1001rdev_p->rnic_info.udbell_len,1002rdev_p->rnic_info.udbell_physbase, rdev_p->rnic_info.kdb_addr,1003rdev_p->qpshift, rdev_p->qpnr, rdev_p->qpmask);10041005err = cxio_hal_init_ctrl_qp(rdev_p);1006if (err) {1007printk(KERN_ERR "%s error %d initializing ctrl_qp.\n",1008__func__, err);1009goto err1;1010}1011err = cxio_hal_init_resource(rdev_p, cxio_num_stags(rdev_p), 0,10120, T3_MAX_NUM_QP, T3_MAX_NUM_CQ,1013T3_MAX_NUM_PD);1014if (err) {1015printk(KERN_ERR "%s error %d initializing hal resources.\n",1016__func__, err);1017goto err2;1018}1019err = cxio_hal_pblpool_create(rdev_p);1020if (err) {1021printk(KERN_ERR "%s error %d initializing pbl mem pool.\n",1022__func__, err);1023goto err3;1024}1025err = cxio_hal_rqtpool_create(rdev_p);1026if (err) {1027printk(KERN_ERR "%s error %d initializing rqt mem pool.\n",1028__func__, err);1029goto err4;1030}1031return 0;1032err4:1033cxio_hal_pblpool_destroy(rdev_p);1034err3:1035cxio_hal_destroy_resource(rdev_p->rscp);1036err2:1037cxio_hal_destroy_ctrl_qp(rdev_p);1038err1:1039rdev_p->t3cdev_p->ulp = NULL;1040list_del(&rdev_p->entry);1041return err;1042}10431044void cxio_rdev_close(struct cxio_rdev *rdev_p)1045{1046if (rdev_p) {1047cxio_hal_pblpool_destroy(rdev_p);1048cxio_hal_rqtpool_destroy(rdev_p);1049list_del(&rdev_p->entry);1050cxio_hal_destroy_ctrl_qp(rdev_p);1051cxio_hal_destroy_resource(rdev_p->rscp);1052rdev_p->t3cdev_p->ulp = NULL;1053}1054}10551056int __init cxio_hal_init(void)1057{1058if (cxio_hal_init_rhdl_resource(T3_MAX_NUM_RI))1059return -ENOMEM;1060t3_register_cpl_handler(CPL_ASYNC_NOTIF, cxio_hal_ev_handler);1061return 0;1062}10631064void __exit cxio_hal_exit(void)1065{1066struct cxio_rdev *rdev, *tmp;10671068t3_register_cpl_handler(CPL_ASYNC_NOTIF, NULL);1069list_for_each_entry_safe(rdev, tmp, &rdev_list, entry)1070cxio_rdev_close(rdev);1071cxio_hal_destroy_rhdl_resource();1072}10731074static void flush_completed_wrs(struct t3_wq *wq, struct t3_cq *cq)1075{1076struct t3_swsq *sqp;1077__u32 ptr = wq->sq_rptr;1078int count = Q_COUNT(wq->sq_rptr, wq->sq_wptr);10791080sqp = wq->sq + Q_PTR2IDX(ptr, wq->sq_size_log2);1081while (count--)1082if (!sqp->signaled) {1083ptr++;1084sqp = wq->sq + Q_PTR2IDX(ptr, wq->sq_size_log2);1085} else if (sqp->complete) {10861087/*1088* Insert this completed cqe into the swcq.1089*/1090PDBG("%s moving cqe into swcq sq idx %ld cq idx %ld\n",1091__func__, Q_PTR2IDX(ptr, wq->sq_size_log2),1092Q_PTR2IDX(cq->sw_wptr, cq->size_log2));1093sqp->cqe.header |= htonl(V_CQE_SWCQE(1));1094*(cq->sw_queue + Q_PTR2IDX(cq->sw_wptr, cq->size_log2))1095= sqp->cqe;1096cq->sw_wptr++;1097sqp->signaled = 0;1098break;1099} else1100break;1101}11021103static void create_read_req_cqe(struct t3_wq *wq, struct t3_cqe *hw_cqe,1104struct t3_cqe *read_cqe)1105{1106read_cqe->u.scqe.wrid_hi = wq->oldest_read->sq_wptr;1107read_cqe->len = wq->oldest_read->read_len;1108read_cqe->header = htonl(V_CQE_QPID(CQE_QPID(*hw_cqe)) |1109V_CQE_SWCQE(SW_CQE(*hw_cqe)) |1110V_CQE_OPCODE(T3_READ_REQ) |1111V_CQE_TYPE(1));1112}11131114/*1115* Return a ptr to the next read wr in the SWSQ or NULL.1116*/1117static void advance_oldest_read(struct t3_wq *wq)1118{11191120u32 rptr = wq->oldest_read - wq->sq + 1;1121u32 wptr = Q_PTR2IDX(wq->sq_wptr, wq->sq_size_log2);11221123while (Q_PTR2IDX(rptr, wq->sq_size_log2) != wptr) {1124wq->oldest_read = wq->sq + Q_PTR2IDX(rptr, wq->sq_size_log2);11251126if (wq->oldest_read->opcode == T3_READ_REQ)1127return;1128rptr++;1129}1130wq->oldest_read = NULL;1131}11321133/*1134* cxio_poll_cq1135*1136* Caller must:1137* check the validity of the first CQE,1138* supply the wq assicated with the qpid.1139*1140* credit: cq credit to return to sge.1141* cqe_flushed: 1 iff the CQE is flushed.1142* cqe: copy of the polled CQE.1143*1144* return value:1145* 0 CQE returned,1146* -1 CQE skipped, try again.1147*/1148int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe,1149u8 *cqe_flushed, u64 *cookie, u32 *credit)1150{1151int ret = 0;1152struct t3_cqe *hw_cqe, read_cqe;11531154*cqe_flushed = 0;1155*credit = 0;1156hw_cqe = cxio_next_cqe(cq);11571158PDBG("%s CQE OOO %d qpid 0x%0x genbit %d type %d status 0x%0x"1159" opcode 0x%0x len 0x%0x wrid_hi_stag 0x%x wrid_low_msn 0x%x\n",1160__func__, CQE_OOO(*hw_cqe), CQE_QPID(*hw_cqe),1161CQE_GENBIT(*hw_cqe), CQE_TYPE(*hw_cqe), CQE_STATUS(*hw_cqe),1162CQE_OPCODE(*hw_cqe), CQE_LEN(*hw_cqe), CQE_WRID_HI(*hw_cqe),1163CQE_WRID_LOW(*hw_cqe));11641165/*1166* skip cqe's not affiliated with a QP.1167*/1168if (wq == NULL) {1169ret = -1;1170goto skip_cqe;1171}11721173/*1174* Gotta tweak READ completions:1175* 1) the cqe doesn't contain the sq_wptr from the wr.1176* 2) opcode not reflected from the wr.1177* 3) read_len not reflected from the wr.1178* 4) cq_type is RQ_TYPE not SQ_TYPE.1179*/1180if (RQ_TYPE(*hw_cqe) && (CQE_OPCODE(*hw_cqe) == T3_READ_RESP)) {11811182/*1183* If this is an unsolicited read response, then the read1184* was generated by the kernel driver as part of peer-2-peer1185* connection setup. So ignore the completion.1186*/1187if (!wq->oldest_read) {1188if (CQE_STATUS(*hw_cqe))1189wq->error = 1;1190ret = -1;1191goto skip_cqe;1192}11931194/*1195* Don't write to the HWCQ, so create a new read req CQE1196* in local memory.1197*/1198create_read_req_cqe(wq, hw_cqe, &read_cqe);1199hw_cqe = &read_cqe;1200advance_oldest_read(wq);1201}12021203/*1204* T3A: Discard TERMINATE CQEs.1205*/1206if (CQE_OPCODE(*hw_cqe) == T3_TERMINATE) {1207ret = -1;1208wq->error = 1;1209goto skip_cqe;1210}12111212if (CQE_STATUS(*hw_cqe) || wq->error) {1213*cqe_flushed = wq->error;1214wq->error = 1;12151216/*1217* T3A inserts errors into the CQE. We cannot return1218* these as work completions.1219*/1220/* incoming write failures */1221if ((CQE_OPCODE(*hw_cqe) == T3_RDMA_WRITE)1222&& RQ_TYPE(*hw_cqe)) {1223ret = -1;1224goto skip_cqe;1225}1226/* incoming read request failures */1227if ((CQE_OPCODE(*hw_cqe) == T3_READ_RESP) && SQ_TYPE(*hw_cqe)) {1228ret = -1;1229goto skip_cqe;1230}12311232/* incoming SEND with no receive posted failures */1233if (CQE_SEND_OPCODE(*hw_cqe) && RQ_TYPE(*hw_cqe) &&1234Q_EMPTY(wq->rq_rptr, wq->rq_wptr)) {1235ret = -1;1236goto skip_cqe;1237}1238BUG_ON((*cqe_flushed == 0) && !SW_CQE(*hw_cqe));1239goto proc_cqe;1240}12411242/*1243* RECV completion.1244*/1245if (RQ_TYPE(*hw_cqe)) {12461247/*1248* HW only validates 4 bits of MSN. So we must validate that1249* the MSN in the SEND is the next expected MSN. If its not,1250* then we complete this with TPT_ERR_MSN and mark the wq in1251* error.1252*/12531254if (Q_EMPTY(wq->rq_rptr, wq->rq_wptr)) {1255wq->error = 1;1256ret = -1;1257goto skip_cqe;1258}12591260if (unlikely((CQE_WRID_MSN(*hw_cqe) != (wq->rq_rptr + 1)))) {1261wq->error = 1;1262hw_cqe->header |= htonl(V_CQE_STATUS(TPT_ERR_MSN));1263goto proc_cqe;1264}1265goto proc_cqe;1266}12671268/*1269* If we get here its a send completion.1270*1271* Handle out of order completion. These get stuffed1272* in the SW SQ. Then the SW SQ is walked to move any1273* now in-order completions into the SW CQ. This handles1274* 2 cases:1275* 1) reaping unsignaled WRs when the first subsequent1276* signaled WR is completed.1277* 2) out of order read completions.1278*/1279if (!SW_CQE(*hw_cqe) && (CQE_WRID_SQ_WPTR(*hw_cqe) != wq->sq_rptr)) {1280struct t3_swsq *sqp;12811282PDBG("%s out of order completion going in swsq at idx %ld\n",1283__func__,1284Q_PTR2IDX(CQE_WRID_SQ_WPTR(*hw_cqe), wq->sq_size_log2));1285sqp = wq->sq +1286Q_PTR2IDX(CQE_WRID_SQ_WPTR(*hw_cqe), wq->sq_size_log2);1287sqp->cqe = *hw_cqe;1288sqp->complete = 1;1289ret = -1;1290goto flush_wq;1291}12921293proc_cqe:1294*cqe = *hw_cqe;12951296/*1297* Reap the associated WR(s) that are freed up with this1298* completion.1299*/1300if (SQ_TYPE(*hw_cqe)) {1301wq->sq_rptr = CQE_WRID_SQ_WPTR(*hw_cqe);1302PDBG("%s completing sq idx %ld\n", __func__,1303Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2));1304*cookie = wq->sq[Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2)].wr_id;1305wq->sq_rptr++;1306} else {1307PDBG("%s completing rq idx %ld\n", __func__,1308Q_PTR2IDX(wq->rq_rptr, wq->rq_size_log2));1309*cookie = wq->rq[Q_PTR2IDX(wq->rq_rptr, wq->rq_size_log2)].wr_id;1310if (wq->rq[Q_PTR2IDX(wq->rq_rptr, wq->rq_size_log2)].pbl_addr)1311cxio_hal_pblpool_free(wq->rdev,1312wq->rq[Q_PTR2IDX(wq->rq_rptr,1313wq->rq_size_log2)].pbl_addr, T3_STAG0_PBL_SIZE);1314BUG_ON(Q_EMPTY(wq->rq_rptr, wq->rq_wptr));1315wq->rq_rptr++;1316}13171318flush_wq:1319/*1320* Flush any completed cqes that are now in-order.1321*/1322flush_completed_wrs(wq, cq);13231324skip_cqe:1325if (SW_CQE(*hw_cqe)) {1326PDBG("%s cq %p cqid 0x%x skip sw cqe sw_rptr 0x%x\n",1327__func__, cq, cq->cqid, cq->sw_rptr);1328++cq->sw_rptr;1329} else {1330PDBG("%s cq %p cqid 0x%x skip hw cqe rptr 0x%x\n",1331__func__, cq, cq->cqid, cq->rptr);1332++cq->rptr;13331334/*1335* T3A: compute credits.1336*/1337if (((cq->rptr - cq->wptr) > (1 << (cq->size_log2 - 1)))1338|| ((cq->rptr - cq->wptr) >= 128)) {1339*credit = cq->rptr - cq->wptr;1340cq->wptr = cq->rptr;1341}1342}1343return ret;1344}134513461347