···11/*22 * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.33 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.44- * Copyright (c) 2005 Cisco Systems. All rights reserved.44+ * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved.55 *66 * This software is available to you under a choice of one of two77 * licenses. You may choose to be licensed under the terms of the GNU···15121512 return mthca_cmd_box(dev, 0, mailbox->dma, cq_num, 0,15131513 CMD_HW2SW_CQ,15141514 CMD_TIME_CLASS_A, status);15151515+}15161516+15171517+int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size,15181518+ u8 *status)15191519+{15201520+ struct mthca_mailbox *mailbox;15211521+ __be32 *inbox;15221522+ int err;15231523+15241524+#define RESIZE_CQ_IN_SIZE 0x4015251525+#define RESIZE_CQ_LOG_SIZE_OFFSET 0x0c15261526+#define RESIZE_CQ_LKEY_OFFSET 0x1c15271527+15281528+ mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);15291529+ if (IS_ERR(mailbox))15301530+ return PTR_ERR(mailbox);15311531+ inbox = mailbox->buf;15321532+15331533+ memset(inbox, 0, RESIZE_CQ_IN_SIZE);15341534+ /*15351535+ * Leave start address fields zeroed out -- mthca assumes that15361536+ * MRs for CQs always start at virtual address 0.15371537+ */15381538+ MTHCA_PUT(inbox, log_size, RESIZE_CQ_LOG_SIZE_OFFSET);15391539+ MTHCA_PUT(inbox, lkey, RESIZE_CQ_LKEY_OFFSET);15401540+15411541+ err = mthca_cmd(dev, mailbox->dma, cq_num, 1, CMD_RESIZE_CQ,15421542+ CMD_TIME_CLASS_B, status);15431543+15441544+ mthca_free_mailbox(dev, mailbox);15451545+ return err;15151546}1516154715171548int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+3
drivers/infiniband/hw/mthca/mthca_cmd.h
···11/*22 * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.33 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.44+ * Copyright (c) 2006 Cisco Systems. All rights reserved.45 *56 * This software is available to you under a choice of one of two67 * licenses. You may choose to be licensed under the terms of the GNU···299298 int cq_num, u8 *status);300299int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,301300 int cq_num, u8 *status);301301+int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size,302302+ u8 *status);302303int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,303304 int srq_num, u8 *status);304305int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+105-27
drivers/infiniband/hw/mthca/mthca_cq.c
···11/*22 * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.33 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.44- * Copyright (c) 2005 Cisco Systems, Inc. All rights reserved.44+ * Copyright (c) 2005, 2006 Cisco Systems, Inc. All rights reserved.55 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.66 * Copyright (c) 2004 Voltaire, Inc. All rights reserved.77 *···150150#define MTHCA_ARBEL_CQ_DB_REQ_NOT (2 << 24)151151#define MTHCA_ARBEL_CQ_DB_REQ_NOT_MULT (3 << 24)152152153153-static inline struct mthca_cqe *get_cqe(struct mthca_cq *cq, int entry)153153+static inline struct mthca_cqe *get_cqe_from_buf(struct mthca_cq_buf *buf,154154+ int entry)154155{155155- if (cq->is_direct)156156- return cq->queue.direct.buf + (entry * MTHCA_CQ_ENTRY_SIZE);156156+ if (buf->is_direct)157157+ return buf->queue.direct.buf + (entry * MTHCA_CQ_ENTRY_SIZE);157158 else158158- return cq->queue.page_list[entry * MTHCA_CQ_ENTRY_SIZE / PAGE_SIZE].buf159159+ return buf->queue.page_list[entry * MTHCA_CQ_ENTRY_SIZE / PAGE_SIZE].buf159160 + (entry * MTHCA_CQ_ENTRY_SIZE) % PAGE_SIZE;160161}161162162162-static inline struct mthca_cqe *cqe_sw(struct mthca_cq *cq, int i)163163+static inline struct mthca_cqe *get_cqe(struct mthca_cq *cq, int entry)163164{164164- struct mthca_cqe *cqe = get_cqe(cq, i);165165+ return get_cqe_from_buf(&cq->buf, entry);166166+}167167+168168+static inline struct mthca_cqe *cqe_sw(struct mthca_cqe *cqe)169169+{165170 return MTHCA_CQ_ENTRY_OWNER_HW & cqe->owner ? NULL : cqe;166171}167172168173static inline struct mthca_cqe *next_cqe_sw(struct mthca_cq *cq)169174{170170- return cqe_sw(cq, cq->cons_index & cq->ibcq.cqe);175175+ return cqe_sw(get_cqe(cq, cq->cons_index & cq->ibcq.cqe));171176}172177173178static inline void set_cqe_hw(struct mthca_cqe *cqe)···294289 * from our QP and therefore don't need to be checked.295290 */296291 for (prod_index = cq->cons_index;297297- cqe_sw(cq, prod_index & cq->ibcq.cqe);292292+ cqe_sw(get_cqe(cq, prod_index & cq->ibcq.cqe));298293 ++prod_index)299294 if (prod_index == cq->cons_index + cq->ibcq.cqe)300295 break;···327322 spin_unlock_irq(&cq->lock);328323 if (atomic_dec_and_test(&cq->refcount))329324 wake_up(&cq->wait);325325+}326326+327327+void mthca_cq_resize_copy_cqes(struct mthca_cq *cq)328328+{329329+ int i;330330+331331+ /*332332+ * In Tavor mode, the hardware keeps the consumer and producer333333+ * indices mod the CQ size. Since we might be making the CQ334334+ * bigger, we need to deal with the case where the producer335335+ * index wrapped around before the CQ was resized.336336+ */337337+ if (!mthca_is_memfree(to_mdev(cq->ibcq.device)) &&338338+ cq->ibcq.cqe < cq->resize_buf->cqe) {339339+ cq->cons_index &= cq->ibcq.cqe;340340+ if (cqe_sw(get_cqe(cq, cq->ibcq.cqe)))341341+ cq->cons_index -= cq->ibcq.cqe + 1;342342+ }343343+344344+ for (i = cq->cons_index; cqe_sw(get_cqe(cq, i & cq->ibcq.cqe)); ++i)345345+ memcpy(get_cqe_from_buf(&cq->resize_buf->buf,346346+ i & cq->resize_buf->cqe),347347+ get_cqe(cq, i & cq->ibcq.cqe), MTHCA_CQ_ENTRY_SIZE);348348+}349349+350350+int mthca_alloc_cq_buf(struct mthca_dev *dev, struct mthca_cq_buf *buf, int nent)351351+{352352+ int ret;353353+ int i;354354+355355+ ret = mthca_buf_alloc(dev, nent * MTHCA_CQ_ENTRY_SIZE,356356+ MTHCA_MAX_DIRECT_CQ_SIZE,357357+ &buf->queue, &buf->is_direct,358358+ &dev->driver_pd, 1, &buf->mr);359359+ if (ret)360360+ return ret;361361+362362+ for (i = 0; i < nent; ++i)363363+ set_cqe_hw(get_cqe_from_buf(buf, i));364364+365365+ return 0;366366+}367367+368368+void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq_buf *buf, int cqe)369369+{370370+ mthca_buf_free(dev, (cqe + 1) * MTHCA_CQ_ENTRY_SIZE, &buf->queue,371371+ buf->is_direct, &buf->mr);330372}331373332374static void handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,···661609662610 spin_lock_irqsave(&cq->lock, flags);663611664664- for (npolled = 0; npolled < num_entries; ++npolled) {612612+ npolled = 0;613613+repoll:614614+ while (npolled < num_entries) {665615 err = mthca_poll_one(dev, cq, &qp,666616 &freed, entry + npolled);667617 if (err)668618 break;619619+ ++npolled;669620 }670621671622 if (freed) {672623 wmb();673624 update_cons_index(dev, cq, freed);625625+ }626626+627627+ /*628628+ * If a CQ resize is in progress and we discovered that the629629+ * old buffer is empty, then peek in the new buffer, and if630630+ * it's not empty, switch to the new buffer and continue631631+ * polling there.632632+ */633633+ if (unlikely(err == -EAGAIN && cq->resize_buf &&634634+ cq->resize_buf->state == CQ_RESIZE_READY)) {635635+ /*636636+ * In Tavor mode, the hardware keeps the producer637637+ * index modulo the CQ size. Since we might be making638638+ * the CQ bigger, we need to mask our consumer index639639+ * using the size of the old CQ buffer before looking640640+ * in the new CQ buffer.641641+ */642642+ if (!mthca_is_memfree(dev))643643+ cq->cons_index &= cq->ibcq.cqe;644644+645645+ if (cqe_sw(get_cqe_from_buf(&cq->resize_buf->buf,646646+ cq->cons_index & cq->resize_buf->cqe))) {647647+ struct mthca_cq_buf tbuf;648648+ int tcqe;649649+650650+ tbuf = cq->buf;651651+ tcqe = cq->ibcq.cqe;652652+ cq->buf = cq->resize_buf->buf;653653+ cq->ibcq.cqe = cq->resize_buf->cqe;654654+655655+ cq->resize_buf->buf = tbuf;656656+ cq->resize_buf->cqe = tcqe;657657+ cq->resize_buf->state = CQ_RESIZE_SWAPPED;658658+659659+ goto repoll;660660+ }674661 }675662676663 spin_unlock_irqrestore(&cq->lock, flags);···770679 return 0;771680}772681773773-static void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq *cq)774774-{775775- mthca_buf_free(dev, (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,776776- &cq->queue, cq->is_direct, &cq->mr);777777-}778778-779682int mthca_init_cq(struct mthca_dev *dev, int nent,780683 struct mthca_ucontext *ctx, u32 pdn,781684 struct mthca_cq *cq)782685{783783- int size = nent * MTHCA_CQ_ENTRY_SIZE;784686 struct mthca_mailbox *mailbox;785687 struct mthca_cq_context *cq_context;786688 int err = -ENOMEM;787689 u8 status;788788- int i;789690790691 cq->ibcq.cqe = nent - 1;791692 cq->is_kernel = !ctx;···815732 cq_context = mailbox->buf;816733817734 if (cq->is_kernel) {818818- err = mthca_buf_alloc(dev, size, MTHCA_MAX_DIRECT_CQ_SIZE,819819- &cq->queue, &cq->is_direct,820820- &dev->driver_pd, 1, &cq->mr);735735+ err = mthca_alloc_cq_buf(dev, &cq->buf, nent);821736 if (err)822737 goto err_out_mailbox;823823-824824- for (i = 0; i < nent; ++i)825825- set_cqe_hw(get_cqe(cq, i));826738 }827739828740 spin_lock_init(&cq->lock);···836758 cq_context->error_eqn = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);837759 cq_context->comp_eqn = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_COMP].eqn);838760 cq_context->pd = cpu_to_be32(pdn);839839- cq_context->lkey = cpu_to_be32(cq->mr.ibmr.lkey);761761+ cq_context->lkey = cpu_to_be32(cq->buf.mr.ibmr.lkey);840762 cq_context->cqn = cpu_to_be32(cq->cqn);841763842764 if (mthca_is_memfree(dev)) {···874796875797err_out_free_mr:876798 if (cq->is_kernel)877877- mthca_free_cq_buf(dev, cq);799799+ mthca_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);878800879801err_out_mailbox:880802 mthca_free_mailbox(dev, mailbox);···940862 wait_event(cq->wait, !atomic_read(&cq->refcount));941863942864 if (cq->is_kernel) {943943- mthca_free_cq_buf(dev, cq);865865+ mthca_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);944866 if (mthca_is_memfree(dev)) {945867 mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);946868 mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
+4-1
drivers/infiniband/hw/mthca/mthca_dev.h
···11/*22 * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.33 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.44- * Copyright (c) 2005 Cisco Systems. All rights reserved.44+ * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved.55 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.66 * Copyright (c) 2004 Voltaire, Inc. All rights reserved.77 *···470470 enum ib_event_type event_type);471471void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,472472 struct mthca_srq *srq);473473+void mthca_cq_resize_copy_cqes(struct mthca_cq *cq);474474+int mthca_alloc_cq_buf(struct mthca_dev *dev, struct mthca_cq_buf *buf, int nent);475475+void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq_buf *buf, int cqe);473476474477int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,475478 struct ib_srq_attr *attr, struct mthca_srq *srq);
+123-4
drivers/infiniband/hw/mthca/mthca_provider.c
···11/*22 * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.33 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.44- * Copyright (c) 2005 Cisco Systems. All rights reserved.44+ * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved.55 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.66 * Copyright (c) 2004 Voltaire, Inc. All rights reserved.77 *···669669 }670670671671 if (context) {672672- cq->mr.ibmr.lkey = ucmd.lkey;673673- cq->set_ci_db_index = ucmd.set_db_index;674674- cq->arm_db_index = ucmd.arm_db_index;672672+ cq->buf.mr.ibmr.lkey = ucmd.lkey;673673+ cq->set_ci_db_index = ucmd.set_db_index;674674+ cq->arm_db_index = ucmd.arm_db_index;675675 }676676677677 for (nent = 1; nent <= entries; nent <<= 1)···689689 goto err_free;690690 }691691692692+ cq->resize_buf = NULL;693693+692694 return &cq->ibcq;693695694696err_free:···707705 to_mucontext(context)->db_tab, ucmd.set_db_index);708706709707 return ERR_PTR(err);708708+}709709+710710+static int mthca_alloc_resize_buf(struct mthca_dev *dev, struct mthca_cq *cq,711711+ int entries)712712+{713713+ int ret;714714+715715+ spin_lock_irq(&cq->lock);716716+ if (cq->resize_buf) {717717+ ret = -EBUSY;718718+ goto unlock;719719+ }720720+721721+ cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_ATOMIC);722722+ if (!cq->resize_buf) {723723+ ret = -ENOMEM;724724+ goto unlock;725725+ }726726+727727+ cq->resize_buf->state = CQ_RESIZE_ALLOC;728728+729729+ ret = 0;730730+731731+unlock:732732+ spin_unlock_irq(&cq->lock);733733+734734+ if (ret)735735+ return ret;736736+737737+ ret = mthca_alloc_cq_buf(dev, &cq->resize_buf->buf, entries);738738+ if (ret) {739739+ spin_lock_irq(&cq->lock);740740+ kfree(cq->resize_buf);741741+ cq->resize_buf = NULL;742742+ spin_unlock_irq(&cq->lock);743743+ return ret;744744+ }745745+746746+ cq->resize_buf->cqe = entries - 1;747747+748748+ spin_lock_irq(&cq->lock);749749+ cq->resize_buf->state = CQ_RESIZE_READY;750750+ spin_unlock_irq(&cq->lock);751751+752752+ return 0;753753+}754754+755755+static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)756756+{757757+ struct mthca_dev *dev = to_mdev(ibcq->device);758758+ struct mthca_cq *cq = to_mcq(ibcq);759759+ struct mthca_resize_cq ucmd;760760+ u32 lkey;761761+ u8 status;762762+ int ret;763763+764764+ if (entries < 1 || entries > dev->limits.max_cqes)765765+ return -EINVAL;766766+767767+ entries = roundup_pow_of_two(entries + 1);768768+ if (entries == ibcq->cqe + 1)769769+ return 0;770770+771771+ if (cq->is_kernel) {772772+ ret = mthca_alloc_resize_buf(dev, cq, entries);773773+ if (ret)774774+ return ret;775775+ lkey = cq->resize_buf->buf.mr.ibmr.lkey;776776+ } else {777777+ if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))778778+ return -EFAULT;779779+ lkey = ucmd.lkey;780780+ }781781+782782+ ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, long_log2(entries), &status);783783+ if (status)784784+ ret = -EINVAL;785785+786786+ if (ret) {787787+ if (cq->resize_buf) {788788+ mthca_free_cq_buf(dev, &cq->resize_buf->buf,789789+ cq->resize_buf->cqe);790790+ kfree(cq->resize_buf);791791+ spin_lock_irq(&cq->lock);792792+ cq->resize_buf = NULL;793793+ spin_unlock_irq(&cq->lock);794794+ }795795+ return ret;796796+ }797797+798798+ if (cq->is_kernel) {799799+ struct mthca_cq_buf tbuf;800800+ int tcqe;801801+802802+ spin_lock_irq(&cq->lock);803803+ if (cq->resize_buf->state == CQ_RESIZE_READY) {804804+ mthca_cq_resize_copy_cqes(cq);805805+ tbuf = cq->buf;806806+ tcqe = cq->ibcq.cqe;807807+ cq->buf = cq->resize_buf->buf;808808+ cq->ibcq.cqe = cq->resize_buf->cqe;809809+ } else {810810+ tbuf = cq->resize_buf->buf;811811+ tcqe = cq->resize_buf->cqe;812812+ }813813+814814+ kfree(cq->resize_buf);815815+ cq->resize_buf = NULL;816816+ spin_unlock_irq(&cq->lock);817817+818818+ mthca_free_cq_buf(dev, &tbuf, tcqe);819819+ } else820820+ ibcq->cqe = entries - 1;821821+822822+ return 0;710823}711824712825static int mthca_destroy_cq(struct ib_cq *cq)···12301113 (1ull << IB_USER_VERBS_CMD_DEREG_MR) |12311114 (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |12321115 (1ull << IB_USER_VERBS_CMD_CREATE_CQ) |11161116+ (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) |12331117 (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |12341118 (1ull << IB_USER_VERBS_CMD_CREATE_QP) |12351119 (1ull << IB_USER_VERBS_CMD_MODIFY_QP) |···12721154 dev->ib_dev.modify_qp = mthca_modify_qp;12731155 dev->ib_dev.destroy_qp = mthca_destroy_qp;12741156 dev->ib_dev.create_cq = mthca_create_cq;11571157+ dev->ib_dev.resize_cq = mthca_resize_cq;12751158 dev->ib_dev.destroy_cq = mthca_destroy_cq;12761159 dev->ib_dev.poll_cq = mthca_poll_cq;12771160 dev->ib_dev.get_dma_mr = mthca_get_dma_mr;
+35-18
drivers/infiniband/hw/mthca/mthca_provider.h
···11/*22 * Copyright (c) 2004 Topspin Communications. All rights reserved.33- * Copyright (c) 2005 Cisco Systems. All rights reserved.33+ * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved.44 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.55 *66 * This software is available to you under a choice of one of two···164164 * - wait_event until ref count is zero165165 *166166 * It is the consumer's responsibilty to make sure that no QP167167- * operations (WQE posting or state modification) are pending when the167167+ * operations (WQE posting or state modification) are pending when a168168 * QP is destroyed. Also, the consumer must make sure that calls to169169- * qp_modify are serialized.169169+ * qp_modify are serialized. Similarly, the consumer is responsible170170+ * for ensuring that no CQ resize operations are pending when a CQ171171+ * is destroyed.170172 *171173 * Possible optimizations (wait for profile data to see if/where we172174 * have locks bouncing between CPUs):···178176 * send queue and one for the receive queue)179177 */180178179179+struct mthca_cq_buf {180180+ union mthca_buf queue;181181+ struct mthca_mr mr;182182+ int is_direct;183183+};184184+185185+struct mthca_cq_resize {186186+ struct mthca_cq_buf buf;187187+ int cqe;188188+ enum {189189+ CQ_RESIZE_ALLOC,190190+ CQ_RESIZE_READY,191191+ CQ_RESIZE_SWAPPED192192+ } state;193193+};194194+181195struct mthca_cq {182182- struct ib_cq ibcq;183183- spinlock_t lock;184184- atomic_t refcount;185185- int cqn;186186- u32 cons_index;187187- int is_direct;188188- int is_kernel;196196+ struct ib_cq ibcq;197197+ spinlock_t lock;198198+ atomic_t refcount;199199+ int cqn;200200+ u32 cons_index;201201+ struct mthca_cq_buf buf;202202+ struct mthca_cq_resize *resize_buf;203203+ int is_kernel;189204190205 /* Next fields are Arbel only */191191- int set_ci_db_index;192192- __be32 *set_ci_db;193193- int arm_db_index;194194- __be32 *arm_db;195195- int arm_sn;206206+ int set_ci_db_index;207207+ __be32 *set_ci_db;208208+ int arm_db_index;209209+ __be32 *arm_db;210210+ int arm_sn;196211197197- union mthca_buf queue;198198- struct mthca_mr mr;199199- wait_queue_head_t wait;212212+ wait_queue_head_t wait;200213};201214202215struct mthca_srq {
+6-1
drivers/infiniband/hw/mthca/mthca_user.h
···11/*22 * Copyright (c) 2005 Topspin Communications. All rights reserved.33- * Copyright (c) 2005 Cisco Systems. All rights reserved.33+ * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved.44 *55 * This software is available to you under a choice of one of two66 * licenses. You may choose to be licensed under the terms of the GNU···72727373struct mthca_create_cq_resp {7474 __u32 cqn;7575+ __u32 reserved;7676+};7777+7878+struct mthca_resize_cq {7979+ __u32 lkey;7580 __u32 reserved;7681};7782