ioat: preserve chanctrl bits when re-arming interrupts
[linux-2.6.git] / drivers / dma / ioat / dma_v2.c
index 58881860f400116290f32c5e127232fb0bcf75bd..2f34f290041ef81a1f441d4d5c5151cc23edd181 100644 (file)
@@ -200,8 +200,7 @@ static void ioat2_reset_channel(struct ioat2_dma_chan *ioat)
                return;
 
        chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
-       chansts = (chan->completion_virt->low
-                                       & IOAT_CHANSTS_DMA_TRANSFER_STATUS);
+       chansts = *chan->completion & IOAT_CHANSTS_DMA_TRANSFER_STATUS;
        if (chanerr) {
                dev_err(to_dev(chan),
                        "chan%d, CHANSTS = 0x%08x CHANERR = 0x%04x, clearing\n",
@@ -281,7 +280,7 @@ static void ioat2_cleanup(struct ioat2_dma_chan *ioat)
        int i;
        struct dma_async_tx_descriptor *tx;
 
-       prefetch(chan->completion_virt);
+       prefetch(chan->completion);
 
        spin_lock_bh(&chan->cleanup_lock);
        phys_complete = ioat_get_current_completion(chan);
@@ -342,8 +341,7 @@ static void ioat2_cleanup_tasklet(unsigned long data)
        struct ioat2_dma_chan *ioat = (void *) data;
 
        ioat2_cleanup(ioat);
-       writew(IOAT_CHANCTRL_INT_DISABLE,
-              ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
+       writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
 /**
@@ -360,7 +358,14 @@ static int ioat2_enumerate_channels(struct ioatdma_device *device)
 
        INIT_LIST_HEAD(&dma->channels);
        dma->chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET);
+       dma->chancnt &= 0x1f; /* bits [4:0] valid */
+       if (dma->chancnt > ARRAY_SIZE(device->idx)) {
+               dev_warn(dev, "(%d) exceeds max supported channels (%zu)\n",
+                        dma->chancnt, ARRAY_SIZE(device->idx));
+               dma->chancnt = ARRAY_SIZE(device->idx);
+       }
        xfercap_log = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
+       xfercap_log &= 0x1f; /* bits [4:0] valid */
        if (xfercap_log == 0)
                return 0;
        dev_dbg(dev, "%s: xfercap = %d\n", __func__, 1 << xfercap_log);
@@ -448,7 +453,6 @@ static int ioat2_alloc_chan_resources(struct dma_chan *c)
        struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
        struct ioat_chan_common *chan = &ioat->base;
        struct ioat_ring_ent **ring;
-       u16 chanctrl;
        u32 chanerr;
        int descs;
        int i;
@@ -458,9 +462,7 @@ static int ioat2_alloc_chan_resources(struct dma_chan *c)
                return 1 << ioat->alloc_order;
 
        /* Setup register to interrupt and write completion status on error */
-       chanctrl = IOAT_CHANCTRL_ERR_INT_EN | IOAT_CHANCTRL_ANY_ERR_ABORT_EN |
-                  IOAT_CHANCTRL_ERR_COMPLETION_EN;
-       writew(chanctrl, chan->reg_base + IOAT_CHANCTRL_OFFSET);
+       writew(IOAT_CHANCTRL_RUN, chan->reg_base + IOAT_CHANCTRL_OFFSET);
 
        chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
        if (chanerr) {
@@ -470,17 +472,15 @@ static int ioat2_alloc_chan_resources(struct dma_chan *c)
 
        /* allocate a completion writeback area */
        /* doing 2 32bit writes to mmio since 1 64b write doesn't work */
-       chan->completion_virt = pci_pool_alloc(chan->device->completion_pool,
-                                              GFP_KERNEL,
-                                              &chan->completion_addr);
-       if (!chan->completion_virt)
+       chan->completion = pci_pool_alloc(chan->device->completion_pool,
+                                         GFP_KERNEL, &chan->completion_dma);
+       if (!chan->completion)
                return -ENOMEM;
 
-       memset(chan->completion_virt, 0,
-              sizeof(*chan->completion_virt));
-       writel(((u64) chan->completion_addr) & 0x00000000FFFFFFFF,
+       memset(chan->completion, 0, sizeof(*chan->completion));
+       writel(((u64) chan->completion_dma) & 0x00000000FFFFFFFF,
               chan->reg_base + IOAT_CHANCMP_OFFSET_LOW);
-       writel(((u64) chan->completion_addr) >> 32,
+       writel(((u64) chan->completion_dma) >> 32,
               chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
 
        ioat->alloc_order = ioat_get_alloc_order();
@@ -655,12 +655,12 @@ static void ioat2_free_chan_resources(struct dma_chan *c)
        ioat->ring = NULL;
        ioat->alloc_order = 0;
        pci_pool_free(ioatdma_device->completion_pool,
-                     chan->completion_virt,
-                     chan->completion_addr);
+                     chan->completion,
+                     chan->completion_dma);
        spin_unlock_bh(&ioat->ring_lock);
 
        chan->last_completion = 0;
-       chan->completion_addr = 0;
+       chan->completion_dma = 0;
        ioat->pending = 0;
        ioat->dmacount = 0;
        chan->watchdog_completion = 0;