Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / drivers / infiniband / hw / ipath / ipath_kernel.h
index 12194f3..4cc0f95 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _IPATH_KERNEL_H
 #define _IPATH_KERNEL_H
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -41,7 +41,9 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
+#include <linux/mutex.h>
 #include <asm/io.h>
+#include <rdma/ib_verbs.h>
 
 #include "ipath_common.h"
 #include "ipath_debug.h"
 extern struct infinipath_stats ipath_stats;
 
 #define IPATH_CHIP_SWVERSION IPATH_CHIP_VERS_MAJ
+/*
+ * First-cut critierion for "device is active" is
+ * two thousand dwords combined Tx, Rx traffic per
+ * 5-second interval. SMA packets are 64 dwords,
+ * and occur "a few per second", presumably each way.
+ */
+#define IPATH_TRAFFIC_ACTIVE_THRESHOLD (2000)
+/*
+ * Struct used to indicate which errors are logged in each of the
+ * error-counters that are logged to EEPROM. A counter is incremented
+ * _once_ (saturating at 255) for each event with any bits set in
+ * the error or hwerror register masks below.
+ */
+#define IPATH_EEP_LOG_CNT (4)
+struct ipath_eep_log_mask {
+       u64 errs_to_log;
+       u64 hwerrs_to_log;
+};
 
 struct ipath_portdata {
        void **port_rcvegrbuf;
@@ -109,6 +129,8 @@ struct ipath_portdata {
        u32 port_tidcursor;
        /* next expected TID to check */
        unsigned long port_flag;
+       /* what happened */
+       unsigned long int_flag;
        /* WAIT_RCV that timed out, no interrupt */
        u32 port_rcvwait_to;
        /* WAIT_PIO that timed out, no interrupt */
@@ -119,8 +141,20 @@ struct ipath_portdata {
        u32 port_pionowait;
        /* total number of rcvhdrqfull errors */
        u32 port_hdrqfull;
+       /*
+        * Used to suppress multiple instances of same
+        * port staying stuck at same point.
+        */
+       u32 port_lastrcvhdrqtail;
+       /* saved total number of rcvhdrqfull errors for poll edge trigger */
+       u32 port_hdrqfull_poll;
+       /* total number of polled urgent packets */
+       u32 port_urgent;
+       /* saved total number of polled urgent packets for poll edge trigger */
+       u32 port_urgent_poll;
        /* pid of process using this port */
        pid_t port_pid;
+       pid_t port_subpid[INFINIPATH_MAX_SUBPORT];
        /* same size as task_struct .comm[] */
        char port_comm[16];
        /* pkeys set by this use of this port */
@@ -137,6 +171,10 @@ struct ipath_portdata {
        u32 userversion;
        /* Bitmask of active slaves */
        u32 active_slaves;
+       /* Type of packets or conditions we want to poll for */
+       u16 poll_type;
+       /* port rcvhdrq head offset */
+       u32 port_head;
 };
 
 struct sk_buff;
@@ -153,6 +191,22 @@ struct ipath_skbinfo {
        dma_addr_t phys;
 };
 
+/*
+ * Possible IB config parameters for ipath_f_get/set_ib_cfg()
+ */
+#define IPATH_IB_CFG_LIDLMC 0 /* Get/set LID (LS16b) and Mask (MS16b) */
+#define IPATH_IB_CFG_HRTBT 1 /* Get/set Heartbeat off/enable/auto */
+#define IPATH_IB_HRTBT_ON 3 /* Heartbeat enabled, sent every 100msec */
+#define IPATH_IB_HRTBT_OFF 0 /* Heartbeat off */
+#define IPATH_IB_CFG_LWID_ENB 2 /* Get/set allowed Link-width */
+#define IPATH_IB_CFG_LWID 3 /* Get currently active Link-width */
+#define IPATH_IB_CFG_SPD_ENB 4 /* Get/set allowed Link speeds */
+#define IPATH_IB_CFG_SPD 5 /* Get current Link spd */
+#define IPATH_IB_CFG_RXPOL_ENB 6 /* Get/set Auto-RX-polarity enable */
+#define IPATH_IB_CFG_LREV_ENB 7 /* Get/set Auto-Lane-reversal enable */
+#define IPATH_IB_CFG_LINKLATENCY 8 /* Get Auto-Lane-reversal enable */
+
+
 struct ipath_devdata {
        struct list_head ipath_list;
 
@@ -193,6 +247,8 @@ struct ipath_devdata {
        struct _ipath_layer ipath_layer;
        /* setup intr */
        int (*ipath_f_intrsetup)(struct ipath_devdata *);
+       /* fallback to alternate interrupt type if possible */
+       int (*ipath_f_intr_fallback)(struct ipath_devdata *);
        /* setup on-chip bus config */
        int (*ipath_f_bus)(struct ipath_devdata *, struct pci_dev *);
        /* hard reset chip */
@@ -215,6 +271,18 @@ struct ipath_devdata {
        int (*ipath_f_get_base_info)(struct ipath_portdata *, void *);
        /* free irq */
        void (*ipath_f_free_irq)(struct ipath_devdata *);
+       struct ipath_message_header *(*ipath_f_get_msgheader)
+                                       (struct ipath_devdata *, __le32 *);
+       void (*ipath_f_config_ports)(struct ipath_devdata *, ushort);
+       int (*ipath_f_get_ib_cfg)(struct ipath_devdata *, int);
+       int (*ipath_f_set_ib_cfg)(struct ipath_devdata *, int, u32);
+       void (*ipath_f_config_jint)(struct ipath_devdata *, u16 , u16);
+       void (*ipath_f_read_counters)(struct ipath_devdata *,
+                                       struct infinipath_counters *);
+       void (*ipath_f_xgxs_reset)(struct ipath_devdata *);
+       /* per chip actions needed for IB Link up/down changes */
+       int (*ipath_f_ib_updown)(struct ipath_devdata *, int, u64);
+
        struct ipath_ibdev *verbs_dev;
        struct timer_list verbs_timer;
        /* total dwords sent (summed from counter) */
@@ -239,18 +307,10 @@ struct ipath_devdata {
         * limiting of hwerror reporting
         */
        ipath_err_t ipath_lasthwerror;
-       /*
-        * errors masked because they occur too fast, also includes errors
-        * that are always ignored (ipath_ignorederrs)
-        */
+       /* errors masked because they occur too fast */
        ipath_err_t ipath_maskederrs;
        /* time in jiffies at which to re-enable maskederrs */
        unsigned long ipath_unmasktime;
-       /*
-        * errors always ignored (masked), at least for a given
-        * chip/device, because they are wrong or not useful
-        */
-       ipath_err_t ipath_ignorederrs;
        /* count of egrfull errors, combined for all ports */
        u64 ipath_last_tidfull;
        /* for ipath_qcheck() */
@@ -275,6 +335,8 @@ struct ipath_devdata {
        u32 ipath_lastport_piobuf;
        /* is a stats timer active */
        u32 ipath_stats_timer_active;
+       /* number of interrupts for this device -- saturates... */
+       u32 ipath_int_counter;
        /* dwords sent read from counter */
        u32 ipath_lastsword;
        /* dwords received read from counter */
@@ -290,21 +352,11 @@ struct ipath_devdata {
         * supports, less gives more pio bufs/port, etc.
         */
        u32 ipath_cfgports;
-       /* port0 rcvhdrq head offset */
-       u32 ipath_port0head;
        /* count of port 0 hdrqfull errors */
        u32 ipath_p0_hdrqfull;
+       /* port 0 number of receive eager buffers */
+       u32 ipath_p0_rcvegrcnt;
 
-       /*
-        * (*cfgports) used to suppress multiple instances of same
-        * port staying stuck at same point
-        */
-       u32 *ipath_lastrcvhdrqtails;
-       /*
-        * (*cfgports) used to suppress multiple instances of same
-        * port staying stuck at same point
-        */
-       u32 *ipath_lastegrheads;
        /*
         * index of last piobuffer we used.  Speeds up searching, by
         * starting at this point.  Doesn't matter if multiple cpu's use and
@@ -344,14 +396,15 @@ struct ipath_devdata {
        unsigned long ipath_wc_len;
        /* ref count for each pkey */
        atomic_t ipath_pkeyrefs[4];
-       /* shadow copy of all exptids physaddr; used only by funcsim */
-       u64 *ipath_tidsimshadow;
        /* shadow copy of struct page *'s for exp tid pages */
        struct page **ipath_pageshadow;
        /* shadow copy of dma handles for exp tid pages */
        dma_addr_t *ipath_physshadow;
-       /* lock to workaround chip bug 9437 */
+       u64 __iomem *ipath_egrtidbase;
+       /* lock to workaround chip bug 9437 and others */
+       spinlock_t ipath_kernel_tid_lock;
        spinlock_t ipath_tid_lock;
+       spinlock_t ipath_sendctrl_lock;
 
        /*
         * IPATH_STATUS_*,
@@ -369,12 +422,11 @@ struct ipath_devdata {
        struct class_device *diag_class_dev;
        /* timer used to prevent stats overflow, error throttling, etc. */
        struct timer_list ipath_stats_timer;
-       /* check for stale messages in rcv queue */
-       /* only allow one intr at a time. */
-       unsigned long ipath_rcv_pending;
        void *ipath_dummy_hdrq; /* used after port close */
        dma_addr_t ipath_dummy_hdrq_phys;
 
+       unsigned long ipath_ureg_align; /* user register alignment */
+
        /*
         * Shadow copies of registers; size indicates read access size.
         * Most of them are readonly, but some are write-only register,
@@ -399,6 +451,8 @@ struct ipath_devdata {
        u64 ipath_gpio_out;
        /* shadow the gpio mask register */
        u64 ipath_gpio_mask;
+       /* shadow the gpio output enable, etc... */
+       u64 ipath_extctrl;
        /* kr_revision shadow */
        u64 ipath_revision;
        /*
@@ -413,6 +467,7 @@ struct ipath_devdata {
        u64 ipath_lastibcstat;
        /* hwerrmask shadow */
        ipath_err_t ipath_hwerrmask;
+       ipath_err_t ipath_errormask; /* errormask shadow */
        /* interrupt config reg shadow */
        u64 ipath_intconfig;
        /* kr_sendpiobufbase value */
@@ -433,8 +488,6 @@ struct ipath_devdata {
        unsigned long ipath_rcvctrl;
        /* shadow kr_sendctrl */
        unsigned long ipath_sendctrl;
-       /* ports waiting for PIOavail intr */
-       unsigned long ipath_portpiowait;
        unsigned long ipath_lastcancel; /* to not count armlaunch after cancel */
 
        /* value we put in kr_rcvhdrcnt */
@@ -473,8 +526,6 @@ struct ipath_devdata {
        u32 ipath_cregbase;
        /* shadow the control register contents */
        u32 ipath_control;
-       /* shadow the gpio output contents */
-       u32 ipath_extctrl;
        /* PCI revision register (HTC rev on FPGA) */
        u32 ipath_pcirev;
 
@@ -529,12 +580,26 @@ struct ipath_devdata {
        u8 ipath_minrev;
        /* board rev, from ipath_revision */
        u8 ipath_boardrev;
+
+       u8 ipath_r_portenable_shift;
+       u8 ipath_r_intravail_shift;
+       u8 ipath_r_tailupd_shift;
+       u8 ipath_r_portcfg_shift;
+
        /* unit # of this chip, if present */
        int ipath_unit;
        /* saved for restore after reset */
        u8 ipath_pci_cacheline;
        /* LID mask control */
        u8 ipath_lmc;
+       /* link width supported */
+       u8 ipath_link_width_supported;
+       /* link speed supported */
+       u8 ipath_link_speed_supported;
+       u8 ipath_link_width_enabled;
+       u8 ipath_link_speed_enabled;
+       u8 ipath_link_width_active;
+       u8 ipath_link_speed_active;
        /* Rx Polarity inversion (compensate for ~tx on partner) */
        u8 ipath_rx_pol_inv;
 
@@ -552,6 +617,9 @@ struct ipath_devdata {
        u32 ipath_overrun_thresh_errs;
        u32 ipath_lli_errs;
 
+       /* status check work */
+       struct delayed_work status_work;
+
        /*
         * Not all devices managed by a driver instance are the same
         * type, so these fields must be per-device.
@@ -566,6 +634,8 @@ struct ipath_devdata {
         */
        u32 ipath_i_rcvavail_mask;
        u32 ipath_i_rcvurg_mask;
+       u16 ipath_i_rcvurg_shift;
+       u16 ipath_i_rcvavail_shift;
 
        /*
         * Register bits for selecting i2c direction and values, used for
@@ -575,6 +645,64 @@ struct ipath_devdata {
        u16 ipath_gpio_scl_num;
        u64 ipath_gpio_sda;
        u64 ipath_gpio_scl;
+
+       /* lock for doing RMW of shadows/regs for ExtCtrl and GPIO */
+       spinlock_t ipath_gpio_lock;
+
+       /*
+        * IB link and linktraining states and masks that vary per chip in
+        * some way.  Set at init, to avoid each IB status change interrupt
+        */
+       u8 ibcs_ls_shift;
+       u8 ibcs_lts_mask;
+       u32 ibcs_mask;
+       u32 ib_init;
+       u32 ib_arm;
+       u32 ib_active;
+
+       u16 ipath_rhf_offset; /* offset of RHF within receive header entry */
+
+       /*
+        * shift/mask for linkcmd, linkinitcmd, maxpktlen in ibccontol
+        * reg. Changes for IBA7220
+        */
+       u8 ibcc_lic_mask; /* LinkInitCmd */
+       u8 ibcc_lc_shift; /* LinkCmd */
+       u8 ibcc_mpl_shift; /* Maxpktlen */
+
+       u8 delay_mult;
+
+       /* used to override LED behavior */
+       u8 ipath_led_override;  /* Substituted for normal value, if non-zero */
+       u16 ipath_led_override_timeoff; /* delta to next timer event */
+       u8 ipath_led_override_vals[2]; /* Alternates per blink-frame */
+       u8 ipath_led_override_phase; /* Just counts, LSB picks from vals[] */
+       atomic_t ipath_led_override_timer_active;
+       /* Used to flash LEDs in override mode */
+       struct timer_list ipath_led_override_timer;
+
+       /* Support (including locks) for EEPROM logging of errors and time */
+       /* control access to actual counters, timer */
+       spinlock_t ipath_eep_st_lock;
+       /* control high-level access to EEPROM */
+       struct mutex ipath_eep_lock;
+       /* Below inc'd by ipath_snap_cntrs(), locked by ipath_eep_st_lock */
+       uint64_t ipath_traffic_wds;
+       /* active time is kept in seconds, but logged in hours */
+       atomic_t ipath_active_time;
+       /* Below are nominal shadow of EEPROM, new since last EEPROM update */
+       uint8_t ipath_eep_st_errs[IPATH_EEP_LOG_CNT];
+       uint8_t ipath_eep_st_new_errs[IPATH_EEP_LOG_CNT];
+       uint16_t ipath_eep_hrs;
+       /*
+        * masks for which bits of errs, hwerrs that cause
+        * each of the counters to increment.
+        */
+       struct ipath_eep_log_mask ipath_eep_st_masks[IPATH_EEP_LOG_CNT];
+
+       /* interrupt mitigation reload register info */
+       u16 ipath_jint_idle_ticks;      /* idle clock ticks */
+       u16 ipath_jint_max_packets;     /* max packets across all ports */
 };
 
 /* Private data for file operations */
@@ -592,6 +720,7 @@ int ipath_enable_wc(struct ipath_devdata *dd);
 void ipath_disable_wc(struct ipath_devdata *dd);
 int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp);
 void ipath_shutdown_device(struct ipath_devdata *);
+void ipath_clear_freeze(struct ipath_devdata *);
 
 struct file_operations;
 int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
@@ -627,13 +756,14 @@ int ipath_unordered_wc(void);
 
 void ipath_disarm_piobufs(struct ipath_devdata *, unsigned first,
                          unsigned cnt);
+void ipath_cancel_sends(struct ipath_devdata *, int);
 
 int ipath_create_rcvhdrq(struct ipath_devdata *, struct ipath_portdata *);
 void ipath_free_pddata(struct ipath_devdata *, struct ipath_portdata *);
 
 int ipath_parse_ushort(const char *str, unsigned short *valp);
 
-void ipath_kreceive(struct ipath_devdata *);
+void ipath_kreceive(struct ipath_portdata *);
 int ipath_setrcvhdrsize(struct ipath_devdata *, unsigned);
 int ipath_reset_device(int);
 void ipath_get_faststats(unsigned long);
@@ -641,6 +771,8 @@ int ipath_set_linkstate(struct ipath_devdata *, u8);
 int ipath_set_mtu(struct ipath_devdata *, u16);
 int ipath_set_lid(struct ipath_devdata *, u32, u8);
 int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
+void ipath_enable_armlaunch(struct ipath_devdata *);
+void ipath_disable_armlaunch(struct ipath_devdata *);
 
 /* for use in system calls, where we want to know device type, etc. */
 #define port_fp(fp) ((struct ipath_filedata *)(fp)->private_data)->pd
@@ -674,6 +806,8 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
 #define IPATH_LINKACTIVE    0x200
                /* link current state is unknown */
 #define IPATH_LINKUNK       0x400
+               /* Write combining flush needed for PIO */
+#define IPATH_PIO_FLUSH_WC  0x1000
                /* no IB cable, or no device on IB cable */
 #define IPATH_NOCABLE       0x4000
                /* Supports port zero per packet receive interrupts via
@@ -685,10 +819,15 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
                 * are 64bit */
 #define IPATH_32BITCOUNTERS 0x20000
                /* can miss port0 rx interrupts */
-#define IPATH_POLL_RX_INTR  0x40000
+               /* Interrupt register is 64 bits */
+#define IPATH_INTREG_64     0x40000
 #define IPATH_DISABLED      0x80000 /* administratively disabled */
                /* Use GPIO interrupts for new counters */
 #define IPATH_GPIO_ERRINTRS 0x100000
+#define IPATH_SWAP_PIOBUFS  0x200000
+               /* Suppress heartbeat, even if turning off loopback */
+#define IPATH_NO_HRTBT      0x1000000
+#define IPATH_HAS_MULT_IB_SPEED 0x8000000
 
 /* Bits in GPIO for the added interrupts */
 #define IPATH_GPIO_PORT0_BIT 2
@@ -700,56 +839,37 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
 /* portdata flag bit offsets */
                /* waiting for a packet to arrive */
 #define IPATH_PORT_WAITING_RCV   2
-               /* waiting for a PIO buffer to be available */
-#define IPATH_PORT_WAITING_PIO   3
                /* master has not finished initializing */
 #define IPATH_PORT_MASTER_UNINIT 4
+               /* waiting for an urgent packet to arrive */
+#define IPATH_PORT_WAITING_URG 5
 
 /* free up any allocated data at closes */
 void ipath_free_data(struct ipath_portdata *dd);
-int ipath_waitfor_mdio_cmdready(struct ipath_devdata *);
-int ipath_waitfor_complete(struct ipath_devdata *, ipath_kreg, u64, u64 *);
 u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *);
 void ipath_init_iba6120_funcs(struct ipath_devdata *);
 void ipath_init_iba6110_funcs(struct ipath_devdata *);
 void ipath_get_eeprom_info(struct ipath_devdata *);
+int ipath_update_eeprom_log(struct ipath_devdata *dd);
+void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr);
 u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg);
-void ipath_disarm_senderrbufs(struct ipath_devdata *, int);
+void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev);
+
+/*
+ * Set LED override, only the two LSBs have "public" meaning, but
+ * any non-zero value substitutes them for the Link and LinkTrain
+ * LED states.
+ */
+#define IPATH_LED_PHYS 1 /* Physical (linktraining) GREEN LED */
+#define IPATH_LED_LOG 2  /* Logical (link) YELLOW LED */
+void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val);
 
 /*
  * number of words used for protocol header if not set by ipath_userinit();
  */
 #define IPATH_DFLT_RCVHDRSIZE 9
 
-#define IPATH_MDIO_CMD_WRITE   1
-#define IPATH_MDIO_CMD_READ    2
-#define IPATH_MDIO_CLD_DIV     25      /* to get 2.5 Mhz mdio clock */
-#define IPATH_MDIO_CMDVALID    0x40000000      /* bit 30 */
-#define IPATH_MDIO_DATAVALID   0x80000000      /* bit 31 */
-#define IPATH_MDIO_CTRL_STD    0x0
-
-static inline u64 ipath_mdio_req(int cmd, int dev, int reg, int data)
-{
-       return (((u64) IPATH_MDIO_CLD_DIV) << 32) |
-               (cmd << 26) |
-               (dev << 21) |
-               (reg << 16) |
-               (data & 0xFFFF);
-}
-
-               /* signal and fifo status, in bank 31 */
-#define IPATH_MDIO_CTRL_XGXS_REG_8  0x8
-               /* controls loopback, redundancy */
-#define IPATH_MDIO_CTRL_8355_REG_1  0x10
-               /* premph, encdec, etc. */
-#define IPATH_MDIO_CTRL_8355_REG_2  0x11
-               /* Kchars, etc. */
-#define IPATH_MDIO_CTRL_8355_REG_6  0x15
-#define IPATH_MDIO_CTRL_8355_REG_9  0x18
-#define IPATH_MDIO_CTRL_8355_REG_10 0x1D
-
 int ipath_get_user_pages(unsigned long, size_t, struct page **);
-int ipath_get_user_pages_nocopy(unsigned long, struct page **);
 void ipath_release_user_pages(struct page **, size_t);
 void ipath_release_user_pages_on_close(struct page **, size_t);
 int ipath_eeprom_read(struct ipath_devdata *, u8, void *, int);
@@ -793,7 +913,7 @@ static inline u32 ipath_read_ureg32(const struct ipath_devdata *dd,
        return readl(regno + (u64 __iomem *)
                     (dd->ipath_uregbase +
                      (char __iomem *)dd->ipath_kregbase +
-                     dd->ipath_palign * port));
+                     dd->ipath_ureg_align * port));
 }
 
 /**
@@ -810,7 +930,7 @@ static inline void ipath_write_ureg(const struct ipath_devdata *dd,
 {
        u64 __iomem *ubase = (u64 __iomem *)
                (dd->ipath_uregbase + (char __iomem *) dd->ipath_kregbase +
-                dd->ipath_palign * port);
+                dd->ipath_ureg_align * port);
        if (dd->ipath_kregbase)
                writeq(value, &ubase[regno]);
 }
@@ -860,6 +980,53 @@ static inline u32 ipath_read_creg32(const struct ipath_devdata *dd,
                      (char __iomem *)dd->ipath_kregbase));
 }
 
+static inline void ipath_write_creg(const struct ipath_devdata *dd,
+                                   ipath_creg regno, u64 value)
+{
+       if (dd->ipath_kregbase)
+               writeq(value, regno + (u64 __iomem *)
+                      (dd->ipath_cregbase +
+                       (char __iomem *)dd->ipath_kregbase));
+}
+
+static inline void ipath_clear_rcvhdrtail(const struct ipath_portdata *pd)
+{
+       *((u64 *) pd->port_rcvhdrtail_kvaddr) = 0ULL;
+}
+
+static inline u32 ipath_get_rcvhdrtail(const struct ipath_portdata *pd)
+{
+       return (u32) le64_to_cpu(*((volatile __le64 *)
+                               pd->port_rcvhdrtail_kvaddr));
+}
+
+static inline u64 ipath_read_ireg(const struct ipath_devdata *dd, ipath_kreg r)
+{
+       return (dd->ipath_flags & IPATH_INTREG_64) ?
+               ipath_read_kreg64(dd, r) : ipath_read_kreg32(dd, r);
+}
+
+/*
+ * from contents of IBCStatus (or a saved copy), return linkstate
+ * Report ACTIVE_DEFER as ACTIVE, because we treat them the same
+ * everywhere, anyway (and should be, for almost all purposes).
+ */
+static inline u32 ipath_ib_linkstate(struct ipath_devdata *dd, u64 ibcs)
+{
+       u32 state = (u32)(ibcs >> dd->ibcs_ls_shift) &
+               INFINIPATH_IBCS_LINKSTATE_MASK;
+       if (state == INFINIPATH_IBCS_L_STATE_ACT_DEFER)
+               state = INFINIPATH_IBCS_L_STATE_ACTIVE;
+       return state;
+}
+
+/* from contents of IBCStatus (or a saved copy), return linktrainingstate */
+static inline u32 ipath_ib_linktrstate(struct ipath_devdata *dd, u64 ibcs)
+{
+       return (u32)(ibcs >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+               dd->ibcs_lts_mask;
+}
+
 /*
  * sysfs interface.
  */
@@ -868,8 +1035,7 @@ struct device_driver;
 
 extern const char ib_ipath_version[];
 
-int ipath_driver_create_group(struct device_driver *);
-void ipath_driver_remove_group(struct device_driver *);
+extern struct attribute_group *ipath_driver_attr_groups[];
 
 int ipath_device_create_group(struct device *, struct ipath_devdata *);
 void ipath_device_remove_group(struct device *, struct ipath_devdata *);