📄 mthca_srq.c
字号:
/* * Copyright (c) 2005 Cisco Systems. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * $Id: mthca_srq.c 3047 2005-08-10 03:59:35Z roland $ */#include <linux/slab.h>#include <linux/string.h>#include "mthca_dev.h"#include "mthca_cmd.h"#include "mthca_memfree.h"#include "mthca_wqe.h"enum { MTHCA_MAX_DIRECT_SRQ_SIZE = 4 * PAGE_SIZE};struct mthca_tavor_srq_context { __be64 wqe_base_ds; /* low 6 bits is descriptor size */ __be32 state_pd; __be32 lkey; __be32 uar; __be32 wqe_cnt; u32 reserved[2];};struct mthca_arbel_srq_context { __be32 state_logsize_srqn; __be32 lkey; __be32 db_index; __be32 logstride_usrpage; __be64 wqe_base; __be32 eq_pd; __be16 limit_watermark; __be16 wqe_cnt; u16 reserved1; __be16 wqe_counter; u32 reserved2[3];};static void *get_wqe(struct mthca_srq *srq, int n){ if (srq->is_direct) return srq->queue.direct.buf + (n << srq->wqe_shift); else return srq->queue.page_list[(n << srq->wqe_shift) >> PAGE_SHIFT].buf + ((n << srq->wqe_shift) & (PAGE_SIZE - 1));}/* * Return a pointer to the location within a WQE that we're using as a * link when the WQE is in the free list. We use the imm field * because in the Tavor case, posting a WQE may overwrite the next * segment of the previous WQE, but a receive WQE will never touch the * imm field. This avoids corrupting our free list if the previous * WQE has already completed and been put on the free list when we * post the next WQE. */static inline int *wqe_to_link(void *wqe){ return (int *) (wqe + offsetof(struct mthca_next_seg, imm));}static void mthca_tavor_init_srq_context(struct mthca_dev *dev, struct mthca_pd *pd, struct mthca_srq *srq, struct mthca_tavor_srq_context *context){ memset(context, 0, sizeof *context); context->wqe_base_ds = cpu_to_be64(1 << (srq->wqe_shift - 4)); context->state_pd = cpu_to_be32(pd->pd_num); context->lkey = cpu_to_be32(srq->mr.ibmr.lkey); if (pd->ibpd.uobject) context->uar = cpu_to_be32(to_mucontext(pd->ibpd.uobject->context)->uar.index); else context->uar = cpu_to_be32(dev->driver_uar.index);}static void mthca_arbel_init_srq_context(struct mthca_dev *dev, struct mthca_pd *pd, struct mthca_srq *srq, struct mthca_arbel_srq_context *context){ int logsize; memset(context, 0, sizeof *context); logsize = long_log2(srq->max) + srq->wqe_shift; context->state_logsize_srqn = cpu_to_be32(logsize << 24 | srq->srqn); context->lkey = cpu_to_be32(srq->mr.ibmr.lkey); context->db_index = cpu_to_be32(srq->db_index); context->logstride_usrpage = cpu_to_be32((srq->wqe_shift - 4) << 29); if (pd->ibpd.uobject) context->logstride_usrpage |= cpu_to_be32(to_mucontext(pd->ibpd.uobject->context)->uar.index); else context->logstride_usrpage |= cpu_to_be32(dev->driver_uar.index); context->eq_pd = cpu_to_be32(MTHCA_EQ_ASYNC << 24 | pd->pd_num);}static void mthca_free_srq_buf(struct mthca_dev *dev, struct mthca_srq *srq){ mthca_buf_free(dev, srq->max << srq->wqe_shift, &srq->queue, srq->is_direct, &srq->mr); kfree(srq->wrid);}static int mthca_alloc_srq_buf(struct mthca_dev *dev, struct mthca_pd *pd, struct mthca_srq *srq){ struct mthca_data_seg *scatter; void *wqe; int err; int i; if (pd->ibpd.uobject) return 0; srq->wrid = kmalloc(srq->max * sizeof (u64), GFP_KERNEL); if (!srq->wrid) return -ENOMEM; err = mthca_buf_alloc(dev, srq->max << srq->wqe_shift, MTHCA_MAX_DIRECT_SRQ_SIZE, &srq->queue, &srq->is_direct, pd, 1, &srq->mr); if (err) { kfree(srq->wrid); return err; } /* * Now initialize the SRQ buffer so that all of the WQEs are * linked into the list of free WQEs. In addition, set the * scatter list L_Keys to the sentry value of 0x100. */ for (i = 0; i < srq->max; ++i) { wqe = get_wqe(srq, i); *wqe_to_link(wqe) = i < srq->max - 1 ? i + 1 : -1; for (scatter = wqe + sizeof (struct mthca_next_seg); (void *) scatter < wqe + (1 << srq->wqe_shift); ++scatter) scatter->lkey = cpu_to_be32(MTHCA_INVAL_LKEY); } srq->last = get_wqe(srq, srq->max - 1); return 0;}int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, struct ib_srq_attr *attr, struct mthca_srq *srq){ struct mthca_mailbox *mailbox; u8 status; int ds; int err; /* Sanity check SRQ size before proceeding */ if (attr->max_wr > dev->limits.max_srq_wqes || attr->max_sge > dev->limits.max_sg) return -EINVAL; srq->max = attr->max_wr; srq->max_gs = attr->max_sge; srq->counter = 0; if (mthca_is_memfree(dev)) srq->max = roundup_pow_of_two(srq->max + 1); ds = min(64UL, roundup_pow_of_two(sizeof (struct mthca_next_seg) + srq->max_gs * sizeof (struct mthca_data_seg))); srq->wqe_shift = long_log2(ds); srq->srqn = mthca_alloc(&dev->srq_table.alloc); if (srq->srqn == -1) return -ENOMEM; if (mthca_is_memfree(dev)) { err = mthca_table_get(dev, dev->srq_table.table, srq->srqn); if (err) goto err_out; if (!pd->ibpd.uobject) { srq->db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SRQ, srq->srqn, &srq->db); if (srq->db_index < 0) { err = -ENOMEM; goto err_out_icm; } } } mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); if (IS_ERR(mailbox)) { err = PTR_ERR(mailbox); goto err_out_db; } err = mthca_alloc_srq_buf(dev, pd, srq); if (err) goto err_out_mailbox; spin_lock_init(&srq->lock); atomic_set(&srq->refcount, 1); init_waitqueue_head(&srq->wait); if (mthca_is_memfree(dev)) mthca_arbel_init_srq_context(dev, pd, srq, mailbox->buf); else mthca_tavor_init_srq_context(dev, pd, srq, mailbox->buf); err = mthca_SW2HW_SRQ(dev, mailbox, srq->srqn, &status); if (err) { mthca_warn(dev, "SW2HW_SRQ failed (%d)\n", err); goto err_out_free_buf; } if (status) { mthca_warn(dev, "SW2HW_SRQ returned status 0x%02x\n", status); err = -EINVAL; goto err_out_free_buf; } spin_lock_irq(&dev->srq_table.lock); if (mthca_array_set(&dev->srq_table.srq, srq->srqn & (dev->limits.num_srqs - 1), srq)) { spin_unlock_irq(&dev->srq_table.lock); goto err_out_free_srq; } spin_unlock_irq(&dev->srq_table.lock); mthca_free_mailbox(dev, mailbox); srq->first_free = 0; srq->last_free = srq->max - 1; return 0;err_out_free_srq: err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status); if (err) mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err); else if (status) mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status);err_out_free_buf: if (!pd->ibpd.uobject) mthca_free_srq_buf(dev, srq);err_out_mailbox: mthca_free_mailbox(dev, mailbox);err_out_db: if (!pd->ibpd.uobject && mthca_is_memfree(dev)) mthca_free_db(dev, MTHCA_DB_TYPE_SRQ, srq->db_index);err_out_icm: mthca_table_put(dev, dev->srq_table.table, srq->srqn);err_out: mthca_free(&dev->srq_table.alloc, srq->srqn); return err;}void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq){ struct mthca_mailbox *mailbox; int err; u8 status; mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); if (IS_ERR(mailbox)) { mthca_warn(dev, "No memory for mailbox to free SRQ.\n"); return; } err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status); if (err) mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err); else if (status) mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status); spin_lock_irq(&dev->srq_table.lock); mthca_array_clear(&dev->srq_table.srq, srq->srqn & (dev->limits.num_srqs - 1)); spin_unlock_irq(&dev->srq_table.lock);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -