Commit cd5e25d9 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband

* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband:
  IB/ipath: kbuild infrastructure
  IB/ipath: infiniband verbs support
  IB/ipath: misc infiniband code, part 2
  IB/ipath: misc infiniband code, part 1
  IB/ipath: infiniband RC protocol support
  IB/ipath: infiniband UC and UD protocol support
  IB/ipath: infiniband header files
  IB/ipath: layering interfaces used by higher-level driver code
  IB/ipath: support for userspace apps using core driver
  IB/ipath: sysfs and ipathfs support for core driver
  IB/ipath: misc driver support code
  IB/ipath: chip initialisation code, and diag support
  IB/ipath: support for PCI Express devices
  IB/ipath: support for HyperTransport devices
  IB/ipath: core driver header files
  IB/ipath: core device driver
parents 86dca4f8 77d8798b
...@@ -1451,6 +1451,12 @@ P: Juanjo Ciarlante ...@@ -1451,6 +1451,12 @@ P: Juanjo Ciarlante
M: jjciarla@raiz.uncu.edu.ar M: jjciarla@raiz.uncu.edu.ar
S: Maintained S: Maintained
IPATH DRIVER:
P: Bryan O'Sullivan
M: support@pathscale.com
L: openib-general@openib.org
S: Supported
IPX NETWORK LAYER IPX NETWORK LAYER
P: Arnaldo Carvalho de Melo P: Arnaldo Carvalho de Melo
M: acme@conectiva.com.br M: acme@conectiva.com.br
......
...@@ -69,6 +69,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq/ ...@@ -69,6 +69,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_MMC) += mmc/ obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_NEW_LEDS) += leds/ obj-$(CONFIG_NEW_LEDS) += leds/
obj-$(CONFIG_INFINIBAND) += infiniband/ obj-$(CONFIG_INFINIBAND) += infiniband/
obj-$(CONFIG_IPATH_CORE) += infiniband/
obj-$(CONFIG_SGI_SN) += sn/ obj-$(CONFIG_SGI_SN) += sn/
obj-y += firmware/ obj-y += firmware/
obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_CRYPTO) += crypto/
......
...@@ -30,6 +30,7 @@ config INFINIBAND_USER_ACCESS ...@@ -30,6 +30,7 @@ config INFINIBAND_USER_ACCESS
<http://www.openib.org>. <http://www.openib.org>.
source "drivers/infiniband/hw/mthca/Kconfig" source "drivers/infiniband/hw/mthca/Kconfig"
source "drivers/infiniband/hw/ipath/Kconfig"
source "drivers/infiniband/ulp/ipoib/Kconfig" source "drivers/infiniband/ulp/ipoib/Kconfig"
......
obj-$(CONFIG_INFINIBAND) += core/ obj-$(CONFIG_INFINIBAND) += core/
obj-$(CONFIG_INFINIBAND_MTHCA) += hw/mthca/ obj-$(CONFIG_INFINIBAND_MTHCA) += hw/mthca/
obj-$(CONFIG_IPATH_CORE) += hw/ipath/
obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/ obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/
obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/ obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/
config IPATH_CORE
tristate "PathScale InfiniPath Driver"
depends on 64BIT && PCI_MSI && NET
---help---
This is a low-level driver for PathScale InfiniPath host channel
adapters (HCAs) based on the HT-400 and PE-800 chips.
config INFINIBAND_IPATH
tristate "PathScale InfiniPath Verbs Driver"
depends on IPATH_CORE && INFINIBAND
---help---
This is a driver that provides InfiniBand verbs support for
PathScale InfiniPath host channel adapters (HCAs). This
allows these devices to be used with both kernel upper level
protocols such as IP-over-InfiniBand as well as with userspace
applications (in conjunction with InfiniBand userspace access).
EXTRA_CFLAGS += -DIPATH_IDSTR='"PathScale kernel.org driver"' \
-DIPATH_KERN_TYPE=0
obj-$(CONFIG_IPATH_CORE) += ipath_core.o
obj-$(CONFIG_INFINIBAND_IPATH) += ib_ipath.o
ipath_core-y := \
ipath_diag.o \
ipath_driver.o \
ipath_eeprom.o \
ipath_file_ops.o \
ipath_fs.o \
ipath_ht400.o \
ipath_init_chip.o \
ipath_intr.o \
ipath_layer.o \
ipath_pe800.o \
ipath_stats.o \
ipath_sysfs.o \
ipath_user_pages.o
ipath_core-$(CONFIG_X86_64) += ipath_wc_x86_64.o
ib_ipath-y := \
ipath_cq.o \
ipath_keys.o \
ipath_mad.o \
ipath_mr.o \
ipath_qp.o \
ipath_rc.o \
ipath_ruc.o \
ipath_srq.o \
ipath_uc.o \
ipath_ud.o \
ipath_verbs.o \
ipath_verbs_mcast.o
This diff is collapsed.
/*
* Copyright (c) 2005, 2006 PathScale, Inc. 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.
*/
#include <linux/err.h>
#include <linux/vmalloc.h>
#include "ipath_verbs.h"
/**
* ipath_cq_enter - add a new entry to the completion queue
* @cq: completion queue
* @entry: work completion entry to add
* @sig: true if @entry is a solicitated entry
*
* This may be called with one of the qp->s_lock or qp->r_rq.lock held.
*/
void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int solicited)
{
unsigned long flags;
u32 next;
spin_lock_irqsave(&cq->lock, flags);
if (cq->head == cq->ibcq.cqe)
next = 0;
else
next = cq->head + 1;
if (unlikely(next == cq->tail)) {
spin_unlock_irqrestore(&cq->lock, flags);
if (cq->ibcq.event_handler) {
struct ib_event ev;
ev.device = cq->ibcq.device;
ev.element.cq = &cq->ibcq;
ev.event = IB_EVENT_CQ_ERR;
cq->ibcq.event_handler(&ev, cq->ibcq.cq_context);
}
return;
}
cq->queue[cq->head] = *entry;
cq->head = next;
if (cq->notify == IB_CQ_NEXT_COMP ||
(cq->notify == IB_CQ_SOLICITED && solicited)) {
cq->notify = IB_CQ_NONE;
cq->triggered++;
/*
* This will cause send_complete() to be called in
* another thread.
*/
tasklet_hi_schedule(&cq->comptask);
}
spin_unlock_irqrestore(&cq->lock, flags);
if (entry->status != IB_WC_SUCCESS)
to_idev(cq->ibcq.device)->n_wqe_errs++;
}
/**
* ipath_poll_cq - poll for work completion entries
* @ibcq: the completion queue to poll
* @num_entries: the maximum number of entries to return
* @entry: pointer to array where work completions are placed
*
* Returns the number of completion entries polled.
*
* This may be called from interrupt context. Also called by ib_poll_cq()
* in the generic verbs code.
*/
int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
{
struct ipath_cq *cq = to_icq(ibcq);
unsigned long flags;
int npolled;
spin_lock_irqsave(&cq->lock, flags);
for (npolled = 0; npolled < num_entries; ++npolled, ++entry) {
if (cq->tail == cq->head)
break;
*entry = cq->queue[cq->tail];
if (cq->tail == cq->ibcq.cqe)
cq->tail = 0;
else
cq->tail++;
}
spin_unlock_irqrestore(&cq->lock, flags);
return npolled;
}
static void send_complete(unsigned long data)
{
struct ipath_cq *cq = (struct ipath_cq *)data;
/*
* The completion handler will most likely rearm the notification
* and poll for all pending entries. If a new completion entry
* is added while we are in this routine, tasklet_hi_schedule()
* won't call us again until we return so we check triggered to
* see if we need to call the handler again.
*/
for (;;) {
u8 triggered = cq->triggered;
cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
if (cq->triggered == triggered)
return;
}
}
/**
* ipath_create_cq - create a completion queue
* @ibdev: the device this completion queue is attached to
* @entries: the minimum size of the completion queue
* @context: unused by the InfiniPath driver
* @udata: unused by the InfiniPath driver
*
* Returns a pointer to the completion queue or negative errno values
* for failure.
*
* Called by ib_create_cq() in the generic verbs code.
*/
struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
struct ib_ucontext *context,
struct ib_udata *udata)
{
struct ipath_cq *cq;
struct ib_wc *wc;
struct ib_cq *ret;
/*
* Need to use vmalloc() if we want to support large #s of
* entries.
*/
cq = kmalloc(sizeof(*cq), GFP_KERNEL);
if (!cq) {
ret = ERR_PTR(-ENOMEM);
goto bail;
}
/*
* Need to use vmalloc() if we want to support large #s of entries.
*/
wc = vmalloc(sizeof(*wc) * (entries + 1));
if (!wc) {
kfree(cq);
ret = ERR_PTR(-ENOMEM);
goto bail;
}
/*
* ib_create_cq() will initialize cq->ibcq except for cq->ibcq.cqe.
* The number of entries should be >= the number requested or return
* an error.
*/
cq->ibcq.cqe = entries;
cq->notify = IB_CQ_NONE;
cq->triggered = 0;
spin_lock_init(&cq->lock);
tasklet_init(&cq->comptask, send_complete, (unsigned long)cq);
cq->head = 0;
cq->tail = 0;
cq->queue = wc;
ret = &cq->ibcq;
bail:
return ret;
}
/**
* ipath_destroy_cq - destroy a completion queue
* @ibcq: the completion queue to destroy.
*
* Returns 0 for success.
*
* Called by ib_destroy_cq() in the generic verbs code.
*/
int ipath_destroy_cq(struct ib_cq *ibcq)
{
struct ipath_cq *cq = to_icq(ibcq);
tasklet_kill(&cq->comptask);
vfree(cq->queue);
kfree(cq);
return 0;
}
/**
* ipath_req_notify_cq - change the notification type for a completion queue
* @ibcq: the completion queue
* @notify: the type of notification to request
*
* Returns 0 for success.
*
* This may be called from interrupt context. Also called by
* ib_req_notify_cq() in the generic verbs code.
*/
int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
{
struct ipath_cq *cq = to_icq(ibcq);
unsigned long flags;
spin_lock_irqsave(&cq->lock, flags);
/*
* Don't change IB_CQ_NEXT_COMP to IB_CQ_SOLICITED but allow
* any other transitions.
*/
if (cq->notify != IB_CQ_NEXT_COMP)
cq->notify = notify;
spin_unlock_irqrestore(&cq->lock, flags);
return 0;
}
int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
{
struct ipath_cq *cq = to_icq(ibcq);
struct ib_wc *wc, *old_wc;
u32 n;
int ret;
/*
* Need to use vmalloc() if we want to support large #s of entries.
*/
wc = vmalloc(sizeof(*wc) * (cqe + 1));
if (!wc) {
ret = -ENOMEM;
goto bail;
}
spin_lock_irq(&cq->lock);
if (cq->head < cq->tail)
n = cq->ibcq.cqe + 1 + cq->head - cq->tail;
else
n = cq->head - cq->tail;
if (unlikely((u32)cqe < n)) {
spin_unlock_irq(&cq->lock);
vfree(wc);
ret = -EOVERFLOW;
goto bail;
}
for (n = 0; cq->tail != cq->head; n++) {
wc[n] = cq->queue[cq->tail];
if (cq->tail == cq->ibcq.cqe)
cq->tail = 0;
else
cq->tail++;
}
cq->ibcq.cqe = cqe;
cq->head = n;
cq->tail = 0;
old_wc = cq->queue;
cq->queue = wc;
spin_unlock_irq(&cq->lock);
vfree(old_wc);
ret = 0;
bail:
return ret;
}
/*
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. 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.
*/
#ifndef _IPATH_DEBUG_H
#define _IPATH_DEBUG_H
#ifndef _IPATH_DEBUGGING /* debugging enabled or not */
#define _IPATH_DEBUGGING 1
#endif
#if _IPATH_DEBUGGING
/*
* Mask values for debugging. The scheme allows us to compile out any
* of the debug tracing stuff, and if compiled in, to enable or disable
* dynamically. This can be set at modprobe time also:
* modprobe infinipath.ko infinipath_debug=7
*/
#define __IPATH_INFO 0x1 /* generic low verbosity stuff */
#define __IPATH_DBG 0x2 /* generic debug */
#define __IPATH_TRSAMPLE 0x8 /* generate trace buffer sample entries */
/* leave some low verbosity spots open */
#define __IPATH_VERBDBG 0x40 /* very verbose debug */
#define __IPATH_PKTDBG 0x80 /* print packet data */
/* print process startup (init)/exit messages */
#define __IPATH_PROCDBG 0x100
/* print mmap/nopage stuff, not using VDBG any more */
#define __IPATH_MMDBG 0x200
#define __IPATH_USER_SEND 0x1000 /* use user mode send */
#define __IPATH_KERNEL_SEND 0x2000 /* use kernel mode send */
#define __IPATH_EPKTDBG 0x4000 /* print ethernet packet data */
#define __IPATH_SMADBG 0x8000 /* sma packet debug */
#define __IPATH_IPATHDBG 0x10000 /* Ethernet (IPATH) general debug on */
#define __IPATH_IPATHWARN 0x20000 /* Ethernet (IPATH) warnings on */
#define __IPATH_IPATHERR 0x40000 /* Ethernet (IPATH) errors on */
#define __IPATH_IPATHPD 0x80000 /* Ethernet (IPATH) packet dump on */
#define __IPATH_IPATHTABLE 0x100000 /* Ethernet (IPATH) table dump on */
#else /* _IPATH_DEBUGGING */
/*
* define all of these even with debugging off, for the few places that do
* if(infinipath_debug & _IPATH_xyzzy), but in a way that will make the
* compiler eliminate the code
*/
#define __IPATH_INFO 0x0 /* generic low verbosity stuff */
#define __IPATH_DBG 0x0 /* generic debug */
#define __IPATH_TRSAMPLE 0x0 /* generate trace buffer sample entries */
#define __IPATH_VERBDBG 0x0 /* very verbose debug */
#define __IPATH_PKTDBG 0x0 /* print packet data */
#define __IPATH_PROCDBG 0x0 /* print process startup (init)/exit messages */
/* print mmap/nopage stuff, not using VDBG any more */
#define __IPATH_MMDBG 0x0
#define __IPATH_EPKTDBG 0x0 /* print ethernet packet data */
#define __IPATH_SMADBG 0x0 /* print process startup (init)/exit messages */#define __IPATH_IPATHDBG 0x0 /* Ethernet (IPATH) table dump on */
#define __IPATH_IPATHWARN 0x0 /* Ethernet (IPATH) warnings on */
#define __IPATH_IPATHERR 0x0 /* Ethernet (IPATH) errors on */
#define __IPATH_IPATHPD 0x0 /* Ethernet (IPATH) packet dump on */
#define __IPATH_IPATHTABLE 0x0 /* Ethernet (IPATH) packet dump on */
#endif /* _IPATH_DEBUGGING */
#define __IPATH_VERBOSEDBG __IPATH_VERBDBG
#endif /* _IPATH_DEBUG_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2005, 2006 PathScale, Inc. 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.
*/
#include <asm/io.h>
#include "ipath_verbs.h"
/**
* ipath_alloc_lkey - allocate an lkey
* @rkt: lkey table in which to allocate the lkey
* @mr: memory region that this lkey protects
*
* Returns 1 if successful, otherwise returns 0.
*/
int ipath_alloc_lkey(struct ipath_lkey_table *rkt, struct ipath_mregion *mr)
{
unsigned long flags;
u32 r;
u32 n;
int ret;
spin_lock_irqsave(&rkt->lock, flags);
/* Find the next available LKEY */
r = n = rkt->next;
for (;;) {
if (rkt->table[r] == NULL)
break;
r = (r + 1) & (rkt->max - 1);
if (r == n) {
spin_unlock_irqrestore(&rkt->lock, flags);
_VERBS_INFO("LKEY table full\n");
ret = 0;
goto bail;
}
}
rkt->next = (r + 1) & (rkt->max - 1);
/*
* Make sure lkey is never zero which is reserved to indicate an
* unrestricted LKEY.
*/
rkt->gen++;
mr->lkey = (r << (32 - ib_ipath_lkey_table_size)) |
((((1 << (24 - ib_ipath_lkey_table_size)) - 1) & rkt->gen)
<< 8);
if (mr->lkey == 0) {
mr->lkey |= 1 << 8;
rkt->gen++;
}
rkt->table[r] = mr;
spin_unlock_irqrestore(&rkt->lock, flags);
ret = 1;
bail:
return ret;
}
/**
* ipath_free_lkey - free an lkey
* @rkt: table from which to free the lkey
* @lkey: lkey id to free
*/
void ipath_free_lkey(struct ipath_lkey_table *rkt, u32 lkey)
{
unsigned long flags;
u32 r;
if (lkey == 0)
return;
r = lkey >> (32 - ib_ipath_lkey_table_size);
spin_lock_irqsave(&rkt->lock, flags);
rkt->table[r] = NULL;
spin_unlock_irqrestore(&rkt->lock, flags);
}
/**
* ipath_lkey_ok - check IB SGE for validity and initialize
* @rkt: table containing lkey to check SGE against
* @isge: outgoing internal SGE
* @sge: SGE to check
* @acc: access flags
*
* Return 1 if valid and successful, otherwise returns 0.
*
* Check the IB SGE for validity and initialize our internal version
* of it.
*/
int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
struct ib_sge *sge, int acc)
{
struct ipath_mregion *mr;
size_t off;
int ret;
/*
* We use LKEY == zero to mean a physical kmalloc() address.
* This is a bit of a hack since we rely on dma_map_single()
* being reversible by calling bus_to_virt().
*/
if (sge->lkey == 0) {
isge->mr = NULL;
isge->vaddr = bus_to_virt(sge->addr);
isge->length = sge->length;
isge->sge_length = sge->length;
ret = 1;
goto bail;
}
spin_lock(&rkt->lock);
mr = rkt->table[(sge->lkey >> (32 - ib_ipath_lkey_table_size))];
spin_unlock(&rkt->lock);
if (unlikely(mr == NULL || mr->lkey != sge->lkey)) {
ret = 0;
goto bail;
}
off = sge->addr - mr->user_base;
if (unlikely(sge->addr < mr->user_base ||
off + sge->length > mr->length ||
(mr->access_flags & acc) != acc)) {
ret = 0;
goto bail;
}
off += mr->offset;
isge->mr = mr;
isge->m = 0;
isge->n = 0;
while (off >= mr->map[isge->m]->segs[isge->n].length) {
off -= mr->map[isge->m]->segs[isge->n].length;
isge->n++;
if (isge->n >= IPATH_SEGSZ) {
isge->m++;
isge->n = 0;
}
}
isge->vaddr = mr->map[isge->m]->segs[isge->n].vaddr + off;
isge->length = mr->map[isge->m]->segs[isge->n].length - off;
isge->sge_length = sge->length;
ret = 1;
bail:
return ret;
}
/**
* ipath_rkey_ok - check the IB virtual address, length, and RKEY
* @dev: infiniband device
* @ss: SGE state
* @len: length of data
* @vaddr: virtual address to place data
* @rkey: rkey to check
* @acc: access flags
*
* Return 1 if successful, otherwise 0.
*
* The QP r_rq.lock should be held.
*/
int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
u32 len, u64 vaddr, u32 rkey, int acc)
{
struct ipath_lkey_table *rkt = &dev->lk_table;
struct ipath_sge *sge = &ss->sge;
struct ipath_mregion *mr;
size_t off;
int ret;
spin_lock(&rkt->lock);
mr = rkt->table[(rkey >> (32 - ib_ipath_lkey_table_size))];
spin_unlock(&rkt->lock);
if (unlikely(mr == NULL || mr->lkey != rkey)) {
ret = 0;
goto bail;
}
off = vaddr - mr->iova;
if (unlikely(vaddr < mr->iova || off + len > mr->length ||
(mr->access_flags & acc) == 0)) {
ret = 0;
goto bail;
}
off += mr->offset;
sge->mr = mr;
sge->m = 0;
sge->n = 0;
while (off >= mr->map[sge->m]->segs[sge->n].length) {
off -= mr->map[sge->m]->segs[sge->n].length;
sge->n++;
if (sge->n >= IPATH_SEGSZ) {
sge->m++;
sge->n = 0;
}
}
sge->vaddr = mr->map[sge->m]->segs[sge->n].vaddr + off;
sge->length = mr->map[sge->m]->segs[sge->n].length - off;
sge->sge_length = len;
ss->sg_list = NULL;
ss->num_sge = 1;
ret = 1;
bail:
return ret;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment