]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/infiniband/hw/ipath/ipath_init_chip.c
Pull ec into release branch
[linux-2.6-omap-h63xx.git] / drivers / infiniband / hw / ipath / ipath_init_chip.c
index d819cca524cd9ac2260e24ee438ac131a9273eb0..49951d5838049349df8ca39237365deb90525fbd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -133,7 +133,8 @@ static int create_port0_egr(struct ipath_devdata *dd)
                                   dd->ipath_ibmaxlen, PCI_DMA_FROMDEVICE);
                dd->ipath_f_put_tid(dd, e + (u64 __iomem *)
                                    ((char __iomem *) dd->ipath_kregbase +
-                                    dd->ipath_rcvegrbase), 0,
+                                    dd->ipath_rcvegrbase),
+                                   RCVHQ_RCV_TYPE_EAGER,
                                    dd->ipath_port0_skbinfo[e].phys);
        }
 
@@ -216,6 +217,20 @@ static int bringup_link(struct ipath_devdata *dd)
        return ret;
 }
 
+static struct ipath_portdata *create_portdata0(struct ipath_devdata *dd)
+{
+       struct ipath_portdata *pd = NULL;
+
+       pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+       if (pd) {
+               pd->port_dd = dd;
+               pd->port_cnt = 1;
+               /* The port 0 pkey table is used by the layer interface. */
+               pd->port_pkeys[0] = IPATH_DEFAULT_P_KEY;
+       }
+       return pd;
+}
+
 static int init_chip_first(struct ipath_devdata *dd,
                           struct ipath_portdata **pdp)
 {
@@ -271,20 +286,16 @@ static int init_chip_first(struct ipath_devdata *dd,
                goto done;
        }
 
-       dd->ipath_pd[0] = kzalloc(sizeof(*pd), GFP_KERNEL);
+       pd = create_portdata0(dd);
 
-       if (!dd->ipath_pd[0]) {
+       if (!pd) {
                ipath_dev_err(dd, "Unable to allocate portdata for port "
                              "0, failing\n");
                ret = -ENOMEM;
                goto done;
        }
-       pd = dd->ipath_pd[0];
-       pd->port_dd = dd;
-       pd->port_port = 0;
-       pd->port_cnt = 1;
-       /* The port 0 pkey table is used by the layer interface. */
-       pd->port_pkeys[0] = IPATH_DEFAULT_P_KEY;
+       dd->ipath_pd[0] = pd;
+
        dd->ipath_rcvtidcnt =
                ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt);
        dd->ipath_rcvtidbase =
@@ -300,7 +311,12 @@ static int init_chip_first(struct ipath_devdata *dd,
        val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiosize);
        dd->ipath_piosize2k = val & ~0U;
        dd->ipath_piosize4k = val >> 32;
-       dd->ipath_ibmtu = 4096; /* default to largest legal MTU */
+       /*
+        * Note: the chips support a maximum MTU of 4096, but the driver
+        * hasn't implemented this feature yet, so set the initial value
+        * to 2048.
+        */
+       dd->ipath_ibmtu = 2048;
        val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufcnt);
        dd->ipath_piobcnt2k = val & ~0U;
        dd->ipath_piobcnt4k = val >> 32;
@@ -330,6 +346,10 @@ static int init_chip_first(struct ipath_devdata *dd,
 
        spin_lock_init(&dd->ipath_tid_lock);
 
+       spin_lock_init(&dd->ipath_gpio_lock);
+       spin_lock_init(&dd->ipath_eep_st_lock);
+       sema_init(&dd->ipath_eep_sem, 1);
+
 done:
        *pdp = pd;
        return ret;
@@ -347,10 +367,9 @@ done:
 static int init_chip_reset(struct ipath_devdata *dd,
                           struct ipath_portdata **pdp)
 {
-       struct ipath_portdata *pd;
        u32 rtmp;
 
-       *pdp = pd = dd->ipath_pd[0];
+       *pdp = dd->ipath_pd[0];
        /* ensure chip does no sends or receives while we re-initialize */
        dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U;
        ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, 0);
@@ -591,6 +610,10 @@ static int init_housekeeping(struct ipath_devdata *dd,
                goto done;
        }
 
+
+       /* clear diagctrl register, in case diags were running and crashed */
+       ipath_write_kreg (dd, dd->ipath_kregs->kr_hwdiagctrl, 0);
+
        /* clear the initial reset flag, in case first driver load */
        ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
                         INFINIPATH_E_RESET);
