lkml.org 
[lkml]   [2005]   [Dec]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH 13 of 20] ipath - routines used by upper layer driver code
    Date
    From
    Signed-off-by: Bryan O'Sullivan <bos@pathscale.com>

    diff -r 5e9b0b7876e2 -r f9bcd9de3548 drivers/infiniband/hw/ipath/ipath_layer.c
    --- /dev/null Thu Jan 1 00:00:00 1970 +0000
    +++ b/drivers/infiniband/hw/ipath/ipath_layer.c Wed Dec 28 14:19:43 2005 -0800
    @@ -0,0 +1,1313 @@
    +/*
    + * 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.
    + *
    + * Patent licenses, if any, provided herein do not apply to
    + * combinations of this program with other software, or any other
    + * product whatsoever.
    + */
    +
    +/*
    + * These are the routines used by layered drivers, currently just the
    + * layered ethernet driver and verbs layer.
    + */
    +
    +#include <linux/pci.h>
    +
    +#include "ipath_kernel.h"
    +#include "ips_common.h"
    +#include "ipath_layer.h"
    +
    +/* unit number is already validated in ipath_ioctl() */
    +int ipath_kset_linkstate(uint32_t arg)
    +{
    + ipath_type unit = 0xffff & (arg >> 16);
    + uint32_t lstate;
    + struct ipath_devdata *dd;
    + int tryarmed = 0;
    +
    + if (unit >= infinipath_max ||
    + !(devdata[unit].ipath_flags & IPATH_INITTED)) {
    + _IPATH_DBG("Invalid unit %u\n", unit);
    + return -ENODEV;
    + }
    +
    + dd = &devdata[unit];
    + arg &= 0xffff;
    + switch (arg) {
    + case IPATH_IB_LINKDOWN:
    + ipath_down_link(unit); /* really moving it to idle */
    + lstate = IPATH_LINKDOWN | IPATH_LINK_SLEEPING;
    + break;
    +
    + case IPATH_IB_LINKDOWN_POLL:
    + ipath_set_ib_lstate(unit, INFINIPATH_IBCC_LINKINITCMD_POLL <<
    + INFINIPATH_IBCC_LINKINITCMD_SHIFT);
    + lstate = IPATH_LINKDOWN;
    + break;
    +
    + case IPATH_IB_LINKDOWN_DISABLE:
    + ipath_set_ib_lstate(unit, INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
    + INFINIPATH_IBCC_LINKINITCMD_SHIFT);
    + lstate = IPATH_LINKDOWN;
    + break;
    +
    + case IPATH_IB_LINKINIT:
    + ipath_set_ib_lstate(unit, INFINIPATH_IBCC_LINKCMD_INIT);
    + lstate = IPATH_LINKINIT;
    + break;
    +
    + case IPATH_IB_LINKARM:
    + ipath_set_ib_lstate(unit, INFINIPATH_IBCC_LINKCMD_ARMED);
    + lstate = IPATH_LINKARMED;
    + break;
    +
    + case IPATH_IB_LINKACTIVE:
    + /*
    + * because we sometimes go to ARMED, but then back to 0x11
    + * (initialized) before the SMA asks us to move to ACTIVE,
    + * we will try to advance state to ARMED here, if necessary
    + */
    + if (!(dd->ipath_flags &
    + (IPATH_LINKINIT | IPATH_LINKARMED | IPATH_LINKDOWN |
    + IPATH_LINK_SLEEPING | IPATH_LINKACTIVE))) {
    + /* this one is just paranoia */
    + _IPATH_DBG
    + ("don't know current state (flags 0x%x), try anyway\n",
    + dd->ipath_flags);
    + tryarmed = 1;
    +
    + }
    + if (!(dd->ipath_flags & (IPATH_LINKARMED | IPATH_LINKACTIVE)))
    + tryarmed = 1;
    + if (tryarmed) {
    + ipath_set_ib_lstate(unit,
    + INFINIPATH_IBCC_LINKCMD_ARMED);
    + /*
    + * give it up to 2 seconds to get to ARMED or
    + * ACTIVE; continue afterwards even if we fail
    + */
    + if (ipath_wait_linkstate
    + (unit, IPATH_LINKARMED | IPATH_LINKACTIVE, 2000))
    + _IPATH_VDBG
    + ("try for active, even though didn't get to ARMED\n");
    + }
    +
    + ipath_set_ib_lstate(unit, INFINIPATH_IBCC_LINKCMD_ACTIVE);
    + lstate = IPATH_LINKACTIVE;
    + break;
    +
    + default:
    + _IPATH_DBG("Unknown linkstate 0x%x requested\n", arg);
    + return -EINVAL;
    + }
    + return ipath_wait_linkstate(unit, lstate, 2000);
    +}
    +
    +/*
    + * we can handle "any" incoming size, the issue here is whether we
    + * need to restrict our outgoing size. For now, we don't do any
    + * sanity checking on this, and we don't deal with what happens to
    + * programs that are already running when the size changes.
    + * unit number is already validated in ipath_ioctl()
    + * NOTE: changing the MTU will usually cause the IBC to go back to
    + * link initialize (0x11) state...
    + */
    +int ipath_kset_mtu(uint32_t arg)
    +{
    + unsigned unit = (arg >> 16) & 0xffff;
    + uint32_t piosize;
    + int changed = 0;
    +
    + if (unit >= infinipath_max ||
    + !(devdata[unit].ipath_flags & IPATH_INITTED)) {
    + _IPATH_DBG("Invalid unit %u\n", unit);
    + return -ENODEV;
    + }
    +
    + arg &= 0xffff;
    + /*
    + * mtu is IB data payload max. It's the largest power of 2 less
    + * than piosize (or even larger, since it only really controls the
    + * largest we can receive; we can send the max of the mtu and piosize).
    + * We check that it's one of the valid IB sizes.
    + */
    + if (arg != 256 && arg != 512 && arg != 1024 && arg != 2048 &&
    + arg != 4096) {
    + _IPATH_DBG("Trying to set invalid mtu %u, failing\n", arg);
    + return -EINVAL;
    + }
    + if (devdata[unit].ipath_ibmtu == arg) {
    + return 0; /* same as current */
    + }
    +
    + piosize = devdata[unit].ipath_ibmaxlen;
    + devdata[unit].ipath_ibmtu = arg;
    +
    + /*
    + * the 128 is the max IB header size allowed for in our pio send buffers
    + * If we are reducing the MTU below that, this doesn't completely make
    + * sense, but it's OK.
    + */
    + if (arg >= (piosize - 128)) {
    + /* hasn't been changed */
    + if (piosize == devdata[unit].ipath_init_ibmaxlen)
    + _IPATH_VDBG
    + ("mtu 0x%x >= ibmaxlen hardware max, nothing to do\n",
    + arg);
    + else {
    + _IPATH_VDBG
    + ("mtu 0x%x restores ibmaxlen to full amount 0x%x\n",
    + arg, piosize);
    + devdata[unit].ipath_ibmaxlen = piosize;
    + changed = 1;
    + }
    + } else if ((arg + 128) == devdata[unit].ipath_ibmaxlen)
    + _IPATH_VDBG("ibmaxlen %x same as current, no change\n", arg);
    + else {
    + piosize = arg + 128;
    + _IPATH_VDBG("ibmaxlen was 0x%x, setting to 0x%x (mtu 0x%x)\n",
    + devdata[unit].ipath_ibmaxlen, piosize, arg);
    + devdata[unit].ipath_ibmaxlen = piosize;
    + changed = 1;
    + }
    +
    + if (changed) {
    + /*
    + * set the IBC maxpktlength to the size of our pio
    + * buffers in words
    + */
    + uint64_t ibc = devdata[unit].ipath_ibcctrl;
    + ibc &= ~(INFINIPATH_IBCC_MAXPKTLEN_MASK <<
    + INFINIPATH_IBCC_MAXPKTLEN_SHIFT);
    +
    + piosize = piosize - 2 * sizeof(uint32_t); /* ignore pbc */
    + devdata[unit].ipath_ibmaxlen = piosize;
    + piosize /= sizeof(uint32_t); /* in words */
    + /*
    + * for ICRC, which we only send in diag test pkt mode, and we
    + * don't need to worry about that for mtu
    + */
    + piosize += 1;
    +
    + ibc |= piosize << INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
    + devdata[unit].ipath_ibcctrl = ibc;
    + ipath_kput_kreg(unit, kr_ibcctrl, devdata[unit].ipath_ibcctrl);
    + }
    + return 0;
    +}
    +
    +void ipath_set_sps_lid(const ipath_type unit, uint32_t arg)
    +{
    + if (unit >= infinipath_max ||
    + !(devdata[unit].ipath_flags & IPATH_INITTED)) {
    + _IPATH_DBG("Invalid unit %u\n", unit);
    + return;
    + }
    +
    + ipath_stats.sps_lid[unit] = devdata[unit].ipath_lid = arg;
    + if (devdata[unit].ipath_layer.l_intr)
    + devdata[unit].ipath_layer.l_intr(unit, IPATH_LAYER_INT_LID);
    +}
    +
    +/* XXX - need to inform anyone who cares this just happened. */
    +int ipath_layer_set_guid(const ipath_type device, uint64_t guid)
    +{
    + if (device >= infinipath_max ||
    + !(devdata[device].ipath_flags & IPATH_INITTED)) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return -ENODEV;
    + }
    + devdata[device].ipath_guid = guid;
    + return 0;
    +}
    +
    +uint64_t ipath_layer_get_guid(const ipath_type device)
    +{
    + if (device >= infinipath_max ||
    + !(devdata[device].ipath_flags & IPATH_INITTED)) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return 0;
    + }
    + return devdata[device].ipath_guid;
    +}
    +
    +uint32_t ipath_layer_get_nguid(const ipath_type device)
    +{
    + if (device >= infinipath_max ||
    + !(devdata[device].ipath_flags & IPATH_INITTED)) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return 0;
    + }
    + return devdata[device].ipath_nguid;
    +}
    +
    +int ipath_layer_query_device(const ipath_type device, uint32_t * vendor,
    + uint32_t * boardrev, uint32_t * majrev,
    + uint32_t * minrev)
    +{
    + if (device >= infinipath_max ||
    + !(devdata[device].ipath_flags & IPATH_INITTED)) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return -ENODEV;
    + }
    +
    + *vendor = devdata[device].ipath_vendorid;
    + *boardrev = devdata[device].ipath_boardrev;
    + *majrev = devdata[device].ipath_majrev;
    + *minrev = devdata[device].ipath_minrev;
    +
    + return 0;
    +}
    +
    +uint32_t ipath_layer_get_flags(const ipath_type device)
    +{
    + if (device >= infinipath_max ||
    + !(devdata[device].ipath_flags & IPATH_INITTED)) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return 0;
    + }
    +
    + return devdata[device].ipath_flags;
    +}
    +
    +struct device *ipath_layer_get_pcidev(const ipath_type device)
    +{
    + if (device >= infinipath_max ||
    + !(devdata[device].ipath_flags & IPATH_INITTED)) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return NULL;
    + }
    +
    + return &(devdata[device].pcidev->dev);
    +}
    +
    +uint16_t ipath_layer_get_deviceid(const ipath_type device)
    +{
    + if (device >= infinipath_max ||
    + !(devdata[device].ipath_flags & IPATH_INITTED)) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return 0;
    + }
    +
    + return devdata[device].ipath_deviceid;
    +}
    +
    +uint64_t ipath_layer_get_lastibcstat(const ipath_type device)
    +{
    + if (device >= infinipath_max ||
    + !(devdata[device].ipath_flags & IPATH_INITTED)) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return 0;
    + }
    +
    + return devdata[device].ipath_lastibcstat;
    +}
    +
    +uint32_t ipath_layer_get_ibmtu(const ipath_type device)
    +{
    + if (device >= infinipath_max ||
    + !(devdata[device].ipath_flags & IPATH_INITTED)) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return 0;
    + }
    +
    + return devdata[device].ipath_ibmtu;
    +}
    +
    +int ipath_layer_register(const ipath_type device,
    + int (*l_intr) (const ipath_type, uint32_t),
    + int (*l_rcv) (const ipath_type, void *,
    + struct sk_buff *), uint16_t l_rcv_opcode,
    + int (*l_rcv_lid) (const ipath_type, void *),
    + uint16_t l_rcv_lid_opcode)
    +{
    + int ret = 0;
    +
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return 1;
    + }
    + if (!(devdata[device].ipath_flags & IPATH_INITTED)) {
    + _IPATH_VDBG("%s not yet initialized, failing\n",
    + ipath_get_unit_name(device));
    + return 1;
    + }
    +
    + _IPATH_VDBG("intr %p rx %p, rx_lid %p\n", l_intr, l_rcv, l_rcv_lid);
    + if (devdata[device].ipath_layer.l_intr
    + || devdata[device].ipath_layer.l_rcv) {
    + _IPATH_DBG
    + ("Layered device already registered on unit %u, failing\n",
    + device);
    + return 1;
    + }
    +
    + if (!(*devdata[device].ipath_statusp & IPATH_STATUS_SMA))
    + *devdata[device].ipath_statusp |= IPATH_STATUS_OIB_SMA;
    + devdata[device].ipath_layer.l_intr = l_intr;
    + devdata[device].ipath_layer.l_rcv = l_rcv;
    + devdata[device].ipath_layer.l_rcv_lid = l_rcv_lid;
    + devdata[device].ipath_layer.l_rcv_opcode = l_rcv_opcode;
    + devdata[device].ipath_layer.l_rcv_lid_opcode = l_rcv_lid_opcode;
    +
    + return ret;
    +}
    +
    +static void ipath_verbs_timer(unsigned long t)
    +{
    + /*
    + * If port 0 receive packet interrupts are not availabile,
    + * check the receive queue.
    + */
    + if (!(devdata[t].ipath_flags & IPATH_GPIO_INTR))
    + ipath_kreceive(t);
    +
    + /* Handle verbs layer timeouts. */
    + if (devdata[t].verbs_layer.l_timer_cb)
    + devdata[t].verbs_layer.l_timer_cb(t);
    +
    + mod_timer(&devdata[t].verbs_layer.l_timer, jiffies + 1);
    +}
    +
    +/* Verbs layer registration. */
    +int ipath_verbs_register(const ipath_type device,
    + int (*l_piobufavail) (const ipath_type device),
    + void (*l_rcv) (const ipath_type device, void *rhdr,
    + void *data, uint32_t tlen),
    + void (*l_timer_cb) (const ipath_type device))
    +{
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return 0;
    + }
    + if (!(devdata[device].ipath_flags & IPATH_INITTED)) {
    + _IPATH_VDBG("%s not yet initialized, failing\n",
    + ipath_get_unit_name(device));
    + return 0;
    + }
    +
    + _IPATH_VDBG("piobufavail %p rx %p\n", l_piobufavail, l_rcv);
    + if (devdata[device].verbs_layer.l_piobufavail ||
    + devdata[device].verbs_layer.l_rcv) {
    + _IPATH_DBG("Verbs layer already registered on unit %u, "
    + "failing\n", device);
    + return 0;
    + }
    +
    + devdata[device].verbs_layer.l_piobufavail = l_piobufavail;
    + devdata[device].verbs_layer.l_rcv = l_rcv;
    + devdata[device].verbs_layer.l_timer_cb = l_timer_cb;
    + devdata[device].verbs_layer.l_flags = 0;
    +
    + return 1;
    +}
    +
    +void ipath_verbs_unregister(const ipath_type device)
    +{
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return;
    + }
    + if (!(devdata[device].ipath_flags & IPATH_INITTED)) {
    + _IPATH_VDBG("%s not yet initialized, failing\n",
    + ipath_get_unit_name(device));
    + return;
    + }
    +
    + *devdata[device].ipath_statusp &= ~IPATH_STATUS_OIB_SMA;
    + devdata[device].verbs_layer.l_piobufavail = NULL;
    + devdata[device].verbs_layer.l_rcv = NULL;
    + devdata[device].verbs_layer.l_timer_cb = NULL;
    + devdata[device].verbs_layer.l_flags = 0;
    +}
    +
    +int ipath_layer_open(const ipath_type device, uint32_t * pktmax)
    +{
    + int ret = 0;
    + uint32_t intval = 0;
    +
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return 1;
    + }
    + if (!devdata[device].ipath_layer.l_intr
    + || !devdata[device].ipath_layer.l_rcv) {
    + _IPATH_DBG("layer not registered, failing\n");
    + return 1;
    + }
    +
    + if ((ret =
    + ipath_setrcvhdrsize(device, NUM_OF_EKSTRA_WORDS_IN_HEADER_QUEUE)))
    + return ret;
    +
    + *pktmax = devdata[device].ipath_ibmaxlen;
    +
    + if (*devdata[device].ipath_statusp & IPATH_STATUS_IB_READY)
    + intval |= IPATH_LAYER_INT_IF_UP;
    + if (ipath_stats.sps_lid[device])
    + intval |= IPATH_LAYER_INT_LID;
    + if (ipath_stats.sps_mlid[device])
    + intval |= IPATH_LAYER_INT_BCAST;
    + /*
    + * do this on open, in case low level is already up and
    + * just layered driver was reloaded, etc.
    + */
    + if (intval)
    + devdata[device].ipath_layer.l_intr(device, intval);
    +
    + return ret;
    +}
    +
    +uint16_t ipath_layer_get_lid(const ipath_type device)
    +{
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return 0;
    + }
    +
    + _IPATH_VDBG("returning mylid 0x%x for layered dev %d\n",
    + devdata[device].ipath_lid, device);
    + return devdata[device].ipath_lid;
    +}
    +
    +/*
    + * get the MAC address. This is the EUID-64 OUI octets (top 3), then
    + * skip the next 2 (which should both be zero or 0xff).
    + * The returned MAC is in network order
    + * mac points to at least 6 bytes of buffer
    + * returns 0 on error (to be consistent with get_lid and get_bcast
    + * return 1 on success
    + * We assume that by the time the LID is set, that the GUID is as valid
    + * as it's ever going to be, rather than adding yet another status bit.
    + */
    +
    +int ipath_layer_get_mac(const ipath_type device, uint8_t * mac)
    +{
    + uint8_t *guid;
    +
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u, failing\n", device);
    + return 0;
    + }
    + guid = (uint8_t *) & devdata[device].ipath_guid;
    +
    + mac[0] = guid[0];
    + mac[1] = guid[1];
    + mac[2] = guid[2];
    + mac[3] = guid[5];
    + mac[4] = guid[6];
    + mac[5] = guid[7];
    + if ((guid[3] || guid[4]) && !(guid[3] == 0xff && guid[4] == 0xff))
    + _IPATH_DBG("Warning, guid bytes 3 and 4 not 0 or 0xffff: %x %x\n",
    + guid[3], guid[4]);
    + _IPATH_VDBG("Returning %x:%x:%x:%x:%x:%x\n",
    + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    + return 1;
    +}
    +
    +uint16_t ipath_layer_get_bcast(const ipath_type device)
    +{
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u, failing\n", device);
    + return 0;
    + }
    +
    + _IPATH_VDBG("returning broadcast LID 0x%x for unit %u\n",
    + devdata[device].ipath_mlid, device);
    + return devdata[device].ipath_mlid;
    +}
    +
    +int ipath_layer_get_num_of_dev(void)
    +{
    + return infinipath_max;
    +}
    +
    +int ipath_layer_get_cr_errpkey(const ipath_type device)
    +{
    + return ipath_kget_creg32(device, cr_errpkey);
    +}
    +
    +void ipath_layer_close(const ipath_type device)
    +{
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return;
    + }
    + if (!devdata[device].ipath_layer.l_intr
    + || !devdata[device].ipath_layer.l_rcv) {
    + /* normal if not all chips are present */
    + _IPATH_VDBG("layer close without open\n");
    + } else {
    + devdata[device].ipath_layer.l_intr = NULL;
    + devdata[device].ipath_layer.l_rcv = NULL;
    + devdata[device].ipath_layer.l_rcv_lid = NULL;
    + devdata[device].ipath_layer.l_rcv_opcode = 0;
    + devdata[device].ipath_layer.l_rcv_lid_opcode = 0;
    + }
    +}
    +
    +static inline void copy_aligned(uint32_t __iomem *piobuf,
    + struct ipath_sge_state *ss,
    + uint32_t length)
    +{
    + struct ipath_sge *sge = &ss->sge;
    +
    + while (length) {
    + uint32_t len = sge->length;
    + uint32_t w;
    +
    + BUG_ON(len == 0);
    + if (len > length)
    + len = length;
    + /* Need to round up for the last dword in the packet. */
    + w = (len + 3) >> 2;
    + if (length == len) { /* last chunk, trigger word is special */
    + uint32_t *src32;
    + memcpy_toio32(piobuf, sge->vaddr, w-1);
    + src32 = (w-1)+(uint32_t*)sge->vaddr;
    + mb(); /* must flush early everything before trigger word */
    + writel(*src32, piobuf+w-1);
    + }
    + else
    + memcpy_toio32(piobuf, sge->vaddr, w);
    + piobuf += w;
    + sge->vaddr += len;
    + sge->length -= len;
    + sge->sge_length -= len;
    + if (sge->sge_length == 0) {
    + if (--ss->num_sge)
    + *sge = *ss->sg_list++;
    + } else if (sge->length == 0 && sge->mr != NULL) {
    + if (++sge->n >= IPATH_SEGSZ) {
    + if (++sge->m >= sge->mr->mapsz)
    + break;
    + sge->n = 0;
    + }
    + sge->vaddr = sge->mr->map[sge->m]->segs[sge->n].vaddr;
    + sge->length = sge->mr->map[sge->m]->segs[sge->n].length;
    + }
    + length -= len;
    + }
    +}
    +
    +static inline void copy_unaligned(uint32_t __iomem *piobuf,
    + struct ipath_sge_state *ss,
    + uint32_t length)
    +{
    + struct ipath_sge *sge = &ss->sge;
    + union {
    + uint8_t wbuf[4];
    + uint32_t w;
    + } u;
    + int extra = 0;
    +
    + while (length) {
    + uint32_t len = sge->length;
    +
    + BUG_ON(len == 0);
    + if (len > length)
    + len = length;
    + length -= len;
    + while (len) {
    + u.wbuf[extra++] = *(uint8_t *) sge->vaddr;
    + sge->vaddr++;
    + sge->length--;
    + sge->sge_length--;
    + if (extra >= 4) {
    + if (!length && len == 1)
    + mb(); /* flush all before the trigger word write */
    + writel(u.w, piobuf);
    + extra = 0;
    + }
    + len--;
    + }
    + if (sge->sge_length == 0) {
    + if (--ss->num_sge)
    + *sge = *ss->sg_list++;
    + } else if (sge->length == 0) {
    + if (++sge->n >= IPATH_SEGSZ) {
    + if (++sge->m >= sge->mr->mapsz)
    + break;
    + sge->n = 0;
    + }
    + sge->vaddr = sge->mr->map[sge->m]->segs[sge->n].vaddr;
    + sge->length = sge->mr->map[sge->m]->segs[sge->n].length;
    + }
    + }
    + if (extra) {
    + while (extra < 4)
    + u.wbuf[extra++] = 0;
    + mb(); /* flush all before the trigger word write */
    + writel(u.w, piobuf);
    + }
    +}
    +
    +/*
    + * This is like ipath_send_smapkt() in that we need to be able to send
    + * packets after the chip is initialized (MADs) but also like
    + * ipath_layer_send() since its used by the verbs layer.
    + */
    +int ipath_verbs_send(const ipath_type device, uint32_t hdrwords,
    + uint32_t *hdr, uint32_t len, struct ipath_sge_state *ss)
    +{
    + struct ipath_devdata *dd = &devdata[device];
    + uint32_t __iomem *piobuf;
    + uint32_t plen;
    +
    + if (device >= infinipath_max ||
    + !(dd->ipath_flags & IPATH_PRESENT) || !dd->ipath_kregbase) {
    + _IPATH_DBG("illegal unit %u\n", device);
    + return -ENODEV;
    + }
    + if (!(dd->ipath_flags & IPATH_INITTED)) {
    + /* no hardware, freeze, etc. */
    + _IPATH_DBG("unit %u not usable\n", device);
    + return -ENODEV;
    + }
    + /* +1 is for the qword padding of pbc */
    + plen = hdrwords + ((len + 3) >> 2) + 1;
    + if ((plen << 2) > dd->ipath_ibmaxlen) {
    + _IPATH_DBG("packet len 0x%x too long, failing\n", plen);
    + return -EINVAL;
    + }
    +
    + /* Get a PIO buffer to use. */
    + if (!(piobuf = ipath_getpiobuf(device, NULL)))
    + return -EBUSY;
    +
    + _IPATH_EPDBG("0x%x+1w pio %p\n", plen - 1, piobuf);
    +
    + /* Write len to control qword, no flags.
    + * we have to flush after the PBC for correctness on some cpus
    + * or WC buffer can be written out of order */
    + writeq(plen, piobuf);
    + mb();
    + piobuf += 2;
    + if (len == 0) {
    + /* if there is just the header portion, must flush before
    + * writing last word of header for correctness, and after
    + * the last header word (trigger word) */
    + memcpy_toio32(piobuf, hdr, hdrwords-1);
    + mb();
    + writel(hdr[hdrwords-1], piobuf+hdrwords-1);
    + mb();
    + return 0;
    + }
    + memcpy_toio32(piobuf, hdr, hdrwords);
    + piobuf += hdrwords;
    + /*
    + * If we really wanted to check everything, we would have to
    + * check that each segment starts on a dword boundary and is
    + * a dword multiple in length.
    + * Since there can be lots of segments, we only check for a simple
    + * common case where the amount to copy is contained in one segment.
    + */
    + if (ss->sge.length == len)
    + copy_aligned(piobuf, ss, len);
    + else
    + copy_unaligned(piobuf, ss, len);
    + mb(); /* be sure trigger word is written */
    + return 0;
    +}
    +
    +void ipath_layer_snapshot_counters(const ipath_type device, uint64_t * swords,
    + uint64_t * rwords, uint64_t * spkts, uint64_t * rpkts)
    +{
    + if (device >= infinipath_max ||
    + !(devdata[device].ipath_flags & IPATH_PRESENT)) {
    + _IPATH_DBG("illegal unit %u\n", device);
    + return;
    + }
    + if (!(devdata[device].ipath_flags & IPATH_INITTED)) {
    + /* no hardware, freeze, etc. */
    + _IPATH_DBG("unit %u not usable\n", device);
    + return;
    + }
    + *swords = ipath_snap_cntr(device, cr_wordsendcnt);
    + *rwords = ipath_snap_cntr(device, cr_wordrcvcnt);
    + *spkts = ipath_snap_cntr(device, cr_pktsendcnt);
    + *rpkts = ipath_snap_cntr(device, cr_pktrcvcnt);
    +}
    +
    +/*
    + * Return the counters needed by recv_pma_get_portcounters().
    + */
    +void ipath_layer_get_counters(const ipath_type device,
    + struct ipath_layer_counters *cntrs)
    +{
    + if (device >= infinipath_max ||
    + !(devdata[device].ipath_flags & IPATH_PRESENT)) {
    + _IPATH_DBG("illegal unit %u\n", device);
    + return;
    + }
    + if (!(devdata[device].ipath_flags & IPATH_INITTED)) {
    + /* no hardware, freeze, etc. */
    + _IPATH_DBG("unit %u not usable\n", device);
    + return;
    + }
    + cntrs->symbol_error_counter =
    + ipath_snap_cntr(device, cr_ibsymbolerrcnt);
    + cntrs->link_error_recovery_counter =
    + ipath_snap_cntr(device, cr_iblinkerrrecovcnt);
    + cntrs->link_downed_counter = ipath_snap_cntr(device, cr_iblinkdowncnt);
    + cntrs->port_rcv_errors = ipath_snap_cntr(device, cr_err_rlencnt) +
    + ipath_snap_cntr(device, cr_invalidrlencnt) +
    + ipath_snap_cntr(device, cr_erricrccnt) +
    + ipath_snap_cntr(device, cr_errvcrccnt) +
    + ipath_snap_cntr(device, cr_badformatcnt);
    + cntrs->port_rcv_remphys_errors = ipath_snap_cntr(device, cr_rcvebpcnt);
    + cntrs->port_xmit_discards = ipath_snap_cntr(device, cr_unsupvlcnt);
    + cntrs->port_xmit_data = ipath_snap_cntr(device, cr_wordsendcnt);
    + cntrs->port_rcv_data = ipath_snap_cntr(device, cr_wordrcvcnt);
    + cntrs->port_xmit_packets = ipath_snap_cntr(device, cr_pktsendcnt);
    + cntrs->port_rcv_packets = ipath_snap_cntr(device, cr_pktrcvcnt);
    +}
    +
    +void ipath_layer_want_buffer(const ipath_type device)
    +{
    + atomic_set_mask(INFINIPATH_S_PIOINTBUFAVAIL,
    + &devdata[device].ipath_sendctrl);
    + ipath_kput_kreg(device, kr_sendctrl, devdata[device].ipath_sendctrl);
    +}
    +
    +int ipath_layer_send(const ipath_type device, void *hdr, void *data,
    + uint32_t datawords)
    +{
    + int ret = 0;
    + uint32_t __iomem *piobuf;
    + uint32_t plen;
    + uint16_t vlsllnh;
    +
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u, failing\n", device);
    + return -EINVAL;
    + }
    + if (!(devdata[device].ipath_flags & IPATH_RCVHDRSZ_SET)) {
    + _IPATH_DBG("send while not open\n");
    + ret = -EINVAL;
    + } else
    + if ((devdata[device].ipath_flags & (IPATH_LINKUNK | IPATH_LINKDOWN))
    + || devdata[device].ipath_lid == 0) {
    + /* lid check is for when sma hasn't yet configured */
    + ret = -ENETDOWN;
    + _IPATH_VDBG("send while not ready, mylid=%u, flags=0x%x\n",
    + devdata[device].ipath_lid,
    + devdata[device].ipath_flags);
    + }
    + /* +1 is for the qword padding of pbc */
    + plen = (sizeof(struct ips_message_header_typ) >> 2) + datawords + 1;
    + if (plen > (devdata[device].ipath_ibmaxlen >> 2)) {
    + _IPATH_DBG("packet len 0x%x too long, failing\n", plen);
    + ret = -EINVAL;
    + }
    + vlsllnh = *((uint16_t *) hdr);
    + if (vlsllnh != htons(IPS_LRH_BTH)) {
    + _IPATH_DBG("Warning: lrh[0] wrong (%x, not %x); not sending\n",
    + vlsllnh, htons(IPS_LRH_BTH));
    + ret = -EINVAL;
    + }
    + if (ret)
    + goto done;
    +
    + /* Get a PIO buffer to use. */
    + if (!(piobuf = ipath_getpiobuf(device, NULL))) {
    + ret = -EBUSY;
    + goto done;
    + }
    +
    + _IPATH_EPDBG("0x%x+1w pio %p\n", plen - 1, piobuf);
    +
    + /* len to control qword, no flags */
    + writeq(plen, piobuf);
    + piobuf += 2;
    + memcpy_toio32(piobuf, hdr,
    + (sizeof(struct ips_message_header_typ) >> 2));
    + piobuf += (sizeof(struct ips_message_header_typ) >> 2);
    + memcpy_toio32(piobuf, data, datawords);
    +
    + ipath_stats.sps_ether_spkts++; /* another ether packet sent */
    +
    +done:
    + return ret;
    +}
    +
    +void ipath_layer_set_piointbufavail_int(const ipath_type device)
    +{
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return;
    + }
    +
    + atomic_set_mask(INFINIPATH_S_PIOINTBUFAVAIL,
    + &devdata[device].ipath_sendctrl);
    +
    + ipath_kput_kreg(device, kr_sendctrl, devdata[device].ipath_sendctrl);
    +}
    +
    +void ipath_layer_enable_timer(const ipath_type device)
    +{
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return;
    + }
    +
    + /*
    + * HT-400 has a design flaw where the chip and kernel idea
    + * of the tail register don't always agree, and therefore we won't
    + * get an interrupt on the next packet received.
    + * If the board supports per packet receive interrupts, use it.
    + * Otherwise, the timer function periodically checks for packets
    + * to cover this case.
    + * Either way, the timer is needed for verbs layer related
    + * processing.
    + */
    + if (devdata[device].ipath_flags & IPATH_GPIO_INTR) {
    + ipath_kput_kreg(device, kr_debugportselect, 0x2074076542310UL);
    + /* Enable GPIO bit 2 interrupt */
    + ipath_kput_kreg(device, kr_gpio_mask, (uint64_t)(1 << 2));
    + }
    +
    + init_timer(&devdata[device].verbs_layer.l_timer);
    + devdata[device].verbs_layer.l_timer.function = ipath_verbs_timer;
    + devdata[device].verbs_layer.l_timer.data = (unsigned long)device;
    + devdata[device].verbs_layer.l_timer.expires = jiffies + 1;
    + add_timer(&devdata[device].verbs_layer.l_timer);
    +}
    +
    +void ipath_layer_disable_timer(const ipath_type device)
    +{
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return;
    + }
    +
    + /* Disable GPIO bit 2 interrupt */
    + if (devdata[device].ipath_flags & IPATH_GPIO_INTR)
    + ipath_kput_kreg(device, kr_gpio_mask, 0);
    +
    + del_timer_sync(&devdata[device].verbs_layer.l_timer);
    +}
    +
    +/*
    + * Get the verbs layer flags.
    + */
    +unsigned ipath_verbs_get_flags(const ipath_type device)
    +{
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return 0;
    + }
    +
    + return devdata[device].verbs_layer.l_flags;
    +}
    +
    +/*
    + * Set the verbs layer flags.
    + */
    +void ipath_verbs_set_flags(const ipath_type device, unsigned flags)
    +{
    + ipath_type s;
    +
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return;
    + }
    +
    + devdata[device].verbs_layer.l_flags = flags;
    +
    + for (s = 0; s < infinipath_max; s++) {
    + if (!(devdata[s].ipath_flags & IPATH_INITTED))
    + continue;
    + if ((flags & IPATH_VERBS_KERNEL_SMA) &&
    + !(*devdata[s].ipath_statusp & IPATH_STATUS_SMA)) {
    + *devdata[s].ipath_statusp |= IPATH_STATUS_OIB_SMA;
    + } else {
    + *devdata[s].ipath_statusp &= ~IPATH_STATUS_OIB_SMA;
    + }
    + }
    +}
    +
    +/*
    + * Return the size of the PKEY table for port 0.
    + */
    +unsigned ipath_layer_get_npkeys(const ipath_type device)
    +{
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return 0;
    + }
    +
    + return ARRAY_SIZE(devdata[device].ipath_pd[0]->port_pkeys);
    +}
    +
    +/*
    + * Return the indexed PKEY from the port 0 PKEY table.
    + */
    +unsigned ipath_layer_get_pkey(const ipath_type device, unsigned index)
    +{
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return 0;
    + }
    + if (index >= ARRAY_SIZE(devdata[device].ipath_pd[0]->port_pkeys))
    + return 0;
    +
    + return devdata[device].ipath_pd[0]->port_pkeys[index];
    +}
    +
    +/*
    + * Return the PKEY table for port 0.
    + */
    +void ipath_layer_get_pkeys(const ipath_type device, uint16_t *pkeys)
    +{
    + struct ipath_portdata *pd;
    +
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return;
    + }
    +
    + pd = devdata[device].ipath_pd[0];
    + memcpy(pkeys, pd->port_pkeys, sizeof(pd->port_pkeys));
    +}
    +
    +/*
    + * Decrecment the reference count for the given PKEY.
    + * Return true if this was the last reference and the hardware table entry
    + * needs to be changed.
    + */
    +static inline int rm_pkey(struct ipath_devdata *dd, uint16_t key)
    +{
    + int i;
    +
    + for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
    + if (dd->ipath_pkeys[i] != key)
    + continue;
    + if (atomic_dec_and_test(&dd->ipath_pkeyrefs[i])) {
    + dd->ipath_pkeys[i] = 0;
    + return 1;
    + }
    + break;
    + }
    + return 0;
    +}
    +
    +/*
    + * Add the given PKEY to the hardware table.
    + * Return an error code if unable to add the entry, zero if no change,
    + * or 1 if the hardware PKEY register needs to be updated.
    + */
    +static inline int add_pkey(struct ipath_devdata *dd, uint16_t key)
    +{
    + int i;
    + uint16_t lkey = key & 0x7FFF;
    + int any = 0;
    +
    + for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
    + if (!dd->ipath_pkeys[i]) {
    + any++;
    + continue;
    + }
    + /* If it matches exactly, try to increment the ref count */
    + if (dd->ipath_pkeys[i] == key) {
    + if (atomic_inc_return(&dd->ipath_pkeyrefs[i]) > 1)
    + return 0;
    + /* Lost the race. Look for an empty slot below. */
    + atomic_dec(&dd->ipath_pkeyrefs[i]);
    + any++;
    + }
    + /*
    + * It makes no sense to have both the limited and unlimited
    + * PKEY set at the same time since the unlimited one will
    + * disable the limited one.
    + */
    + if ((dd->ipath_pkeys[i] & 0x7FFF) == lkey)
    + return -EEXIST;
    + }
    + if (!any)
    + return -EBUSY;
    + for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
    + if (!dd->ipath_pkeys[i] &&
    + atomic_inc_return(&dd->ipath_pkeyrefs[i]) == 1) {
    + /* for ipathstats, etc. */
    + ipath_stats.sps_pkeys[i] = lkey;
    + dd->ipath_pkeys[i] = key;
    + return 1;
    + }
    + }
    + return -EBUSY;
    +}
    +
    +/*
    + * Set the PKEY table for port 0.
    + */
    +int ipath_layer_set_pkeys(const ipath_type device, uint16_t *pkeys)
    +{
    + struct ipath_portdata *pd;
    + struct ipath_devdata *dd;
    + int i;
    + int changed = 0;
    +
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return -EINVAL;
    + }
    +
    + dd = &devdata[device];
    + pd = dd->ipath_pd[0];
    +
    + for (i = 0; i > ARRAY_SIZE(pd->port_pkeys); i++) {
    + uint16_t key = pkeys[i];
    + uint16_t okey = pd->port_pkeys[i];
    +
    + if (key == okey)
    + continue;
    + /*
    + * The value of this PKEY table entry is changing.
    + * Remove the old entry in the hardware's array of PKEYs.
    + */
    + if (okey & 0x7FFF)
    + changed |= rm_pkey(dd, okey);
    + if (key & 0x7FFF) {
    + int ret = add_pkey(dd, key);
    +
    + if (ret < 0)
    + key = 0;
    + else
    + changed |= ret;
    + }
    + pd->port_pkeys[i] = key;
    + }
    + if (changed) {
    + uint64_t pkey;
    +
    + pkey = (uint64_t) dd->ipath_pkeys[0] |
    + ((uint64_t) dd->ipath_pkeys[1] << 16) |
    + ((uint64_t) dd->ipath_pkeys[2] << 32) |
    + ((uint64_t) dd->ipath_pkeys[3] << 48);
    + _IPATH_VDBG("p0 new pkey reg %llx\n", pkey);
    + ipath_kput_kreg(pd->port_unit, kr_partitionkey, pkey);
    + }
    + return 0;
    +}
    +
    +/*
    + * Registers that vary with the chip implementation constants (port)
    + * use this routine.
    + */
    +uint64_t ipath_kget_kreg64_port(const ipath_type stype, ipath_kreg regno,
    + unsigned port)
    +{
    + ipath_kreg tmp =
    + (port < devdata[stype].ipath_portcnt && regno == kr_rcvhdraddr) ?
    + regno + port :
    + ((port < devdata[stype].ipath_portcnt
    + && regno == kr_rcvhdrtailaddr) ? regno + port : __kr_invalid);
    + return ipath_kget_kreg64(stype, tmp);
    +}
    +
    +/*
    + * Registers that vary with the chip implementation constants (port)
    + * use this routine.
    + */
    +void ipath_kput_kreg_port(const ipath_type stype, ipath_kreg regno,
    + unsigned port, uint64_t value)
    +{
    + ipath_kreg tmp =
    + (port < devdata[stype].ipath_portcnt && regno == kr_rcvhdraddr) ?
    + regno + port :
    + ((port < devdata[stype].ipath_portcnt
    + && regno == kr_rcvhdrtailaddr) ? regno + port : __kr_invalid);
    + ipath_kput_kreg(stype, tmp, value);
    +}
    +
    +/*
    + * Returns zero if the default is POLL, 1 if the default is SLEEP.
    + */
    +int ipath_layer_get_linkdowndefaultstate(const ipath_type device)
    +{
    + struct ipath_devdata *dd;
    +
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return -EINVAL;
    + }
    +
    + dd = &devdata[device];
    + return (dd->ipath_ibcctrl & INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE) ?
    + 1 : 0;
    +}
    +
    +/*
    + * Note that this will only take effect when the link state changes.
    + */
    +int ipath_layer_set_linkdowndefaultstate(const ipath_type device, int sleep)
    +{
    + struct ipath_devdata *dd;
    +
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return -EINVAL;
    + }
    +
    + _IPATH_DBG("state %s\n", sleep ? "SLEEP" : "POLL");
    + dd = &devdata[device];
    + if (sleep)
    + dd->ipath_ibcctrl |= INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE;
    + else
    + dd->ipath_ibcctrl &= ~INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE;
    + return 0;
    +}
    +
    +int ipath_layer_get_phyerrthreshold(const ipath_type device)
    +{
    + struct ipath_devdata *dd;
    +
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return -EINVAL;
    + }
    +
    + dd = &devdata[device];
    + return (dd->ipath_ibcctrl >> INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) &
    + INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK;
    +}
    +
    +/*
    + * Note that this will only take effect when the link state changes.
    + */
    +int ipath_layer_set_phyerrthreshold(const ipath_type device, unsigned n)
    +{
    + struct ipath_devdata *dd;
    + unsigned v;
    +
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return -EINVAL;
    + }
    +
    + dd = &devdata[device];
    + v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) &
    + INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK;
    + if (v != n) {
    + _IPATH_DBG("error threshold %u\n", n);
    + dd->ipath_ibcctrl &=
    + ~(INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK <<
    + INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT);
    + dd->ipath_ibcctrl |=
    + (uint64_t)n << INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT;
    + }
    + return 0;
    +}
    +
    +int ipath_layer_get_overrunthreshold(const ipath_type device)
    +{
    + struct ipath_devdata *dd;
    +
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return -EINVAL;
    + }
    +
    + dd = &devdata[device];
    + return (dd->ipath_ibcctrl >> INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) &
    + INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK;
    +}
    +
    +/*
    + * Note that this will only take effect when the link state changes.
    + */
    +int ipath_layer_set_overrunthreshold(const ipath_type device, unsigned n)
    +{
    + struct ipath_devdata *dd;
    + unsigned v;
    +
    + if (device >= infinipath_max) {
    + _IPATH_DBG("Invalid unit %u\n", device);
    + return -EINVAL;
    + }
    +
    + dd = &devdata[device];
    + v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) &
    + INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK;
    + if (v != n) {
    + _IPATH_DBG("overrun threshold %u\n", n);
    + dd->ipath_ibcctrl &=
    + ~(INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK <<
    + INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT);
    + dd->ipath_ibcctrl |=
    + (uint64_t)n << INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT;
    + }
    + return 0;
    +}
    +
    +EXPORT_SYMBOL(ipath_kset_linkstate);
    +EXPORT_SYMBOL(ipath_kset_mtu);
    +EXPORT_SYMBOL(ipath_layer_close);
    +EXPORT_SYMBOL(ipath_layer_get_bcast);
    +EXPORT_SYMBOL(ipath_layer_get_cr_errpkey);
    +EXPORT_SYMBOL(ipath_layer_get_deviceid);
    +EXPORT_SYMBOL(ipath_layer_get_flags);
    +EXPORT_SYMBOL(ipath_layer_get_guid);
    +EXPORT_SYMBOL(ipath_layer_get_ibmtu);
    +EXPORT_SYMBOL(ipath_layer_get_lastibcstat);
    +EXPORT_SYMBOL(ipath_layer_get_lid);
    +EXPORT_SYMBOL(ipath_layer_get_mac);
    +EXPORT_SYMBOL(ipath_layer_get_nguid);
    +EXPORT_SYMBOL(ipath_layer_get_num_of_dev);
    +EXPORT_SYMBOL(ipath_layer_get_pcidev);
    +EXPORT_SYMBOL(ipath_layer_open);
    +EXPORT_SYMBOL(ipath_layer_query_device);
    +EXPORT_SYMBOL(ipath_layer_register);
    +EXPORT_SYMBOL(ipath_layer_send);
    +EXPORT_SYMBOL(ipath_layer_set_guid);
    +EXPORT_SYMBOL(ipath_layer_set_piointbufavail_int);
    +EXPORT_SYMBOL(ipath_layer_snapshot_counters);
    +EXPORT_SYMBOL(ipath_layer_get_counters);
    +EXPORT_SYMBOL(ipath_layer_want_buffer);
    +EXPORT_SYMBOL(ipath_verbs_register);
    +EXPORT_SYMBOL(ipath_verbs_send);
    +EXPORT_SYMBOL(ipath_verbs_unregister);
    +EXPORT_SYMBOL(ipath_set_sps_lid);
    +EXPORT_SYMBOL(ipath_layer_enable_timer);
    +EXPORT_SYMBOL(ipath_layer_disable_timer);
    +EXPORT_SYMBOL(ipath_verbs_get_flags);
    +EXPORT_SYMBOL(ipath_verbs_set_flags);
    +EXPORT_SYMBOL(ipath_layer_get_npkeys);
    +EXPORT_SYMBOL(ipath_layer_get_pkey);
    +EXPORT_SYMBOL(ipath_layer_get_pkeys);
    +EXPORT_SYMBOL(ipath_layer_set_pkeys);
    +EXPORT_SYMBOL(ipath_layer_get_linkdowndefaultstate);
    +EXPORT_SYMBOL(ipath_layer_set_linkdowndefaultstate);
    +EXPORT_SYMBOL(ipath_layer_get_phyerrthreshold);
    +EXPORT_SYMBOL(ipath_layer_set_phyerrthreshold);
    +EXPORT_SYMBOL(ipath_layer_get_overrunthreshold);
    +EXPORT_SYMBOL(ipath_layer_set_overrunthreshold);
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2005-12-29 01:47    [W:0.092 / U:2.404 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site