diff options
Diffstat (limited to 'drivers/dma/ioat')
-rw-r--r-- | drivers/dma/ioat/dma.c | 46 | ||||
-rw-r--r-- | drivers/dma/ioat/dma.h | 11 | ||||
-rw-r--r-- | drivers/dma/ioat/dma_v2.c | 70 | ||||
-rw-r--r-- | drivers/dma/ioat/dma_v2.h | 6 | ||||
-rw-r--r-- | drivers/dma/ioat/dma_v3.c | 64 | ||||
-rw-r--r-- | drivers/dma/ioat/registers.h | 2 |
6 files changed, 90 insertions, 109 deletions
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index dcc4ab78b32b..5d0e42b263df 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c | |||
@@ -94,16 +94,12 @@ static irqreturn_t ioat_dma_do_interrupt_msix(int irq, void *data) | |||
94 | return IRQ_HANDLED; | 94 | return IRQ_HANDLED; |
95 | } | 95 | } |
96 | 96 | ||
97 | static void ioat1_cleanup_tasklet(unsigned long data); | ||
98 | |||
99 | /* common channel initialization */ | 97 | /* common channel initialization */ |
100 | void ioat_init_channel(struct ioatdma_device *device, | 98 | void ioat_init_channel(struct ioatdma_device *device, struct ioat_chan_common *chan, int idx) |
101 | struct ioat_chan_common *chan, int idx, | ||
102 | void (*timer_fn)(unsigned long), | ||
103 | void (*tasklet)(unsigned long), | ||
104 | unsigned long ioat) | ||
105 | { | 99 | { |
106 | struct dma_device *dma = &device->common; | 100 | struct dma_device *dma = &device->common; |
101 | struct dma_chan *c = &chan->common; | ||
102 | unsigned long data = (unsigned long) c; | ||
107 | 103 | ||
108 | chan->device = device; | 104 | chan->device = device; |
109 | chan->reg_base = device->reg_base + (0x80 * (idx + 1)); | 105 | chan->reg_base = device->reg_base + (0x80 * (idx + 1)); |
@@ -112,14 +108,12 @@ void ioat_init_channel(struct ioatdma_device *device, | |||
112 | list_add_tail(&chan->common.device_node, &dma->channels); | 108 | list_add_tail(&chan->common.device_node, &dma->channels); |
113 | device->idx[idx] = chan; | 109 | device->idx[idx] = chan; |
114 | init_timer(&chan->timer); | 110 | init_timer(&chan->timer); |
115 | chan->timer.function = timer_fn; | 111 | chan->timer.function = device->timer_fn; |
116 | chan->timer.data = ioat; | 112 | chan->timer.data = data; |
117 | tasklet_init(&chan->cleanup_task, tasklet, ioat); | 113 | tasklet_init(&chan->cleanup_task, device->cleanup_fn, data); |
118 | tasklet_disable(&chan->cleanup_task); | 114 | tasklet_disable(&chan->cleanup_task); |
119 | } | 115 | } |
120 | 116 | ||
121 | static void ioat1_timer_event(unsigned long data); | ||
122 | |||
123 | /** | 117 | /** |
124 | * ioat1_dma_enumerate_channels - find and initialize the device's channels | 118 | * ioat1_dma_enumerate_channels - find and initialize the device's channels |
125 | * @device: the device to be enumerated | 119 | * @device: the device to be enumerated |
@@ -155,10 +149,7 @@ static int ioat1_enumerate_channels(struct ioatdma_device *device) | |||
155 | if (!ioat) | 149 | if (!ioat) |
156 | break; | 150 | break; |
157 | 151 | ||
158 | ioat_init_channel(device, &ioat->base, i, | 152 | ioat_init_channel(device, &ioat->base, i); |
159 | ioat1_timer_event, | ||
160 | ioat1_cleanup_tasklet, | ||
161 | (unsigned long) ioat); | ||
162 | ioat->xfercap = xfercap; | 153 | ioat->xfercap = xfercap; |
163 | spin_lock_init(&ioat->desc_lock); | 154 | spin_lock_init(&ioat->desc_lock); |
164 | INIT_LIST_HEAD(&ioat->free_desc); | 155 | INIT_LIST_HEAD(&ioat->free_desc); |
@@ -532,12 +523,12 @@ ioat1_dma_prep_memcpy(struct dma_chan *c, dma_addr_t dma_dest, | |||
532 | return &desc->txd; | 523 | return &desc->txd; |
533 | } | 524 | } |
534 | 525 | ||
535 | static void ioat1_cleanup_tasklet(unsigned long data) | 526 | static void ioat1_cleanup_event(unsigned long data) |
536 | { | 527 | { |
537 | struct ioat_dma_chan *chan = (void *)data; | 528 | struct ioat_dma_chan *ioat = to_ioat_chan((void *) data); |
538 | 529 | ||
539 | ioat1_cleanup(chan); | 530 | ioat1_cleanup(ioat); |
540 | writew(IOAT_CHANCTRL_RUN, chan->base.reg_base + IOAT_CHANCTRL_OFFSET); | 531 | writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET); |
541 | } | 532 | } |
542 | 533 | ||
543 | void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags, | 534 | void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags, |
@@ -687,7 +678,7 @@ static void ioat1_cleanup(struct ioat_dma_chan *ioat) | |||
687 | 678 | ||
688 | static void ioat1_timer_event(unsigned long data) | 679 | static void ioat1_timer_event(unsigned long data) |
689 | { | 680 | { |
690 | struct ioat_dma_chan *ioat = (void *) data; | 681 | struct ioat_dma_chan *ioat = to_ioat_chan((void *) data); |
691 | struct ioat_chan_common *chan = &ioat->base; | 682 | struct ioat_chan_common *chan = &ioat->base; |
692 | 683 | ||
693 | dev_dbg(to_dev(chan), "%s: state: %lx\n", __func__, chan->state); | 684 | dev_dbg(to_dev(chan), "%s: state: %lx\n", __func__, chan->state); |
@@ -734,16 +725,17 @@ static void ioat1_timer_event(unsigned long data) | |||
734 | spin_unlock_bh(&chan->cleanup_lock); | 725 | spin_unlock_bh(&chan->cleanup_lock); |
735 | } | 726 | } |
736 | 727 | ||
737 | static enum dma_status | 728 | enum dma_status |
738 | ioat1_dma_is_complete(struct dma_chan *c, dma_cookie_t cookie, | 729 | ioat_is_dma_complete(struct dma_chan *c, dma_cookie_t cookie, |
739 | dma_cookie_t *done, dma_cookie_t *used) | 730 | dma_cookie_t *done, dma_cookie_t *used) |
740 | { | 731 | { |
741 | struct ioat_dma_chan *ioat = to_ioat_chan(c); | 732 | struct ioat_chan_common *chan = to_chan_common(c); |
733 | struct ioatdma_device *device = chan->device; | ||
742 | 734 | ||
743 | if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS) | 735 | if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS) |
744 | return DMA_SUCCESS; | 736 | return DMA_SUCCESS; |
745 | 737 | ||
746 | ioat1_cleanup(ioat); | 738 | device->cleanup_fn((unsigned long) c); |
747 | 739 | ||
748 | return ioat_is_complete(c, cookie, done, used); | 740 | return ioat_is_complete(c, cookie, done, used); |
749 | } | 741 | } |
@@ -1199,12 +1191,14 @@ int __devinit ioat1_dma_probe(struct ioatdma_device *device, int dca) | |||
1199 | device->intr_quirk = ioat1_intr_quirk; | 1191 | device->intr_quirk = ioat1_intr_quirk; |
1200 | device->enumerate_channels = ioat1_enumerate_channels; | 1192 | device->enumerate_channels = ioat1_enumerate_channels; |
1201 | device->self_test = ioat_dma_self_test; | 1193 | device->self_test = ioat_dma_self_test; |
1194 | device->timer_fn = ioat1_timer_event; | ||
1195 | device->cleanup_fn = ioat1_cleanup_event; | ||
1202 | dma = &device->common; | 1196 | dma = &device->common; |
1203 | dma->device_prep_dma_memcpy = ioat1_dma_prep_memcpy; | 1197 | dma->device_prep_dma_memcpy = ioat1_dma_prep_memcpy; |
1204 | dma->device_issue_pending = ioat1_dma_memcpy_issue_pending; | 1198 | dma->device_issue_pending = ioat1_dma_memcpy_issue_pending; |
1205 | dma->device_alloc_chan_resources = ioat1_dma_alloc_chan_resources; | 1199 | dma->device_alloc_chan_resources = ioat1_dma_alloc_chan_resources; |
1206 | dma->device_free_chan_resources = ioat1_dma_free_chan_resources; | 1200 | dma->device_free_chan_resources = ioat1_dma_free_chan_resources; |
1207 | dma->device_is_tx_complete = ioat1_dma_is_complete; | 1201 | dma->device_is_tx_complete = ioat_is_dma_complete; |
1208 | 1202 | ||
1209 | err = ioat_probe(device); | 1203 | err = ioat_probe(device); |
1210 | if (err) | 1204 | if (err) |
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index bbc3e78ef333..4f747a254074 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h | |||
@@ -61,7 +61,7 @@ | |||
61 | * @intr_quirk: interrupt setup quirk (for ioat_v1 devices) | 61 | * @intr_quirk: interrupt setup quirk (for ioat_v1 devices) |
62 | * @enumerate_channels: hw version specific channel enumeration | 62 | * @enumerate_channels: hw version specific channel enumeration |
63 | * @reset_hw: hw version specific channel (re)initialization | 63 | * @reset_hw: hw version specific channel (re)initialization |
64 | * @cleanup_tasklet: select between the v2 and v3 cleanup routines | 64 | * @cleanup_fn: select between the v2 and v3 cleanup routines |
65 | * @timer_fn: select between the v2 and v3 timer watchdog routines | 65 | * @timer_fn: select between the v2 and v3 timer watchdog routines |
66 | * @self_test: hardware version specific self test for each supported op type | 66 | * @self_test: hardware version specific self test for each supported op type |
67 | * | 67 | * |
@@ -80,7 +80,7 @@ struct ioatdma_device { | |||
80 | void (*intr_quirk)(struct ioatdma_device *device); | 80 | void (*intr_quirk)(struct ioatdma_device *device); |
81 | int (*enumerate_channels)(struct ioatdma_device *device); | 81 | int (*enumerate_channels)(struct ioatdma_device *device); |
82 | int (*reset_hw)(struct ioat_chan_common *chan); | 82 | int (*reset_hw)(struct ioat_chan_common *chan); |
83 | void (*cleanup_tasklet)(unsigned long data); | 83 | void (*cleanup_fn)(unsigned long data); |
84 | void (*timer_fn)(unsigned long data); | 84 | void (*timer_fn)(unsigned long data); |
85 | int (*self_test)(struct ioatdma_device *device); | 85 | int (*self_test)(struct ioatdma_device *device); |
86 | }; | 86 | }; |
@@ -337,10 +337,9 @@ struct dca_provider * __devinit ioat_dca_init(struct pci_dev *pdev, | |||
337 | void __iomem *iobase); | 337 | void __iomem *iobase); |
338 | unsigned long ioat_get_current_completion(struct ioat_chan_common *chan); | 338 | unsigned long ioat_get_current_completion(struct ioat_chan_common *chan); |
339 | void ioat_init_channel(struct ioatdma_device *device, | 339 | void ioat_init_channel(struct ioatdma_device *device, |
340 | struct ioat_chan_common *chan, int idx, | 340 | struct ioat_chan_common *chan, int idx); |
341 | void (*timer_fn)(unsigned long), | 341 | enum dma_status ioat_is_dma_complete(struct dma_chan *c, dma_cookie_t cookie, |
342 | void (*tasklet)(unsigned long), | 342 | dma_cookie_t *done, dma_cookie_t *used); |
343 | unsigned long ioat); | ||
344 | void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags, | 343 | void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags, |
345 | size_t len, struct ioat_dma_descriptor *hw); | 344 | size_t len, struct ioat_dma_descriptor *hw); |
346 | bool ioat_cleanup_preamble(struct ioat_chan_common *chan, | 345 | bool ioat_cleanup_preamble(struct ioat_chan_common *chan, |
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 5cc37afe2bc1..1ed5d66d7dca 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c | |||
@@ -51,48 +51,40 @@ MODULE_PARM_DESC(ioat_ring_max_alloc_order, | |||
51 | 51 | ||
52 | void __ioat2_issue_pending(struct ioat2_dma_chan *ioat) | 52 | void __ioat2_issue_pending(struct ioat2_dma_chan *ioat) |
53 | { | 53 | { |
54 | void * __iomem reg_base = ioat->base.reg_base; | 54 | struct ioat_chan_common *chan = &ioat->base; |
55 | 55 | ||
56 | ioat->pending = 0; | ||
57 | ioat->dmacount += ioat2_ring_pending(ioat); | 56 | ioat->dmacount += ioat2_ring_pending(ioat); |
58 | ioat->issued = ioat->head; | 57 | ioat->issued = ioat->head; |
59 | /* make descriptor updates globally visible before notifying channel */ | 58 | /* make descriptor updates globally visible before notifying channel */ |
60 | wmb(); | 59 | wmb(); |
61 | writew(ioat->dmacount, reg_base + IOAT_CHAN_DMACOUNT_OFFSET); | 60 | writew(ioat->dmacount, chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET); |
62 | dev_dbg(to_dev(&ioat->base), | 61 | dev_dbg(to_dev(chan), |
63 | "%s: head: %#x tail: %#x issued: %#x count: %#x\n", | 62 | "%s: head: %#x tail: %#x issued: %#x count: %#x\n", |
64 | __func__, ioat->head, ioat->tail, ioat->issued, ioat->dmacount); | 63 | __func__, ioat->head, ioat->tail, ioat->issued, ioat->dmacount); |
65 | } | 64 | } |
66 | 65 | ||
67 | void ioat2_issue_pending(struct dma_chan *chan) | 66 | void ioat2_issue_pending(struct dma_chan *c) |
68 | { | 67 | { |
69 | struct ioat2_dma_chan *ioat = to_ioat2_chan(chan); | 68 | struct ioat2_dma_chan *ioat = to_ioat2_chan(c); |
70 | 69 | ||
71 | spin_lock_bh(&ioat->ring_lock); | 70 | if (ioat2_ring_pending(ioat)) { |
72 | if (ioat->pending == 1) | 71 | spin_lock_bh(&ioat->ring_lock); |
73 | __ioat2_issue_pending(ioat); | 72 | __ioat2_issue_pending(ioat); |
74 | spin_unlock_bh(&ioat->ring_lock); | 73 | spin_unlock_bh(&ioat->ring_lock); |
74 | } | ||
75 | } | 75 | } |
76 | 76 | ||
77 | /** | 77 | /** |
78 | * ioat2_update_pending - log pending descriptors | 78 | * ioat2_update_pending - log pending descriptors |
79 | * @ioat: ioat2+ channel | 79 | * @ioat: ioat2+ channel |
80 | * | 80 | * |
81 | * set pending to '1' unless pending is already set to '2', pending == 2 | 81 | * Check if the number of unsubmitted descriptors has exceeded the |
82 | * indicates that submission is temporarily blocked due to an in-flight | 82 | * watermark. Called with ring_lock held |
83 | * reset. If we are already above the ioat_pending_level threshold then | ||
84 | * just issue pending. | ||
85 | * | ||
86 | * called with ring_lock held | ||
87 | */ | 83 | */ |
88 | static void ioat2_update_pending(struct ioat2_dma_chan *ioat) | 84 | static void ioat2_update_pending(struct ioat2_dma_chan *ioat) |
89 | { | 85 | { |
90 | if (unlikely(ioat->pending == 2)) | 86 | if (ioat2_ring_pending(ioat) > ioat_pending_level) |
91 | return; | ||
92 | else if (ioat2_ring_pending(ioat) > ioat_pending_level) | ||
93 | __ioat2_issue_pending(ioat); | 87 | __ioat2_issue_pending(ioat); |
94 | else | ||
95 | ioat->pending = 1; | ||
96 | } | 88 | } |
97 | 89 | ||
98 | static void __ioat2_start_null_desc(struct ioat2_dma_chan *ioat) | 90 | static void __ioat2_start_null_desc(struct ioat2_dma_chan *ioat) |
@@ -166,7 +158,7 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete) | |||
166 | seen_current = true; | 158 | seen_current = true; |
167 | } | 159 | } |
168 | ioat->tail += i; | 160 | ioat->tail += i; |
169 | BUG_ON(!seen_current); /* no active descs have written a completion? */ | 161 | BUG_ON(active && !seen_current); /* no active descs have written a completion? */ |
170 | 162 | ||
171 | chan->last_completion = phys_complete; | 163 | chan->last_completion = phys_complete; |
172 | if (ioat->head == ioat->tail) { | 164 | if (ioat->head == ioat->tail) { |
@@ -207,9 +199,9 @@ static void ioat2_cleanup(struct ioat2_dma_chan *ioat) | |||
207 | spin_unlock_bh(&chan->cleanup_lock); | 199 | spin_unlock_bh(&chan->cleanup_lock); |
208 | } | 200 | } |
209 | 201 | ||
210 | void ioat2_cleanup_tasklet(unsigned long data) | 202 | void ioat2_cleanup_event(unsigned long data) |
211 | { | 203 | { |
212 | struct ioat2_dma_chan *ioat = (void *) data; | 204 | struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data); |
213 | 205 | ||
214 | ioat2_cleanup(ioat); | 206 | ioat2_cleanup(ioat); |
215 | writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET); | 207 | writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET); |
@@ -291,7 +283,7 @@ static void ioat2_restart_channel(struct ioat2_dma_chan *ioat) | |||
291 | 283 | ||
292 | void ioat2_timer_event(unsigned long data) | 284 | void ioat2_timer_event(unsigned long data) |
293 | { | 285 | { |
294 | struct ioat2_dma_chan *ioat = (void *) data; | 286 | struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data); |
295 | struct ioat_chan_common *chan = &ioat->base; | 287 | struct ioat_chan_common *chan = &ioat->base; |
296 | 288 | ||
297 | spin_lock_bh(&chan->cleanup_lock); | 289 | spin_lock_bh(&chan->cleanup_lock); |
@@ -397,10 +389,7 @@ int ioat2_enumerate_channels(struct ioatdma_device *device) | |||
397 | if (!ioat) | 389 | if (!ioat) |
398 | break; | 390 | break; |
399 | 391 | ||
400 | ioat_init_channel(device, &ioat->base, i, | 392 | ioat_init_channel(device, &ioat->base, i); |
401 | device->timer_fn, | ||
402 | device->cleanup_tasklet, | ||
403 | (unsigned long) ioat); | ||
404 | ioat->xfercap_log = xfercap_log; | 393 | ioat->xfercap_log = xfercap_log; |
405 | spin_lock_init(&ioat->ring_lock); | 394 | spin_lock_init(&ioat->ring_lock); |
406 | if (device->reset_hw(&ioat->base)) { | 395 | if (device->reset_hw(&ioat->base)) { |
@@ -546,7 +535,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) | |||
546 | ioat->head = 0; | 535 | ioat->head = 0; |
547 | ioat->issued = 0; | 536 | ioat->issued = 0; |
548 | ioat->tail = 0; | 537 | ioat->tail = 0; |
549 | ioat->pending = 0; | ||
550 | ioat->alloc_order = order; | 538 | ioat->alloc_order = order; |
551 | spin_unlock_bh(&ioat->ring_lock); | 539 | spin_unlock_bh(&ioat->ring_lock); |
552 | 540 | ||
@@ -701,7 +689,7 @@ int ioat2_alloc_and_lock(u16 *idx, struct ioat2_dma_chan *ioat, int num_descs) | |||
701 | 689 | ||
702 | mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT); | 690 | mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT); |
703 | spin_unlock_bh(&chan->cleanup_lock); | 691 | spin_unlock_bh(&chan->cleanup_lock); |
704 | device->timer_fn((unsigned long) ioat); | 692 | device->timer_fn((unsigned long) &chan->common); |
705 | } else | 693 | } else |
706 | spin_unlock_bh(&chan->cleanup_lock); | 694 | spin_unlock_bh(&chan->cleanup_lock); |
707 | return -ENOMEM; | 695 | return -ENOMEM; |
@@ -785,7 +773,7 @@ void ioat2_free_chan_resources(struct dma_chan *c) | |||
785 | 773 | ||
786 | tasklet_disable(&chan->cleanup_task); | 774 | tasklet_disable(&chan->cleanup_task); |
787 | del_timer_sync(&chan->timer); | 775 | del_timer_sync(&chan->timer); |
788 | device->cleanup_tasklet((unsigned long) ioat); | 776 | device->cleanup_fn((unsigned long) c); |
789 | device->reset_hw(chan); | 777 | device->reset_hw(chan); |
790 | 778 | ||
791 | spin_lock_bh(&ioat->ring_lock); | 779 | spin_lock_bh(&ioat->ring_lock); |
@@ -815,25 +803,9 @@ void ioat2_free_chan_resources(struct dma_chan *c) | |||
815 | 803 | ||
816 | chan->last_completion = 0; | 804 | chan->last_completion = 0; |
817 | chan->completion_dma = 0; | 805 | chan->completion_dma = 0; |
818 | ioat->pending = 0; | ||
819 | ioat->dmacount = 0; | 806 | ioat->dmacount = 0; |
820 | } | 807 | } |
821 | 808 | ||
822 | enum dma_status | ||
823 | ioat2_is_complete(struct dma_chan *c, dma_cookie_t cookie, | ||
824 | dma_cookie_t *done, dma_cookie_t *used) | ||
825 | { | ||
826 | struct ioat2_dma_chan *ioat = to_ioat2_chan(c); | ||
827 | struct ioatdma_device *device = ioat->base.device; | ||
828 | |||
829 | if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS) | ||
830 | return DMA_SUCCESS; | ||
831 | |||
832 | device->cleanup_tasklet((unsigned long) ioat); | ||
833 | |||
834 | return ioat_is_complete(c, cookie, done, used); | ||
835 | } | ||
836 | |||
837 | static ssize_t ring_size_show(struct dma_chan *c, char *page) | 809 | static ssize_t ring_size_show(struct dma_chan *c, char *page) |
838 | { | 810 | { |
839 | struct ioat2_dma_chan *ioat = to_ioat2_chan(c); | 811 | struct ioat2_dma_chan *ioat = to_ioat2_chan(c); |
@@ -874,7 +846,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca) | |||
874 | 846 | ||
875 | device->enumerate_channels = ioat2_enumerate_channels; | 847 | device->enumerate_channels = ioat2_enumerate_channels; |
876 | device->reset_hw = ioat2_reset_hw; | 848 | device->reset_hw = ioat2_reset_hw; |
877 | device->cleanup_tasklet = ioat2_cleanup_tasklet; | 849 | device->cleanup_fn = ioat2_cleanup_event; |
878 | device->timer_fn = ioat2_timer_event; | 850 | device->timer_fn = ioat2_timer_event; |
879 | device->self_test = ioat_dma_self_test; | 851 | device->self_test = ioat_dma_self_test; |
880 | dma = &device->common; | 852 | dma = &device->common; |
@@ -882,7 +854,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca) | |||
882 | dma->device_issue_pending = ioat2_issue_pending; | 854 | dma->device_issue_pending = ioat2_issue_pending; |
883 | dma->device_alloc_chan_resources = ioat2_alloc_chan_resources; | 855 | dma->device_alloc_chan_resources = ioat2_alloc_chan_resources; |
884 | dma->device_free_chan_resources = ioat2_free_chan_resources; | 856 | dma->device_free_chan_resources = ioat2_free_chan_resources; |
885 | dma->device_is_tx_complete = ioat2_is_complete; | 857 | dma->device_is_tx_complete = ioat_is_dma_complete; |
886 | 858 | ||
887 | err = ioat_probe(device); | 859 | err = ioat_probe(device); |
888 | if (err) | 860 | if (err) |
diff --git a/drivers/dma/ioat/dma_v2.h b/drivers/dma/ioat/dma_v2.h index 3afad8da43cc..ef2871fd7868 100644 --- a/drivers/dma/ioat/dma_v2.h +++ b/drivers/dma/ioat/dma_v2.h | |||
@@ -47,7 +47,6 @@ extern int ioat_ring_alloc_order; | |||
47 | * @head: allocated index | 47 | * @head: allocated index |
48 | * @issued: hardware notification point | 48 | * @issued: hardware notification point |
49 | * @tail: cleanup index | 49 | * @tail: cleanup index |
50 | * @pending: lock free indicator for issued != head | ||
51 | * @dmacount: identical to 'head' except for occasionally resetting to zero | 50 | * @dmacount: identical to 'head' except for occasionally resetting to zero |
52 | * @alloc_order: log2 of the number of allocated descriptors | 51 | * @alloc_order: log2 of the number of allocated descriptors |
53 | * @ring: software ring buffer implementation of hardware ring | 52 | * @ring: software ring buffer implementation of hardware ring |
@@ -61,7 +60,6 @@ struct ioat2_dma_chan { | |||
61 | u16 tail; | 60 | u16 tail; |
62 | u16 dmacount; | 61 | u16 dmacount; |
63 | u16 alloc_order; | 62 | u16 alloc_order; |
64 | int pending; | ||
65 | struct ioat_ring_ent **ring; | 63 | struct ioat_ring_ent **ring; |
66 | spinlock_t ring_lock; | 64 | spinlock_t ring_lock; |
67 | }; | 65 | }; |
@@ -178,12 +176,10 @@ ioat2_dma_prep_memcpy_lock(struct dma_chan *c, dma_addr_t dma_dest, | |||
178 | void ioat2_issue_pending(struct dma_chan *chan); | 176 | void ioat2_issue_pending(struct dma_chan *chan); |
179 | int ioat2_alloc_chan_resources(struct dma_chan *c); | 177 | int ioat2_alloc_chan_resources(struct dma_chan *c); |
180 | void ioat2_free_chan_resources(struct dma_chan *c); | 178 | void ioat2_free_chan_resources(struct dma_chan *c); |
181 | enum dma_status ioat2_is_complete(struct dma_chan *c, dma_cookie_t cookie, | ||
182 | dma_cookie_t *done, dma_cookie_t *used); | ||
183 | void __ioat2_restart_chan(struct ioat2_dma_chan *ioat); | 179 | void __ioat2_restart_chan(struct ioat2_dma_chan *ioat); |
184 | bool reshape_ring(struct ioat2_dma_chan *ioat, int order); | 180 | bool reshape_ring(struct ioat2_dma_chan *ioat, int order); |
185 | void __ioat2_issue_pending(struct ioat2_dma_chan *ioat); | 181 | void __ioat2_issue_pending(struct ioat2_dma_chan *ioat); |
186 | void ioat2_cleanup_tasklet(unsigned long data); | 182 | void ioat2_cleanup_event(unsigned long data); |
187 | void ioat2_timer_event(unsigned long data); | 183 | void ioat2_timer_event(unsigned long data); |
188 | int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo); | 184 | int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo); |
189 | int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo); | 185 | int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo); |
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index 9908c9e94b2d..26febc56dab1 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c | |||
@@ -293,17 +293,25 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete) | |||
293 | } | 293 | } |
294 | } | 294 | } |
295 | ioat->tail += i; | 295 | ioat->tail += i; |
296 | BUG_ON(!seen_current); /* no active descs have written a completion? */ | 296 | BUG_ON(active && !seen_current); /* no active descs have written a completion? */ |
297 | chan->last_completion = phys_complete; | 297 | chan->last_completion = phys_complete; |
298 | if (ioat->head == ioat->tail) { | 298 | |
299 | active = ioat2_ring_active(ioat); | ||
300 | if (active == 0) { | ||
299 | dev_dbg(to_dev(chan), "%s: cancel completion timeout\n", | 301 | dev_dbg(to_dev(chan), "%s: cancel completion timeout\n", |
300 | __func__); | 302 | __func__); |
301 | clear_bit(IOAT_COMPLETION_PENDING, &chan->state); | 303 | clear_bit(IOAT_COMPLETION_PENDING, &chan->state); |
302 | mod_timer(&chan->timer, jiffies + IDLE_TIMEOUT); | 304 | mod_timer(&chan->timer, jiffies + IDLE_TIMEOUT); |
303 | } | 305 | } |
306 | /* 5 microsecond delay per pending descriptor */ | ||
307 | writew(min((5 * active), IOAT_INTRDELAY_MASK), | ||
308 | chan->device->reg_base + IOAT_INTRDELAY_OFFSET); | ||
304 | } | 309 | } |
305 | 310 | ||
306 | static void ioat3_cleanup(struct ioat2_dma_chan *ioat) | 311 | /* try to cleanup, but yield (via spin_trylock) to incoming submissions |
312 | * with the expectation that we will immediately poll again shortly | ||
313 | */ | ||
314 | static void ioat3_cleanup_poll(struct ioat2_dma_chan *ioat) | ||
307 | { | 315 | { |
308 | struct ioat_chan_common *chan = &ioat->base; | 316 | struct ioat_chan_common *chan = &ioat->base; |
309 | unsigned long phys_complete; | 317 | unsigned long phys_complete; |
@@ -329,29 +337,41 @@ static void ioat3_cleanup(struct ioat2_dma_chan *ioat) | |||
329 | spin_unlock_bh(&chan->cleanup_lock); | 337 | spin_unlock_bh(&chan->cleanup_lock); |
330 | } | 338 | } |
331 | 339 | ||
332 | static void ioat3_cleanup_tasklet(unsigned long data) | 340 | /* run cleanup now because we already delayed the interrupt via INTRDELAY */ |
341 | static void ioat3_cleanup_sync(struct ioat2_dma_chan *ioat) | ||
342 | { | ||
343 | struct ioat_chan_common *chan = &ioat->base; | ||
344 | unsigned long phys_complete; | ||
345 | |||
346 | prefetch(chan->completion); | ||
347 | |||
348 | spin_lock_bh(&chan->cleanup_lock); | ||
349 | if (!ioat_cleanup_preamble(chan, &phys_complete)) { | ||
350 | spin_unlock_bh(&chan->cleanup_lock); | ||
351 | return; | ||
352 | } | ||
353 | spin_lock_bh(&ioat->ring_lock); | ||
354 | |||
355 | __cleanup(ioat, phys_complete); | ||
356 | |||
357 | spin_unlock_bh(&ioat->ring_lock); | ||
358 | spin_unlock_bh(&chan->cleanup_lock); | ||
359 | } | ||
360 | |||
361 | static void ioat3_cleanup_event(unsigned long data) | ||
333 | { | 362 | { |
334 | struct ioat2_dma_chan *ioat = (void *) data; | 363 | struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data); |
335 | 364 | ||
336 | ioat3_cleanup(ioat); | 365 | ioat3_cleanup_sync(ioat); |
337 | writew(IOAT_CHANCTRL_RUN | IOAT3_CHANCTRL_COMPL_DCA_EN, | 366 | writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET); |
338 | ioat->base.reg_base + IOAT_CHANCTRL_OFFSET); | ||
339 | } | 367 | } |
340 | 368 | ||
341 | static void ioat3_restart_channel(struct ioat2_dma_chan *ioat) | 369 | static void ioat3_restart_channel(struct ioat2_dma_chan *ioat) |
342 | { | 370 | { |
343 | struct ioat_chan_common *chan = &ioat->base; | 371 | struct ioat_chan_common *chan = &ioat->base; |
344 | unsigned long phys_complete; | 372 | unsigned long phys_complete; |
345 | u32 status; | ||
346 | |||
347 | status = ioat_chansts(chan); | ||
348 | if (is_ioat_active(status) || is_ioat_idle(status)) | ||
349 | ioat_suspend(chan); | ||
350 | while (is_ioat_active(status) || is_ioat_idle(status)) { | ||
351 | status = ioat_chansts(chan); | ||
352 | cpu_relax(); | ||
353 | } | ||
354 | 373 | ||
374 | ioat2_quiesce(chan, 0); | ||
355 | if (ioat_cleanup_preamble(chan, &phys_complete)) | 375 | if (ioat_cleanup_preamble(chan, &phys_complete)) |
356 | __cleanup(ioat, phys_complete); | 376 | __cleanup(ioat, phys_complete); |
357 | 377 | ||
@@ -360,7 +380,7 @@ static void ioat3_restart_channel(struct ioat2_dma_chan *ioat) | |||
360 | 380 | ||
361 | static void ioat3_timer_event(unsigned long data) | 381 | static void ioat3_timer_event(unsigned long data) |
362 | { | 382 | { |
363 | struct ioat2_dma_chan *ioat = (void *) data; | 383 | struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data); |
364 | struct ioat_chan_common *chan = &ioat->base; | 384 | struct ioat_chan_common *chan = &ioat->base; |
365 | 385 | ||
366 | spin_lock_bh(&chan->cleanup_lock); | 386 | spin_lock_bh(&chan->cleanup_lock); |
@@ -426,7 +446,7 @@ ioat3_is_complete(struct dma_chan *c, dma_cookie_t cookie, | |||
426 | if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS) | 446 | if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS) |
427 | return DMA_SUCCESS; | 447 | return DMA_SUCCESS; |
428 | 448 | ||
429 | ioat3_cleanup(ioat); | 449 | ioat3_cleanup_poll(ioat); |
430 | 450 | ||
431 | return ioat_is_complete(c, cookie, done, used); | 451 | return ioat_is_complete(c, cookie, done, used); |
432 | } | 452 | } |
@@ -1239,11 +1259,11 @@ int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) | |||
1239 | 1259 | ||
1240 | if (is_raid_device) { | 1260 | if (is_raid_device) { |
1241 | dma->device_is_tx_complete = ioat3_is_complete; | 1261 | dma->device_is_tx_complete = ioat3_is_complete; |
1242 | device->cleanup_tasklet = ioat3_cleanup_tasklet; | 1262 | device->cleanup_fn = ioat3_cleanup_event; |
1243 | device->timer_fn = ioat3_timer_event; | 1263 | device->timer_fn = ioat3_timer_event; |
1244 | } else { | 1264 | } else { |
1245 | dma->device_is_tx_complete = ioat2_is_complete; | 1265 | dma->device_is_tx_complete = ioat_is_dma_complete; |
1246 | device->cleanup_tasklet = ioat2_cleanup_tasklet; | 1266 | device->cleanup_fn = ioat2_cleanup_event; |
1247 | device->timer_fn = ioat2_timer_event; | 1267 | device->timer_fn = ioat2_timer_event; |
1248 | } | 1268 | } |
1249 | 1269 | ||
diff --git a/drivers/dma/ioat/registers.h b/drivers/dma/ioat/registers.h index e8ae63baf588..1391798542b6 100644 --- a/drivers/dma/ioat/registers.h +++ b/drivers/dma/ioat/registers.h | |||
@@ -60,7 +60,7 @@ | |||
60 | #define IOAT_PERPORTOFFSET_OFFSET 0x0A /* 16-bit */ | 60 | #define IOAT_PERPORTOFFSET_OFFSET 0x0A /* 16-bit */ |
61 | 61 | ||
62 | #define IOAT_INTRDELAY_OFFSET 0x0C /* 16-bit */ | 62 | #define IOAT_INTRDELAY_OFFSET 0x0C /* 16-bit */ |
63 | #define IOAT_INTRDELAY_INT_DELAY_MASK 0x3FFF /* Interrupt Delay Time */ | 63 | #define IOAT_INTRDELAY_MASK 0x3FFF /* Interrupt Delay Time */ |
64 | #define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalescing Supported */ | 64 | #define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalescing Supported */ |
65 | 65 | ||
66 | #define IOAT_DEVICE_STATUS_OFFSET 0x0E /* 16-bit */ | 66 | #define IOAT_DEVICE_STATUS_OFFSET 0x0E /* 16-bit */ |