IB/ipath: fix for crash on module unload, if cfgports < portcnt
[pandora-kernel.git] / drivers / infiniband / hw / ipath / ipath_init_chip.c
index 2823ff9..c63de8f 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2006 QLogic, Inc. 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
@@ -35,7 +36,7 @@
 #include <linux/vmalloc.h>
 
 #include "ipath_kernel.h"
-#include "ips_common.h"
+#include "ipath_common.h"
 
 /*
  * min buffers we want to have per port, after driver
@@ -53,13 +54,19 @@ MODULE_PARM_DESC(cfgports, "Set max number of ports to use");
 
 /*
  * Number of buffers reserved for driver (layered drivers and SMA
- * send).  Reserved at end of buffer list.
+ * send).  Reserved at end of buffer list.   Initialized based on
+ * number of PIO buffers if not set via module interface.
+ * The problem with this is that it's global, but we'll use different
+ * numbers for different chip types.  So the default value is not
+ * very useful.  I've redefined it for the 1.3 release so that it's
+ * zero unless set by the user to something else, in which case we
+ * try to respect it.
  */
-static ushort ipath_kpiobufs = 32;
+static ushort ipath_kpiobufs;
 
 static int ipath_set_kpiobufs(const char *val, struct kernel_param *kp);
 
-module_param_call(kpiobufs, ipath_set_kpiobufs, param_get_uint,
+module_param_call(kpiobufs, ipath_set_kpiobufs, param_get_ushort,
                  &ipath_kpiobufs, S_IWUSR | S_IRUGO);
 MODULE_PARM_DESC(kpiobufs, "Set number of PIO buffers for driver");
 
@@ -108,6 +115,7 @@ static int create_port0_egr(struct ipath_devdata *dd)
                                      "eager TID %u\n", e);
                        while (e != 0)
                                dev_kfree_skb(skbs[--e]);
+                       vfree(skbs);
                        ret = -ENOMEM;
                        goto bail;
                }
@@ -232,7 +240,11 @@ static int init_chip_first(struct ipath_devdata *dd,
                          "only supports %u\n", ipath_cfgports,
                          dd->ipath_portcnt);
        }
-       dd->ipath_pd = kzalloc(sizeof(*dd->ipath_pd) * dd->ipath_cfgports,
+       /*
+        * Allocate full portcnt array, rather than just cfgports, because
+        * cleanup iterates across all possible ports.
+        */
+       dd->ipath_pd = kzalloc(sizeof(*dd->ipath_pd) * dd->ipath_portcnt,
                               GFP_KERNEL);
 
        if (!dd->ipath_pd) {
@@ -269,7 +281,7 @@ static int init_chip_first(struct ipath_devdata *dd,
        pd->port_port = 0;
        pd->port_cnt = 1;
        /* The port 0 pkey table is used by the layer interface. */
-       pd->port_pkeys[0] = IPS_DEFAULT_P_KEY;
+       pd->port_pkeys[0] = IPATH_DEFAULT_P_KEY;
        dd->ipath_rcvtidcnt =
                ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt);
        dd->ipath_rcvtidbase =
@@ -403,17 +415,8 @@ static int init_pioavailregs(struct ipath_devdata *dd)
        /* and its length */
        dd->ipath_freezelen = L1_CACHE_BYTES - sizeof(dd->ipath_statusp[0]);
 
-       if (dd->ipath_unit * 64 > (IPATH_PORT0_RCVHDRTAIL_SIZE - 64)) {
-               ipath_dev_err(dd, "unit %u too large for port 0 "
-                             "rcvhdrtail buffer size\n", dd->ipath_unit);
-               ret = -ENODEV;
-       }
-       else
-               ret = 0;
+       ret = 0;
 
-       /* so we can get current tail in ipath_kreceive(), per chip */
-       dd->ipath_hdrqtailptr = &ipath_port0_rcvhdrtail[
-               dd->ipath_unit * (64 / sizeof(*ipath_port0_rcvhdrtail))];
 done:
        return ret;
 }
@@ -531,8 +534,11 @@ static int init_housekeeping(struct ipath_devdata *dd,
         * Don't clear ipath_flags as 8bit mode was set before
         * entering this func. However, we do set the linkstate to
         * unknown, so we can watch for a transition.
+        * PRESENT is set because we want register reads to work,
+        * and the kernel infrastructure saw it in config space;
+        * We clear it if we have failures.
         */
-       dd->ipath_flags |= IPATH_LINKUNK;
+       dd->ipath_flags |= IPATH_LINKUNK | IPATH_PRESENT;
        dd->ipath_flags &= ~(IPATH_LINKACTIVE | IPATH_LINKARMED |
                             IPATH_LINKDOWN | IPATH_LINKINIT);
 
@@ -560,6 +566,7 @@ static int init_housekeeping(struct ipath_devdata *dd,
            || (dd->ipath_uregbase & 0xffffffff) == 0xffffffff) {
                ipath_dev_err(dd, "Register read failures from chip, "
                              "giving up initialization\n");
+               dd->ipath_flags &= ~IPATH_PRESENT;
                ret = -ENODEV;
                goto done;
        }
@@ -642,8 +649,9 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
 {
        int ret = 0, i;
        u32 val32, kpiobufs;
-       u64 val, atmp;
+       u64 val;
        struct ipath_portdata *pd = NULL; /* keep gcc4 happy */
+       gfp_t gfp_flags = GFP_USER | __GFP_COMP;
 
        ret = init_housekeeping(dd, &pd, reinit);
        if (ret)
@@ -682,16 +690,14 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
         */
        dd->ipath_pioavregs = ALIGN(val, sizeof(u64) * BITS_PER_BYTE / 2)
                / (sizeof(u64) * BITS_PER_BYTE / 2);
-       if (!ipath_kpiobufs)    /* have to have at least 1, for SMA */
-               kpiobufs = ipath_kpiobufs = 1;
-       else if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) <
-                (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT)) {
-               dev_info(&dd->pcidev->dev, "Too few PIO buffers (%u) "
-                        "for %u ports to have %u each!\n",
-                        dd->ipath_piobcnt2k + dd->ipath_piobcnt4k,
-                        dd->ipath_cfgports, IPATH_MIN_USER_PORT_BUFCNT);
-               kpiobufs = 1;   /* reserve just the minimum for SMA/ether */
-       } else
+       if (ipath_kpiobufs == 0) {
+               /* not set by user, or set explictly to default  */
+               if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) > 128)
+                       kpiobufs = 32;
+               else
+                       kpiobufs = 16;
+       }
+       else
                kpiobufs = ipath_kpiobufs;
 
        if (kpiobufs >
@@ -767,24 +773,6 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
                goto done;
        }
 