@@ -633,7 +656,7 @@ static int init_housekeeping(struct ipath_devdata *dd,
        ret = dd->ipath_f_get_boardname(dd, boardn, sizeof boardn);
 
        snprintf(dd->ipath_boardversion, sizeof(dd->ipath_boardversion),
-                "Driver %u.%u, %s, InfiniPath%u %u.%u, PCI %u, "
+                "ChipABI %u.%u, %s, InfiniPath%u %u.%u, PCI %u, "
                 "SW Compat %u\n",
                 IPATH_CHIP_VERS_MAJ, IPATH_CHIP_VERS_MIN, boardn,
                 (unsigned)(dd->ipath_revision >> INFINIPATH_R_ARCH_SHIFT) &
@@ -669,6 +692,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
 {
        int ret = 0, i;
        u32 val32, kpiobufs;
+       u32 piobufs, uports;
        u64 val;
        struct ipath_portdata *pd = NULL; /* keep gcc4 happy */
        gfp_t gfp_flags = GFP_USER | __GFP_COMP;
@@ -703,16 +727,17 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
         * the in memory DMA'ed copies of the registers.  This has to
         * be done early, before we calculate lastport, etc.
         */
-       val = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;
+       piobufs = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;
        /*
         * calc number of pioavail registers, and save it; we have 2
         * bits per buffer.
         */
-       dd->ipath_pioavregs = ALIGN(val, sizeof(u64) * BITS_PER_BYTE / 2)
+       dd->ipath_pioavregs = ALIGN(piobufs, sizeof(u64) * BITS_PER_BYTE / 2)
                / (sizeof(u64) * BITS_PER_BYTE / 2);
+       uports = dd->ipath_cfgports ? dd->ipath_cfgports - 1 : 0;
        if (ipath_kpiobufs == 0) {
                /* not set by user (this is default) */
-               if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) > 128)
+               if (piobufs > 144)
                        kpiobufs = 32;
                else
                        kpiobufs = 16;
@@ -720,31 +745,25 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
        else
                kpiobufs = ipath_kpiobufs;
 
-       if (kpiobufs >
-           (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k -
-            (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT))) {
-               i = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k -
-                       (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT);
+       if (kpiobufs + (uports * IPATH_MIN_USER_PORT_BUFCNT) > piobufs) {
+               i = (int) piobufs -
+                       (int) (uports * IPATH_MIN_USER_PORT_BUFCNT);
                if (i < 0)
                        i = 0;
-               dev_info(&dd->pcidev->dev, "Allocating %d PIO bufs for "
-                        "kernel leaves too few for %d user ports "
+               dev_info(&dd->pcidev->dev, "Allocating %d PIO bufs of "
+                        "%d for kernel leaves too few for %d user ports "
                         "(%d each); using %u\n", kpiobufs,
-                        dd->ipath_cfgports - 1,
-                        IPATH_MIN_USER_PORT_BUFCNT, i);
+                        piobufs, uports, IPATH_MIN_USER_PORT_BUFCNT, i);
                /*
                 * shouldn't change ipath_kpiobufs, because could be
                 * different for different devices...
                 */
                kpiobufs = i;
        }
-       dd->ipath_lastport_piobuf =
-               dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - kpiobufs;
-       dd->ipath_pbufsport = dd->ipath_cfgports > 1
-               ? dd->ipath_lastport_piobuf / (dd->ipath_cfgports - 1)
-               : 0;
-       val32 = dd->ipath_lastport_piobuf -
-               (dd->ipath_pbufsport * (dd->ipath_cfgports - 1));
+       dd->ipath_lastport_piobuf = piobufs - kpiobufs;
+       dd->ipath_pbufsport =
+               uports ? dd->ipath_lastport_piobuf / uports : 0;
+       val32 = dd->ipath_lastport_piobuf - (dd->ipath_pbufsport * uports);
        if (val32 > 0) {
                ipath_dbg("allocating %u pbufs/port leaves %u unused, "
                          "add to kernel\n", dd->ipath_pbufsport, val32);
@@ -755,10 +774,15 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
        dd->ipath_lastpioindex = dd->ipath_lastport_piobuf;
        ipath_cdbg(VERBOSE, "%d PIO bufs for kernel out of %d total %u "
                   "each for %u user ports\n", kpiobufs,
-                  dd->ipath_piobcnt2k + dd->ipath_piobcnt4k,
-                  dd->ipath_pbufsport, dd->ipath_cfgports - 1);
+                  piobufs, dd->ipath_pbufsport, uports);
 
        dd->ipath_f_early_init(dd);
+       /*
+        * cancel any possible active sends from early driver load.
+        * Follows early_init because some chips have to initialize
+        * PIO buffers in early_init to avoid false parity errors.
+        */
+       ipath_cancel_sends(dd);
 
        /* early_init sets rcvhdrentsize and rcvhdrsize, so this must be
         * done after early_init */
@@ -840,11 +864,24 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
         * Set up the port 0 (kernel) rcvhdr q and egr TIDs.  If doing
         * re-init, the simplest way to handle this is to free
         * existing, and re-allocate.
+        * Need to re-create rest of port 0 portdata as well.
         */
        if (reinit) {
-               struct ipath_portdata *pd = dd->ipath_pd[0];
-               dd->ipath_pd[0] = NULL;
-               ipath_free_pddata(dd, pd);
+               /* Alloc and init new ipath_portdata for port0,
+                * Then free old pd. Could lead to fragmentation, but also
+                * makes later support for hot-swap easier.
+                */
+               struct ipath_portdata *npd;
+               npd = create_portdata0(dd);
+               if (npd) {
+                       ipath_free_pddata(dd, pd);
+                       dd->ipath_pd[0] = pd = npd;
+               } else {
+                       ipath_dev_err(dd, "Unable to allocate portdata for"
+                                     "  port 0, failing\n");
+                       ret = -ENOMEM;
+                       goto done;
+               }
        }
        dd->ipath_f_tidtemplate(dd);
        ret = ipath_create_rcvhdrq(dd, pd);