aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSiva Yerramreddy <yshivakrishna@gmail.com>2014-07-11 17:04:23 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-07-11 21:31:12 -0400
commitd4ef098e4cd836b3726781eabe064d7010b6eaa8 (patch)
tree6d5eab0949f4cbc3552847a4ce874cb92a117379
parentb8e439f48a19e5832c08b4656a3a8ebb1f4b05f8 (diff)
misc: mic: add dma support in host driver
This patch adds a dma device on the mic virtual bus and uses this dmaengine to transfer data for virtio devices Reviewed-by: Nikhil Rao <nikhil.rao@intel.com> Signed-off-by: Sudeep Dutt <sudeep.dutt@intel.com> Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com> Signed-off-by: Siva Yerramreddy <yshivakrishna@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/misc/mic/Kconfig2
-rw-r--r--drivers/misc/mic/host/mic_boot.c83
-rw-r--r--drivers/misc/mic/host/mic_device.h24
-rw-r--r--drivers/misc/mic/host/mic_intr.h3
-rw-r--r--drivers/misc/mic/host/mic_virtio.c181
-rw-r--r--drivers/misc/mic/host/mic_virtio.h21
-rw-r--r--drivers/misc/mic/host/mic_x100.c8
7 files changed, 281 insertions, 41 deletions
diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig
index ee1d2ac3cd09..bf76313dab16 100644
--- a/drivers/misc/mic/Kconfig
+++ b/drivers/misc/mic/Kconfig
@@ -19,7 +19,7 @@ comment "Intel MIC Host Driver"
19 19
20config INTEL_MIC_HOST 20config INTEL_MIC_HOST
21 tristate "Intel MIC Host Driver" 21 tristate "Intel MIC Host Driver"
22 depends on 64BIT && PCI && X86 22 depends on 64BIT && PCI && X86 && INTEL_MIC_BUS
23 select VHOST_RING 23 select VHOST_RING
24 help 24 help
25 This enables Host Driver support for the Intel Many Integrated 25 This enables Host Driver support for the Intel Many Integrated
diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c
index b75c6b5cc20f..ff2b0fb1a6be 100644
--- a/drivers/misc/mic/host/mic_boot.c
+++ b/drivers/misc/mic/host/mic_boot.c
@@ -23,11 +23,70 @@
23#include <linux/pci.h> 23#include <linux/pci.h>
24 24
25#include <linux/mic_common.h> 25#include <linux/mic_common.h>
26#include <linux/mic_bus.h>
26#include "../common/mic_dev.h" 27#include "../common/mic_dev.h"
27#include "mic_device.h" 28#include "mic_device.h"
28#include "mic_smpt.h" 29#include "mic_smpt.h"
29#include "mic_virtio.h" 30#include "mic_virtio.h"
30 31
32static inline struct mic_device *mbdev_to_mdev(struct mbus_device *mbdev)
33{
34 return dev_get_drvdata(mbdev->dev.parent);
35}
36
37static dma_addr_t
38mic_dma_map_page(struct device *dev, struct page *page,
39 unsigned long offset, size_t size, enum dma_data_direction dir,
40 struct dma_attrs *attrs)
41{
42 void *va = phys_to_virt(page_to_phys(page)) + offset;
43 struct mic_device *mdev = dev_get_drvdata(dev->parent);
44
45 return mic_map_single(mdev, va, size);
46}
47
48static void
49mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
50 size_t size, enum dma_data_direction dir,
51 struct dma_attrs *attrs)
52{
53 struct mic_device *mdev = dev_get_drvdata(dev->parent);
54 mic_unmap_single(mdev, dma_addr, size);
55}
56
57static struct dma_map_ops mic_dma_ops = {
58 .map_page = mic_dma_map_page,
59 .unmap_page = mic_dma_unmap_page,
60};
61
62static struct mic_irq *
63_mic_request_threaded_irq(struct mbus_device *mbdev,
64 irq_handler_t handler, irq_handler_t thread_fn,
65 const char *name, void *data, int intr_src)
66{
67 return mic_request_threaded_irq(mbdev_to_mdev(mbdev), handler,
68 thread_fn, name, data,
69 intr_src, MIC_INTR_DMA);
70}
71
72static void _mic_free_irq(struct mbus_device *mbdev,
73 struct mic_irq *cookie, void *data)
74{
75 return mic_free_irq(mbdev_to_mdev(mbdev), cookie, data);
76}
77
78static void _mic_ack_interrupt(struct mbus_device *mbdev, int num)
79{
80 struct mic_device *mdev = mbdev_to_mdev(mbdev);
81 mdev->ops->intr_workarounds(mdev);
82}
83
84static struct mbus_hw_ops mbus_hw_ops = {
85 .request_threaded_irq = _mic_request_threaded_irq,
86 .free_irq = _mic_free_irq,
87 .ack_interrupt = _mic_ack_interrupt,
88};
89
31/** 90/**
32 * mic_reset - Reset the MIC device. 91 * mic_reset - Reset the MIC device.
33 * @mdev: pointer to mic_device instance 92 * @mdev: pointer to mic_device instance
@@ -95,9 +154,21 @@ retry:
95 */ 154 */
96 goto retry; 155 goto retry;
97 } 156 }
157 mdev->dma_mbdev = mbus_register_device(mdev->sdev->parent,
158 MBUS_DEV_DMA_HOST, &mic_dma_ops,
159 &mbus_hw_ops, mdev->mmio.va);
160 if (IS_ERR(mdev->dma_mbdev)) {
161 rc = PTR_ERR(mdev->dma_mbdev);
162 goto unlock_ret;
163 }
164 mdev->dma_ch = mic_request_dma_chan(mdev);
165 if (!mdev->dma_ch) {
166 rc = -ENXIO;
167 goto dma_remove;
168 }
98 rc = mdev->ops->load_mic_fw(mdev, buf); 169 rc = mdev->ops->load_mic_fw(mdev, buf);
99 if (rc) 170 if (rc)
100 goto unlock_ret; 171 goto dma_release;
101 mic_smpt_restore(mdev); 172 mic_smpt_restore(mdev);
102 mic_intr_restore(mdev); 173 mic_intr_restore(mdev);
103 mdev->intr_ops->enable_interrupts(mdev); 174 mdev->intr_ops->enable_interrupts(mdev);
@@ -105,6 +176,11 @@ retry:
105 mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32); 176 mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
106 mdev->ops->send_firmware_intr(mdev); 177 mdev->ops->send_firmware_intr(mdev);
107 mic_set_state(mdev, MIC_ONLINE); 178 mic_set_state(mdev, MIC_ONLINE);
179 goto unlock_ret;
180dma_release:
181 dma_release_channel(mdev->dma_ch);
182dma_remove:
183 mbus_unregister_device(mdev->dma_mbdev);
108unlock_ret: 184unlock_ret:
109 mutex_unlock(&mdev->mic_mutex); 185 mutex_unlock(&mdev->mic_mutex);
110 return rc; 186 return rc;
@@ -122,6 +198,11 @@ void mic_stop(struct mic_device *mdev, bool force)
122 mutex_lock(&mdev->mic_mutex); 198 mutex_lock(&mdev->mic_mutex);
123 if (MIC_OFFLINE != mdev->state || force) { 199 if (MIC_OFFLINE != mdev->state || force) {
124 mic_virtio_reset_devices(mdev); 200 mic_virtio_reset_devices(mdev);
201 if (mdev->dma_ch) {
202 dma_release_channel(mdev->dma_ch);
203 mdev->dma_ch = NULL;
204 }
205 mbus_unregister_device(mdev->dma_mbdev);
125 mic_bootparam_init(mdev); 206 mic_bootparam_init(mdev);
126 mic_reset(mdev); 207 mic_reset(mdev);
127 if (MIC_RESET_FAILED == mdev->state) 208 if (MIC_RESET_FAILED == mdev->state)
diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h
index 0398c696d257..016bd15a7bd1 100644
--- a/drivers/misc/mic/host/mic_device.h
+++ b/drivers/misc/mic/host/mic_device.h
@@ -25,6 +25,8 @@
25#include <linux/idr.h> 25#include <linux/idr.h>
26#include <linux/notifier.h> 26#include <linux/notifier.h>
27#include <linux/irqreturn.h> 27#include <linux/irqreturn.h>
28#include <linux/dmaengine.h>
29#include <linux/mic_bus.h>
28 30
29#include "mic_intr.h" 31#include "mic_intr.h"
30 32
@@ -87,6 +89,8 @@ enum mic_stepping {
87 * @cdev: Character device for MIC. 89 * @cdev: Character device for MIC.
88 * @vdev_list: list of virtio devices. 90 * @vdev_list: list of virtio devices.
89 * @pm_notifier: Handles PM notifications from the OS. 91 * @pm_notifier: Handles PM notifications from the OS.
92 * @dma_mbdev: MIC BUS DMA device.
93 * @dma_ch: DMA channel reserved by this driver for use by virtio devices.
90 */ 94 */
91struct mic_device { 95struct mic_device {
92 struct mic_mw mmio; 96 struct mic_mw mmio;
@@ -124,6 +128,8 @@ struct mic_device {
124 struct cdev cdev; 128 struct cdev cdev;
125 struct list_head vdev_list; 129 struct list_head vdev_list;
126 struct notifier_block pm_notifier; 130 struct notifier_block pm_notifier;
131 struct mbus_device *dma_mbdev;
132 struct dma_chan *dma_ch;
127}; 133};
128 134
129/** 135/**
@@ -144,6 +150,7 @@ struct mic_device {
144 * @load_mic_fw: Load firmware segments required to boot the card 150 * @load_mic_fw: Load firmware segments required to boot the card
145 * into card memory. This includes the kernel, command line, ramdisk etc. 151 * into card memory. This includes the kernel, command line, ramdisk etc.
146 * @get_postcode: Get post code status from firmware. 152 * @get_postcode: Get post code status from firmware.
153 * @dma_filter: DMA filter function to be used.
147 */ 154 */
148struct mic_hw_ops { 155struct mic_hw_ops {
149 u8 aper_bar; 156 u8 aper_bar;
@@ -159,6 +166,7 @@ struct mic_hw_ops {
159 void (*send_firmware_intr)(struct mic_device *mdev); 166 void (*send_firmware_intr)(struct mic_device *mdev);
160 int (*load_mic_fw)(struct mic_device *mdev, const char *buf); 167 int (*load_mic_fw)(struct mic_device *mdev, const char *buf);
161 u32 (*get_postcode)(struct mic_device *mdev); 168 u32 (*get_postcode)(struct mic_device *mdev);
169 bool (*dma_filter)(struct dma_chan *chan, void *param);
162}; 170};
163 171
164/** 172/**
@@ -187,6 +195,22 @@ mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
187 iowrite32(val, mw->va + offset); 195 iowrite32(val, mw->va + offset);
188} 196}
189 197
198static inline struct dma_chan *mic_request_dma_chan(struct mic_device *mdev)
199{
200 dma_cap_mask_t mask;
201 struct dma_chan *chan;
202
203 dma_cap_zero(mask);
204 dma_cap_set(DMA_MEMCPY, mask);
205 chan = dma_request_channel(mask, mdev->ops->dma_filter,
206 mdev->sdev->parent);
207 if (chan)
208 return chan;
209 dev_err(mdev->sdev->parent, "%s %d unable to acquire channel\n",
210 __func__, __LINE__);
211 return NULL;
212}
213
190void mic_sysfs_init(struct mic_device *mdev); 214void mic_sysfs_init(struct mic_device *mdev);
191int mic_start(struct mic_device *mdev, const char *buf); 215int mic_start(struct mic_device *mdev, const char *buf);
192void mic_stop(struct mic_device *mdev, bool force); 216void mic_stop(struct mic_device *mdev, bool force);
diff --git a/drivers/misc/mic/host/mic_intr.h b/drivers/misc/mic/host/mic_intr.h
index b1334dd9a0a1..9f783d4ad7f1 100644
--- a/drivers/misc/mic/host/mic_intr.h
+++ b/drivers/misc/mic/host/mic_intr.h
@@ -27,8 +27,9 @@
27 * The minimum number of msix vectors required for normal operation. 27 * The minimum number of msix vectors required for normal operation.
28 * 3 for virtio network, console and block devices. 28 * 3 for virtio network, console and block devices.
29 * 1 for card shutdown notifications. 29 * 1 for card shutdown notifications.
30 * 4 for host owned DMA channels.
30 */ 31 */
31#define MIC_MIN_MSIX 4 32#define MIC_MIN_MSIX 8
32#define MIC_NUM_OFFSETS 32 33#define MIC_NUM_OFFSETS 32
33 34
34/** 35/**
diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c
index aba3e8324b82..a020e4eb435a 100644
--- a/drivers/misc/mic/host/mic_virtio.c
+++ b/drivers/misc/mic/host/mic_virtio.c
@@ -21,60 +21,157 @@
21#include <linux/pci.h> 21#include <linux/pci.h>
22#include <linux/sched.h> 22#include <linux/sched.h>
23#include <linux/uaccess.h> 23#include <linux/uaccess.h>
24 24#include <linux/dmaengine.h>
25#include <linux/mic_common.h> 25#include <linux/mic_common.h>
26
26#include "../common/mic_dev.h" 27#include "../common/mic_dev.h"
27#include "mic_device.h" 28#include "mic_device.h"
28#include "mic_smpt.h" 29#include "mic_smpt.h"
29#include "mic_virtio.h" 30#include "mic_virtio.h"
30 31
31/* 32/*
32 * Initiates the copies across the PCIe bus from card memory to 33 * Size of the internal buffer used during DMA's as an intermediate buffer
33 * a user space buffer. 34 * for copy to/from user.
34 */ 35 */
35static int mic_virtio_copy_to_user(struct mic_vdev *mvdev, 36#define MIC_INT_DMA_BUF_SIZE PAGE_ALIGN(64 * 1024ULL)
36 void __user *ubuf, size_t len, u64 addr) 37
38static int mic_sync_dma(struct mic_device *mdev, dma_addr_t dst,
39 dma_addr_t src, size_t len)
37{ 40{
38 int err; 41 int err = 0;
39 void __iomem *dbuf = mvdev->mdev->aper.va + addr; 42 struct dma_async_tx_descriptor *tx;
40 /* 43 struct dma_chan *mic_ch = mdev->dma_ch;
41 * We are copying from IO below an should ideally use something 44
42 * like copy_to_user_fromio(..) if it existed. 45 if (!mic_ch) {
43 */ 46 err = -EBUSY;
44 if (copy_to_user(ubuf, (void __force *)dbuf, len)) { 47 goto error;
45 err = -EFAULT; 48 }
46 dev_err(mic_dev(mvdev), "%s %d err %d\n", 49
50 tx = mic_ch->device->device_prep_dma_memcpy(mic_ch, dst, src, len,
51 DMA_PREP_FENCE);
52 if (!tx) {
53 err = -ENOMEM;
54 goto error;
55 } else {
56 dma_cookie_t cookie = tx->tx_submit(tx);
57
58 err = dma_submit_error(cookie);
59 if (err)
60 goto error;
61 err = dma_sync_wait(mic_ch, cookie);
62 }
63error:
64 if (err)
65 dev_err(mdev->sdev->parent, "%s %d err %d\n",
47 __func__, __LINE__, err); 66 __func__, __LINE__, err);
48 goto err; 67 return err;
68}
69
70/*
71 * Initiates the copies across the PCIe bus from card memory to a user
72 * space buffer. When transfers are done using DMA, source/destination
73 * addresses and transfer length must follow the alignment requirements of
74 * the MIC DMA engine.
75 */
76static int mic_virtio_copy_to_user(struct mic_vdev *mvdev, void __user *ubuf,
77 size_t len, u64 daddr, size_t dlen,
78 int vr_idx)
79{
80 struct mic_device *mdev = mvdev->mdev;
81 void __iomem *dbuf = mdev->aper.va + daddr;
82 struct mic_vringh *mvr = &mvdev->mvr[vr_idx];
83 size_t dma_alignment = 1 << mdev->dma_ch->device->copy_align;
84 size_t dma_offset;
85 size_t partlen;
86 int err;
87
88 dma_offset = daddr - round_down(daddr, dma_alignment);
89 daddr -= dma_offset;
90 len += dma_offset;
91
92 while (len) {
93 partlen = min_t(size_t, len, MIC_INT_DMA_BUF_SIZE);
94
95 err = mic_sync_dma(mdev, mvr->buf_da, daddr,
96 ALIGN(partlen, dma_alignment));
97 if (err)
98 goto err;
99
100 if (copy_to_user(ubuf, mvr->buf + dma_offset,
101 partlen - dma_offset)) {
102 err = -EFAULT;
103 goto err;
104 }
105 daddr += partlen;
106 ubuf += partlen;
107 dbuf += partlen;
108 mvdev->in_bytes_dma += partlen;
109 mvdev->in_bytes += partlen;
110 len -= partlen;
111 dma_offset = 0;
49 } 112 }
50 mvdev->in_bytes += len; 113 return 0;
51 err = 0;
52err: 114err:
115 dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err);
53 return err; 116 return err;
54} 117}
55 118
56/* 119/*
57 * Initiates copies across the PCIe bus from a user space 120 * Initiates copies across the PCIe bus from a user space buffer to card
58 * buffer to card memory. 121 * memory. When transfers are done using DMA, source/destination addresses
122 * and transfer length must follow the alignment requirements of the MIC
123 * DMA engine.
59 */ 124 */
60static int mic_virtio_copy_from_user(struct mic_vdev *mvdev, 125static int mic_virtio_copy_from_user(struct mic_vdev *mvdev, void __user *ubuf,
61 void __user *ubuf, size_t len, u64 addr) 126 size_t len, u64 daddr, size_t dlen,
127 int vr_idx)
62{ 128{
129 struct mic_device *mdev = mvdev->mdev;
130 void __iomem *dbuf = mdev->aper.va + daddr;
131 struct mic_vringh *mvr = &mvdev->mvr[vr_idx];
132 size_t dma_alignment = 1 << mdev->dma_ch->device->copy_align;
133 size_t partlen;
63 int err; 134 int err;
64 void __iomem *dbuf = mvdev->mdev->aper.va + addr; 135
136 if (daddr & (dma_alignment - 1)) {
137 mvdev->tx_dst_unaligned += len;
138 goto memcpy;
139 } else if (ALIGN(len, dma_alignment) > dlen) {
140 mvdev->tx_len_unaligned += len;
141 goto memcpy;
142 }
143
144 while (len) {
145 partlen = min_t(size_t, len, MIC_INT_DMA_BUF_SIZE);
146
147 if (copy_from_user(mvr->buf, ubuf, partlen)) {
148 err = -EFAULT;
149 goto err;
150 }
151 err = mic_sync_dma(mdev, daddr, mvr->buf_da,
152 ALIGN(partlen, dma_alignment));
153 if (err)
154 goto err;
155 daddr += partlen;
156 ubuf += partlen;
157 dbuf += partlen;
158 mvdev->out_bytes_dma += partlen;
159 mvdev->out_bytes += partlen;
160 len -= partlen;
161 }
162memcpy:
65 /* 163 /*
66 * We are copying to IO below and should ideally use something 164 * We are copying to IO below and should ideally use something
67 * like copy_from_user_toio(..) if it existed. 165 * like copy_from_user_toio(..) if it existed.
68 */ 166 */
69 if (copy_from_user((void __force *)dbuf, ubuf, len)) { 167 if (copy_from_user((void __force *)dbuf, ubuf, len)) {
70 err = -EFAULT; 168 err = -EFAULT;
71 dev_err(mic_dev(mvdev), "%s %d err %d\n",
72 __func__, __LINE__, err);
73 goto err; 169 goto err;
74 } 170 }
75 mvdev->out_bytes += len; 171 mvdev->out_bytes += len;
76 err = 0; 172 return 0;
77err: 173err:
174 dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err);
78 return err; 175 return err;
79} 176}
80 177
@@ -110,7 +207,8 @@ static inline u32 mic_vringh_iov_consumed(struct vringh_kiov *iov)
110 * way to override the VRINGH xfer(..) routines as of v3.10. 207 * way to override the VRINGH xfer(..) routines as of v3.10.
111 */ 208 */
112static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov, 209static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov,
113 void __user *ubuf, size_t len, bool read, size_t *out_len) 210 void __user *ubuf, size_t len, bool read, int vr_idx,
211 size_t *out_len)
114{ 212{
115 int ret = 0; 213 int ret = 0;
116 size_t partlen, tot_len = 0; 214 size_t partlen, tot_len = 0;
@@ -118,13 +216,15 @@ static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov,
118 while (len && iov->i < iov->used) { 216 while (len && iov->i < iov->used) {
119 partlen = min(iov->iov[iov->i].iov_len, len); 217 partlen = min(iov->iov[iov->i].iov_len, len);
120 if (read) 218 if (read)
121 ret = mic_virtio_copy_to_user(mvdev, 219 ret = mic_virtio_copy_to_user(mvdev, ubuf, partlen,
122 ubuf, partlen, 220 (u64)iov->iov[iov->i].iov_base,
123 (u64)iov->iov[iov->i].iov_base); 221 iov->iov[iov->i].iov_len,
222 vr_idx);
124 else 223 else
125 ret = mic_virtio_copy_from_user(mvdev, 224 ret = mic_virtio_copy_from_user(mvdev, ubuf, partlen,
126 ubuf, partlen, 225 (u64)iov->iov[iov->i].iov_base,
127 (u64)iov->iov[iov->i].iov_base); 226 iov->iov[iov->i].iov_len,
227 vr_idx);
128 if (ret) { 228 if (ret) {
129 dev_err(mic_dev(mvdev), "%s %d err %d\n", 229 dev_err(mic_dev(mvdev), "%s %d err %d\n",
130 __func__, __LINE__, ret); 230 __func__, __LINE__, ret);
@@ -192,8 +292,8 @@ static int _mic_virtio_copy(struct mic_vdev *mvdev,
192 ubuf = iov.iov_base; 292 ubuf = iov.iov_base;
193 } 293 }
194 /* Issue all the read descriptors first */ 294 /* Issue all the read descriptors first */
195 ret = mic_vringh_copy(mvdev, riov, ubuf, len, 295 ret = mic_vringh_copy(mvdev, riov, ubuf, len, MIC_VRINGH_READ,
196 MIC_VRINGH_READ, &out_len); 296 copy->vr_idx, &out_len);
197 if (ret) { 297 if (ret) {
198 dev_err(mic_dev(mvdev), "%s %d err %d\n", 298 dev_err(mic_dev(mvdev), "%s %d err %d\n",
199 __func__, __LINE__, ret); 299 __func__, __LINE__, ret);
@@ -203,8 +303,8 @@ static int _mic_virtio_copy(struct mic_vdev *mvdev,
203 ubuf += out_len; 303 ubuf += out_len;
204 copy->out_len += out_len; 304 copy->out_len += out_len;
205 /* Issue the write descriptors next */ 305 /* Issue the write descriptors next */
206 ret = mic_vringh_copy(mvdev, wiov, ubuf, len, 306 ret = mic_vringh_copy(mvdev, wiov, ubuf, len, !MIC_VRINGH_READ,
207 !MIC_VRINGH_READ, &out_len); 307 copy->vr_idx, &out_len);
208 if (ret) { 308 if (ret) {
209 dev_err(mic_dev(mvdev), "%s %d err %d\n", 309 dev_err(mic_dev(mvdev), "%s %d err %d\n",
210 __func__, __LINE__, ret); 310 __func__, __LINE__, ret);
@@ -589,6 +689,10 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
589 dev_dbg(mdev->sdev->parent, 689 dev_dbg(mdev->sdev->parent,
590 "%s %d index %d va %p info %p vr_size 0x%x\n", 690 "%s %d index %d va %p info %p vr_size 0x%x\n",
591 __func__, __LINE__, i, vr->va, vr->info, vr_size); 691 __func__, __LINE__, i, vr->va, vr->info, vr_size);
692 mvr->buf = (void *)__get_free_pages(GFP_KERNEL,
693 get_order(MIC_INT_DMA_BUF_SIZE));
694 mvr->buf_da = mic_map_single(mvdev->mdev, mvr->buf,
695 MIC_INT_DMA_BUF_SIZE);
592 } 696 }
593 697
594 snprintf(irqname, sizeof(irqname), "mic%dvirtio%d", mdev->id, 698 snprintf(irqname, sizeof(irqname), "mic%dvirtio%d", mdev->id,
@@ -673,6 +777,11 @@ skip_hot_remove:
673 vqconfig = mic_vq_config(mvdev->dd); 777 vqconfig = mic_vq_config(mvdev->dd);
674 for (i = 0; i < mvdev->dd->num_vq; i++) { 778 for (i = 0; i < mvdev->dd->num_vq; i++) {
675 struct mic_vringh *mvr = &mvdev->mvr[i]; 779 struct mic_vringh *mvr = &mvdev->mvr[i];
780
781 mic_unmap_single(mvdev->mdev, mvr->buf_da,
782 MIC_INT_DMA_BUF_SIZE);
783 free_pages((unsigned long)mvr->buf,
784 get_order(MIC_INT_DMA_BUF_SIZE));
676 vringh_kiov_cleanup(&mvr->riov); 785 vringh_kiov_cleanup(&mvr->riov);
677 vringh_kiov_cleanup(&mvr->wiov); 786 vringh_kiov_cleanup(&mvr->wiov);
678 mic_unmap_single(mdev, le64_to_cpu(vqconfig[i].address), 787 mic_unmap_single(mdev, le64_to_cpu(vqconfig[i].address),
diff --git a/drivers/misc/mic/host/mic_virtio.h b/drivers/misc/mic/host/mic_virtio.h
index 184f3c84805b..d574efb853d9 100644
--- a/drivers/misc/mic/host/mic_virtio.h
+++ b/drivers/misc/mic/host/mic_virtio.h
@@ -46,18 +46,23 @@
46 * @vrh: The host VRINGH used for accessing the card vrings. 46 * @vrh: The host VRINGH used for accessing the card vrings.
47 * @riov: The VRINGH read kernel IOV. 47 * @riov: The VRINGH read kernel IOV.
48 * @wiov: The VRINGH write kernel IOV. 48 * @wiov: The VRINGH write kernel IOV.
49 * @head: The VRINGH head index address passed to vringh_getdesc_kern(..).
50 * @vr_mutex: Mutex for synchronizing access to the VRING. 49 * @vr_mutex: Mutex for synchronizing access to the VRING.
50 * @buf: Temporary kernel buffer used to copy in/out data
51 * from/to the card via DMA.
52 * @buf_da: dma address of buf.
51 * @mvdev: Back pointer to MIC virtio device for vringh_notify(..). 53 * @mvdev: Back pointer to MIC virtio device for vringh_notify(..).
54 * @head: The VRINGH head index address passed to vringh_getdesc_kern(..).
52 */ 55 */
53struct mic_vringh { 56struct mic_vringh {
54 struct mic_vring vring; 57 struct mic_vring vring;
55 struct vringh vrh; 58 struct vringh vrh;
56 struct vringh_kiov riov; 59 struct vringh_kiov riov;
57 struct vringh_kiov wiov; 60 struct vringh_kiov wiov;
58 u16 head;
59 struct mutex vr_mutex; 61 struct mutex vr_mutex;
62 void *buf;
63 dma_addr_t buf_da;
60 struct mic_vdev *mvdev; 64 struct mic_vdev *mvdev;
65 u16 head;
61}; 66};
62 67
63/** 68/**
@@ -69,6 +74,14 @@ struct mic_vringh {
69 * @poll_wake - Used for waking up threads blocked in poll. 74 * @poll_wake - Used for waking up threads blocked in poll.
70 * @out_bytes - Debug stats for number of bytes copied from host to card. 75 * @out_bytes - Debug stats for number of bytes copied from host to card.
71 * @in_bytes - Debug stats for number of bytes copied from card to host. 76 * @in_bytes - Debug stats for number of bytes copied from card to host.
77 * @out_bytes_dma - Debug stats for number of bytes copied from host to card
78 * using DMA.
79 * @in_bytes_dma - Debug stats for number of bytes copied from card to host
80 * using DMA.
81 * @tx_len_unaligned - Debug stats for number of bytes copied to the card where
82 * the transfer length did not have the required DMA alignment.
83 * @tx_dst_unaligned - Debug stats for number of bytes copied where the
84 * destination address on the card did not have the required DMA alignment.
72 * @mvr - Store per VRING data structures. 85 * @mvr - Store per VRING data structures.
73 * @virtio_bh_work - Work struct used to schedule virtio bottom half handling. 86 * @virtio_bh_work - Work struct used to schedule virtio bottom half handling.
74 * @dd - Virtio device descriptor. 87 * @dd - Virtio device descriptor.
@@ -84,6 +97,10 @@ struct mic_vdev {
84 int poll_wake; 97 int poll_wake;
85 unsigned long out_bytes; 98 unsigned long out_bytes;
86 unsigned long in_bytes; 99 unsigned long in_bytes;
100 unsigned long out_bytes_dma;
101 unsigned long in_bytes_dma;
102 unsigned long tx_len_unaligned;
103 unsigned long tx_dst_unaligned;
87 struct mic_vringh mvr[MIC_MAX_VRINGS]; 104 struct mic_vringh mvr[MIC_MAX_VRINGS];
88 struct work_struct virtio_bh_work; 105 struct work_struct virtio_bh_work;
89 struct mic_device_desc *dd; 106 struct mic_device_desc *dd;
diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c
index 5562fdd3ef4e..b7a21e11dcdf 100644
--- a/drivers/misc/mic/host/mic_x100.c
+++ b/drivers/misc/mic/host/mic_x100.c
@@ -549,6 +549,13 @@ struct mic_smpt_ops mic_x100_smpt_ops = {
549 .set = mic_x100_smpt_set, 549 .set = mic_x100_smpt_set,
550}; 550};
551 551
552static bool mic_x100_dma_filter(struct dma_chan *chan, void *param)
553{
554 if (chan->device->dev->parent == (struct device *)param)
555 return true;
556 return false;
557}
558
552struct mic_hw_ops mic_x100_ops = { 559struct mic_hw_ops mic_x100_ops = {
553 .aper_bar = MIC_X100_APER_BAR, 560 .aper_bar = MIC_X100_APER_BAR,
554 .mmio_bar = MIC_X100_MMIO_BAR, 561 .mmio_bar = MIC_X100_MMIO_BAR,
@@ -563,6 +570,7 @@ struct mic_hw_ops mic_x100_ops = {
563 .send_firmware_intr = mic_x100_send_firmware_intr, 570 .send_firmware_intr = mic_x100_send_firmware_intr,
564 .load_mic_fw = mic_x100_load_firmware, 571 .load_mic_fw = mic_x100_load_firmware,
565 .get_postcode = mic_x100_get_postcode, 572 .get_postcode = mic_x100_get_postcode,
573 .dma_filter = mic_x100_dma_filter,
566}; 574};
567 575
568struct mic_hw_intr_ops mic_x100_intr_ops = { 576struct mic_hw_intr_ops mic_x100_intr_ops = {