-       val = ipath_port0_rcvhdrtail_dma + dd->ipath_unit * 64;
-
-       /* verify that the alignment requirement was met */
-       ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdrtailaddr,
-                             0, val);
-       atmp = ipath_read_kreg64_port(
-               dd, dd->ipath_kregs->kr_rcvhdrtailaddr, 0);
-       if (val != atmp) {
-               ipath_dev_err(dd, "Catastrophic software error, "
-                             "RcvHdrTailAddr0 written as %llx, "
-                             "read back as %llx from %x\n",
-                             (unsigned long long) val,
-                             (unsigned long long) atmp,
-                             dd->ipath_kregs->kr_rcvhdrtailaddr);
-               ret = -EINVAL;
-               goto done;
-       }
-
        ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvbthqp, IPATH_KD_QP);
 
        /*
@@ -828,25 +816,45 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
        /* clear any interrups up to this point (ints still not enabled) */
        ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL);
 
-       ipath_stats.sps_lid[dd->ipath_unit] = dd->ipath_lid;
-
        /*
         * 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.
         */
-       if (reinit)
-               ipath_free_pddata(dd, 0, 0);
+       if (reinit) {
+               struct ipath_portdata *pd = dd->ipath_pd[0];
+               dd->ipath_pd[0] = NULL;
+               ipath_free_pddata(dd, pd);
+       }
        dd->ipath_f_tidtemplate(dd);
        ret = ipath_create_rcvhdrq(dd, pd);
-       if (!ret)
+       if (!ret) {
+               dd->ipath_hdrqtailptr =
+                       (volatile __le64 *)pd->port_rcvhdrtail_kvaddr;
                ret = create_port0_egr(dd);
+       }
        if (ret)
                ipath_dev_err(dd, "failed to allocate port 0 (kernel) "
                              "rcvhdrq and/or egr bufs\n");
        else
                enable_chip(dd, pd, reinit);
 
+
+       if (!ret && !reinit) {
+           /* used when we close a port, for DMA already in flight at close */
+               dd->ipath_dummy_hdrq = dma_alloc_coherent(
+                       &dd->pcidev->dev, pd->port_rcvhdrq_size,
+                       &dd->ipath_dummy_hdrq_phys,
+                       gfp_flags);
+               if (!dd->ipath_dummy_hdrq ) {
+                       dev_info(&dd->pcidev->dev,
+                               "Couldn't allocate 0x%lx bytes for dummy hdrq\n",
+                               pd->port_rcvhdrq_size);
+                       /* fallback to just 0'ing */
+                       dd->ipath_dummy_hdrq_phys = 0UL;
+               }
+       }
+
        /*
         * cause retrigger of pending interrupts ignored during init,
         * even if we had errors
@@ -871,7 +879,6 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
 
 done:
        if (!ret) {
-               ipath_get_guid(dd);
                *dd->ipath_statusp |= IPATH_STATUS_CHIP_PRESENT;
                if (!dd->ipath_f_intrsetup(dd)) {
                        /* now we can enable all interrupts from the chip */