Signed-off-by: Bryan O'Sullivan <[EMAIL PROTECTED]>

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);
_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to