]> err.no Git - linux-2.6/blobdiff - drivers/infiniband/hw/ipath/ipath_sdma.c
Merge branches 'at91', 'dyntick', 'ep93xx', 'iop', 'ixp', 'misc', 'orion', 'omap...
[linux-2.6] / drivers / infiniband / hw / ipath / ipath_sdma.c
index 1974df7a9f789e6e19568876f59c9a4c5f5783ae..eaba03273e4febd20ca45ce88e3b63fbd7e83f40 100644 (file)
@@ -263,14 +263,10 @@ static void sdma_abort_task(unsigned long opaque)
                hwstatus = ipath_read_kreg64(dd,
                                dd->ipath_kregs->kr_senddmastatus);
 
-               if (/* ScoreBoardDrainInProg */
-                   test_bit(63, &hwstatus) ||
-                   /* AbortInProg */
-                   test_bit(62, &hwstatus) ||
-                   /* InternalSDmaEnable */
-                   test_bit(61, &hwstatus) ||
-                   /* ScbEmpty */
-                   !test_bit(30, &hwstatus)) {
+               if ((hwstatus & (IPATH_SDMA_STATUS_SCORE_BOARD_DRAIN_IN_PROG |
+                                IPATH_SDMA_STATUS_ABORT_IN_PROG             |
+                                IPATH_SDMA_STATUS_INTERNAL_SDMA_ENABLE)) ||
+                   !(hwstatus & IPATH_SDMA_STATUS_SCB_EMPTY)) {
                        if (dd->ipath_sdma_reset_wait > 0) {
                                /* not done shutting down sdma */
                                --dd->ipath_sdma_reset_wait;
@@ -308,13 +304,15 @@ static void sdma_abort_task(unsigned long opaque)
                spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
 
                /*
-                * Don't restart sdma here. Wait until link is up to ACTIVE.
-                * VL15 MADs used to bring the link up use PIO, and multiple
-                * link transitions otherwise cause the sdma engine to be
+                * Don't restart sdma here (with the exception
+                * below). Wait until link is up to ACTIVE.  VL15 MADs
+                * used to bring the link up use PIO, and multiple link
+                * transitions otherwise cause the sdma engine to be
                 * stopped and started multiple times.
-                * The disable is done here, including the shadow, so the
-                * state is kept consistent.
-                * See ipath_restart_sdma() for the actual starting of sdma.
+                * The disable is done here, including the shadow,
+                * so the state is kept consistent.
+                * See ipath_restart_sdma() for the actual starting
+                * of sdma.
                 */
                spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
                dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE;
@@ -326,6 +324,13 @@ static void sdma_abort_task(unsigned long opaque)
                /* make sure I see next message */
                dd->ipath_sdma_abort_jiffies = 0;
 
+               /*
+                * Not everything that takes SDMA offline is a link
+                * status change.  If the link was up, restart SDMA.
+                */
+               if (dd->ipath_flags & IPATH_LINKACTIVE)
+                       ipath_restart_sdma(dd);
+
                goto done;
        }
 
@@ -336,7 +341,7 @@ resched:
         * state change
         */
        if (jiffies > dd->ipath_sdma_abort_jiffies) {
-               ipath_dbg("looping with status 0x%016llx\n",
+               ipath_dbg("looping with status 0x%08lx\n",
                          dd->ipath_sdma_status);
                dd->ipath_sdma_abort_jiffies = jiffies + 5 * HZ;
        }
@@ -427,7 +432,12 @@ int setup_sdma(struct ipath_devdata *dd)
                goto done;
        }
 
-       dd->ipath_sdma_status = 0;
+       /*
+        * Set initial status as if we had been up, then gone down.
+        * This lets initial start on transition to ACTIVE be the
+        * same as restart after link flap.
+        */
+       dd->ipath_sdma_status = IPATH_SDMA_ABORT_ABORTED;
        dd->ipath_sdma_abort_jiffies = 0;
        dd->ipath_sdma_generation = 0;
        dd->ipath_sdma_descq_tail = 0;
@@ -449,16 +459,19 @@ int setup_sdma(struct ipath_devdata *dd)
        ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmaheadaddr,
                         dd->ipath_sdma_head_phys);
 
-       /* Reserve all the former "kernel" piobufs */
-       n = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - dd->ipath_pioreserved;
-       for (i = dd->ipath_lastport_piobuf; i < n; ++i) {
+       /*
+        * Reserve all the former "kernel" piobufs, using high number range
+        * so we get as many 4K buffers as possible
+        */
+       n = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;
+       i = dd->ipath_lastport_piobuf + dd->ipath_pioreserved;
+       ipath_chg_pioavailkernel(dd, i, n - i , 0);
+       for (; i < n; ++i) {
                unsigned word = i / 64;
                unsigned bit = i & 63;
                BUG_ON(word >= 3);
                senddmabufmask[word] |= 1ULL << bit;
        }
-       ipath_chg_pioavailkernel(dd, dd->ipath_lastport_piobuf,
-               n - dd->ipath_lastport_piobuf, 0);
        ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask0,
                         senddmabufmask[0]);
        ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask1,
@@ -598,7 +611,7 @@ void ipath_restart_sdma(struct ipath_devdata *dd)
        }
        spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
        if (!needed) {
-               ipath_dbg("invalid attempt to restart SDMA, status 0x%016llx\n",
+               ipath_dbg("invalid attempt to restart SDMA, status 0x%08lx\n",
                        dd->ipath_sdma_status);
                goto bail;
        }
@@ -615,6 +628,9 @@ void ipath_restart_sdma(struct ipath_devdata *dd)
        ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
        spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
 
+       /* notify upper layers */
+       ipath_ib_piobufavail(dd->verbs_dev);
+
 bail:
        return;
 }