aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mic/host
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-06 19:41:06 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-06 19:41:06 -0500
commit1071ec7bc2dabd0a9d12a1ae5570f4fd3ba944ca (patch)
tree3f889877ae180066a8e682d915680f240fbfd6ec /drivers/misc/mic/host
parentc287322c3aadf45ee15339bffdbc2e9117b9cc7a (diff)
parent425792266a40189e0b3fec02cb59a69935d8c58c (diff)
Merge tag 'char-misc-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc patches from Greg KH: "Here's the big char/misc driver patchset for 3.13-rc1. Lots of stuff in here, including some new drivers for Intel's "MIC" co-processor devices, and a new eeprom driver. Other things include the driver attribute cleanups, extcon driver updates, hyperv updates, and a raft of other miscellaneous driver fixes. All of these have been in linux-next for a while" * tag 'char-misc-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (121 commits) misc: mic: Fixes for randconfig build errors and warnings. tifm: fix error return code in tifm_7xx1_probe() w1-gpio: Use devm_* functions w1-gpio: Detect of_gpio_error for first gpio uio: Pass pointers to virt_to_page(), not integers uio: fix memory leak misc/at24: avoid infinite loop on write() misc/93xx46: avoid infinite loop on write() misc: atmel_pwm: add deferred-probing support mei: wd: host_init propagate error codes from called functions mei: replace stray pr_debug with dev_dbg mei: bus: propagate error code returned by mei_me_cl_by_id mei: mei_cl_link remove duplicated check for open_handle_count mei: print correct device state during unexpected reset mei: nfc: fix memory leak in error path lkdtm: add tests for additional page permissions lkdtm: adjust recursion size to avoid warnings lkdtm: isolate stack corruption test mei: move host_clients_map cleanup to device init mei: me: downgrade two errors to debug level ...
Diffstat (limited to 'drivers/misc/mic/host')
-rw-r--r--drivers/misc/mic/host/Makefile14
-rw-r--r--drivers/misc/mic/host/mic_boot.c300
-rw-r--r--drivers/misc/mic/host/mic_debugfs.c491
-rw-r--r--drivers/misc/mic/host/mic_device.h203
-rw-r--r--drivers/misc/mic/host/mic_fops.c222
-rw-r--r--drivers/misc/mic/host/mic_fops.h32
-rw-r--r--drivers/misc/mic/host/mic_intr.c630
-rw-r--r--drivers/misc/mic/host/mic_intr.h137
-rw-r--r--drivers/misc/mic/host/mic_main.c537
-rw-r--r--drivers/misc/mic/host/mic_smpt.c442
-rw-r--r--drivers/misc/mic/host/mic_smpt.h98
-rw-r--r--drivers/misc/mic/host/mic_sysfs.c459
-rw-r--r--drivers/misc/mic/host/mic_virtio.c700
-rw-r--r--drivers/misc/mic/host/mic_virtio.h138
-rw-r--r--drivers/misc/mic/host/mic_x100.c570
-rw-r--r--drivers/misc/mic/host/mic_x100.h98
16 files changed, 5071 insertions, 0 deletions
diff --git a/drivers/misc/mic/host/Makefile b/drivers/misc/mic/host/Makefile
new file mode 100644
index 000000000000..c2197f999394
--- /dev/null
+++ b/drivers/misc/mic/host/Makefile
@@ -0,0 +1,14 @@
1#
2# Makefile - Intel MIC Linux driver.
3# Copyright(c) 2013, Intel Corporation.
4#
5obj-$(CONFIG_INTEL_MIC_HOST) += mic_host.o
6mic_host-objs := mic_main.o
7mic_host-objs += mic_x100.o
8mic_host-objs += mic_sysfs.o
9mic_host-objs += mic_smpt.o
10mic_host-objs += mic_intr.o
11mic_host-objs += mic_boot.o
12mic_host-objs += mic_debugfs.o
13mic_host-objs += mic_fops.o
14mic_host-objs += mic_virtio.o
diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c
new file mode 100644
index 000000000000..b079c65eed6d
--- /dev/null
+++ b/drivers/misc/mic/host/mic_boot.c
@@ -0,0 +1,300 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#include <linux/delay.h>
22#include <linux/firmware.h>
23#include <linux/pci.h>
24
25#include <linux/mic_common.h>
26#include "../common/mic_dev.h"
27#include "mic_device.h"
28#include "mic_smpt.h"
29#include "mic_virtio.h"
30
31/**
32 * mic_reset - Reset the MIC device.
33 * @mdev: pointer to mic_device instance
34 */
35static void mic_reset(struct mic_device *mdev)
36{
37 int i;
38
39#define MIC_RESET_TO (45)
40
41 INIT_COMPLETION(mdev->reset_wait);
42 mdev->ops->reset_fw_ready(mdev);
43 mdev->ops->reset(mdev);
44
45 for (i = 0; i < MIC_RESET_TO; i++) {
46 if (mdev->ops->is_fw_ready(mdev))
47 goto done;
48 /*
49 * Resets typically take 10s of seconds to complete.
50 * Since an MMIO read is required to check if the
51 * firmware is ready or not, a 1 second delay works nicely.
52 */
53 msleep(1000);
54 }
55 mic_set_state(mdev, MIC_RESET_FAILED);
56done:
57 complete_all(&mdev->reset_wait);
58}
59
60/* Initialize the MIC bootparams */
61void mic_bootparam_init(struct mic_device *mdev)
62{
63 struct mic_bootparam *bootparam = mdev->dp;
64
65 bootparam->magic = MIC_MAGIC;
66 bootparam->c2h_shutdown_db = mdev->shutdown_db;
67 bootparam->h2c_shutdown_db = -1;
68 bootparam->h2c_config_db = -1;
69 bootparam->shutdown_status = 0;
70 bootparam->shutdown_card = 0;
71}
72
73/**
74 * mic_start - Start the MIC.
75 * @mdev: pointer to mic_device instance
76 * @buf: buffer containing boot string including firmware/ramdisk path.
77 *
78 * This function prepares an MIC for boot and initiates boot.
79 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
80 */
81int mic_start(struct mic_device *mdev, const char *buf)
82{
83 int rc;
84 mutex_lock(&mdev->mic_mutex);
85retry:
86 if (MIC_OFFLINE != mdev->state) {
87 rc = -EINVAL;
88 goto unlock_ret;
89 }
90 if (!mdev->ops->is_fw_ready(mdev)) {
91 mic_reset(mdev);
92 /*
93 * The state will either be MIC_OFFLINE if the reset succeeded
94 * or MIC_RESET_FAILED if the firmware reset failed.
95 */
96 goto retry;
97 }
98 rc = mdev->ops->load_mic_fw(mdev, buf);
99 if (rc)
100 goto unlock_ret;
101 mic_smpt_restore(mdev);
102 mic_intr_restore(mdev);
103 mdev->intr_ops->enable_interrupts(mdev);
104 mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
105 mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
106 mdev->ops->send_firmware_intr(mdev);
107 mic_set_state(mdev, MIC_ONLINE);
108unlock_ret:
109 mutex_unlock(&mdev->mic_mutex);
110 return rc;
111}
112
113/**
114 * mic_stop - Prepare the MIC for reset and trigger reset.
115 * @mdev: pointer to mic_device instance
116 * @force: force a MIC to reset even if it is already offline.
117 *
118 * RETURNS: None.
119 */
120void mic_stop(struct mic_device *mdev, bool force)
121{
122 mutex_lock(&mdev->mic_mutex);
123 if (MIC_OFFLINE != mdev->state || force) {
124 mic_virtio_reset_devices(mdev);
125 mic_bootparam_init(mdev);
126 mic_reset(mdev);
127 if (MIC_RESET_FAILED == mdev->state)
128 goto unlock;
129 mic_set_shutdown_status(mdev, MIC_NOP);
130 if (MIC_SUSPENDED != mdev->state)
131 mic_set_state(mdev, MIC_OFFLINE);
132 }
133unlock:
134 mutex_unlock(&mdev->mic_mutex);
135}
136
137/**
138 * mic_shutdown - Initiate MIC shutdown.
139 * @mdev: pointer to mic_device instance
140 *
141 * RETURNS: None.
142 */
143void mic_shutdown(struct mic_device *mdev)
144{
145 struct mic_bootparam *bootparam = mdev->dp;
146 s8 db = bootparam->h2c_shutdown_db;
147
148 mutex_lock(&mdev->mic_mutex);
149 if (MIC_ONLINE == mdev->state && db != -1) {
150 bootparam->shutdown_card = 1;
151 mdev->ops->send_intr(mdev, db);
152 mic_set_state(mdev, MIC_SHUTTING_DOWN);
153 }
154 mutex_unlock(&mdev->mic_mutex);
155}
156
157/**
158 * mic_shutdown_work - Handle shutdown interrupt from MIC.
159 * @work: The work structure.
160 *
161 * This work is scheduled whenever the host has received a shutdown
162 * interrupt from the MIC.
163 */
164void mic_shutdown_work(struct work_struct *work)
165{
166 struct mic_device *mdev = container_of(work, struct mic_device,
167 shutdown_work);
168 struct mic_bootparam *bootparam = mdev->dp;
169
170 mutex_lock(&mdev->mic_mutex);
171 mic_set_shutdown_status(mdev, bootparam->shutdown_status);
172 bootparam->shutdown_status = 0;
173
174 /*
175 * if state is MIC_SUSPENDED, OSPM suspend is in progress. We do not
176 * change the state here so as to prevent users from booting the card
177 * during and after the suspend operation.
178 */
179 if (MIC_SHUTTING_DOWN != mdev->state &&
180 MIC_SUSPENDED != mdev->state)
181 mic_set_state(mdev, MIC_SHUTTING_DOWN);
182 mutex_unlock(&mdev->mic_mutex);
183}
184
185/**
186 * mic_reset_trigger_work - Trigger MIC reset.
187 * @work: The work structure.
188 *
189 * This work is scheduled whenever the host wants to reset the MIC.
190 */
191void mic_reset_trigger_work(struct work_struct *work)
192{
193 struct mic_device *mdev = container_of(work, struct mic_device,
194 reset_trigger_work);
195
196 mic_stop(mdev, false);
197}
198
199/**
200 * mic_complete_resume - Complete MIC Resume after an OSPM suspend/hibernate
201 * event.
202 * @mdev: pointer to mic_device instance
203 *
204 * RETURNS: None.
205 */
206void mic_complete_resume(struct mic_device *mdev)
207{
208 if (mdev->state != MIC_SUSPENDED) {
209 dev_warn(mdev->sdev->parent, "state %d should be %d\n",
210 mdev->state, MIC_SUSPENDED);
211 return;
212 }
213
214 /* Make sure firmware is ready */
215 if (!mdev->ops->is_fw_ready(mdev))
216 mic_stop(mdev, true);
217
218 mutex_lock(&mdev->mic_mutex);
219 mic_set_state(mdev, MIC_OFFLINE);
220 mutex_unlock(&mdev->mic_mutex);
221}
222
223/**
224 * mic_prepare_suspend - Handle suspend notification for the MIC device.
225 * @mdev: pointer to mic_device instance
226 *
227 * RETURNS: None.
228 */
229void mic_prepare_suspend(struct mic_device *mdev)
230{
231 int rc;
232
233#define MIC_SUSPEND_TIMEOUT (60 * HZ)
234
235 mutex_lock(&mdev->mic_mutex);
236 switch (mdev->state) {
237 case MIC_OFFLINE:
238 /*
239 * Card is already offline. Set state to MIC_SUSPENDED
240 * to prevent users from booting the card.
241 */
242 mic_set_state(mdev, MIC_SUSPENDED);
243 mutex_unlock(&mdev->mic_mutex);
244 break;
245 case MIC_ONLINE:
246 /*
247 * Card is online. Set state to MIC_SUSPENDING and notify
248 * MIC user space daemon which will issue card
249 * shutdown and reset.
250 */
251 mic_set_state(mdev, MIC_SUSPENDING);
252 mutex_unlock(&mdev->mic_mutex);
253 rc = wait_for_completion_timeout(&mdev->reset_wait,
254 MIC_SUSPEND_TIMEOUT);
255 /* Force reset the card if the shutdown completion timed out */
256 if (!rc) {
257 mutex_lock(&mdev->mic_mutex);
258 mic_set_state(mdev, MIC_SUSPENDED);
259 mutex_unlock(&mdev->mic_mutex);
260 mic_stop(mdev, true);
261 }
262 break;
263 case MIC_SHUTTING_DOWN:
264 /*
265 * Card is shutting down. Set state to MIC_SUSPENDED
266 * to prevent further boot of the card.
267 */
268 mic_set_state(mdev, MIC_SUSPENDED);
269 mutex_unlock(&mdev->mic_mutex);
270 rc = wait_for_completion_timeout(&mdev->reset_wait,
271 MIC_SUSPEND_TIMEOUT);
272 /* Force reset the card if the shutdown completion timed out */
273 if (!rc)
274 mic_stop(mdev, true);
275 break;
276 default:
277 mutex_unlock(&mdev->mic_mutex);
278 break;
279 }
280}
281
282/**
283 * mic_suspend - Initiate MIC suspend. Suspend merely issues card shutdown.
284 * @mdev: pointer to mic_device instance
285 *
286 * RETURNS: None.
287 */
288void mic_suspend(struct mic_device *mdev)
289{
290 struct mic_bootparam *bootparam = mdev->dp;
291 s8 db = bootparam->h2c_shutdown_db;
292
293 mutex_lock(&mdev->mic_mutex);
294 if (MIC_SUSPENDING == mdev->state && db != -1) {
295 bootparam->shutdown_card = 1;
296 mdev->ops->send_intr(mdev, db);
297 mic_set_state(mdev, MIC_SUSPENDED);
298 }
299 mutex_unlock(&mdev->mic_mutex);
300}
diff --git a/drivers/misc/mic/host/mic_debugfs.c b/drivers/misc/mic/host/mic_debugfs.c
new file mode 100644
index 000000000000..028ba5d6fd1c
--- /dev/null
+++ b/drivers/misc/mic/host/mic_debugfs.c
@@ -0,0 +1,491 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#include <linux/debugfs.h>
22#include <linux/pci.h>
23#include <linux/seq_file.h>
24
25#include <linux/mic_common.h>
26#include "../common/mic_dev.h"
27#include "mic_device.h"
28#include "mic_smpt.h"
29#include "mic_virtio.h"
30
31/* Debugfs parent dir */
32static struct dentry *mic_dbg;
33
34/**
35 * mic_log_buf_show - Display MIC kernel log buffer.
36 *
37 * log_buf addr/len is read from System.map by user space
38 * and populated in sysfs entries.
39 */
40static int mic_log_buf_show(struct seq_file *s, void *unused)
41{
42 void __iomem *log_buf_va;
43 int __iomem *log_buf_len_va;
44 struct mic_device *mdev = s->private;
45 void *kva;
46 int size;
47 unsigned long aper_offset;
48
49 if (!mdev || !mdev->log_buf_addr || !mdev->log_buf_len)
50 goto done;
51 /*
52 * Card kernel will never be relocated and any kernel text/data mapping
53 * can be translated to phys address by subtracting __START_KERNEL_map.
54 */
55 aper_offset = (unsigned long)mdev->log_buf_len - __START_KERNEL_map;
56 log_buf_len_va = mdev->aper.va + aper_offset;
57 aper_offset = (unsigned long)mdev->log_buf_addr - __START_KERNEL_map;
58 log_buf_va = mdev->aper.va + aper_offset;
59 size = ioread32(log_buf_len_va);
60
61 kva = kmalloc(size, GFP_KERNEL);
62 if (!kva)
63 goto done;
64 mutex_lock(&mdev->mic_mutex);
65 memcpy_fromio(kva, log_buf_va, size);
66 switch (mdev->state) {
67 case MIC_ONLINE:
68 /* Fall through */
69 case MIC_SHUTTING_DOWN:
70 seq_write(s, kva, size);
71 break;
72 default:
73 break;
74 }
75 mutex_unlock(&mdev->mic_mutex);
76 kfree(kva);
77done:
78 return 0;
79}
80
81static int mic_log_buf_open(struct inode *inode, struct file *file)
82{
83 return single_open(file, mic_log_buf_show, inode->i_private);
84}
85
86static int mic_log_buf_release(struct inode *inode, struct file *file)
87{
88 return single_release(inode, file);
89}
90
91static const struct file_operations log_buf_ops = {
92 .owner = THIS_MODULE,
93 .open = mic_log_buf_open,
94 .read = seq_read,
95 .llseek = seq_lseek,
96 .release = mic_log_buf_release
97};
98
99static int mic_smpt_show(struct seq_file *s, void *pos)
100{
101 int i;
102 struct mic_device *mdev = s->private;
103 unsigned long flags;
104
105 seq_printf(s, "MIC %-2d |%-10s| %-14s %-10s\n",
106 mdev->id, "SMPT entry", "SW DMA addr", "RefCount");
107 seq_puts(s, "====================================================\n");
108
109 if (mdev->smpt) {
110 struct mic_smpt_info *smpt_info = mdev->smpt;
111 spin_lock_irqsave(&smpt_info->smpt_lock, flags);
112 for (i = 0; i < smpt_info->info.num_reg; i++) {
113 seq_printf(s, "%9s|%-10d| %-#14llx %-10lld\n",
114 " ", i, smpt_info->entry[i].dma_addr,
115 smpt_info->entry[i].ref_count);
116 }
117 spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
118 }
119 seq_puts(s, "====================================================\n");
120 return 0;
121}
122
123static int mic_smpt_debug_open(struct inode *inode, struct file *file)
124{
125 return single_open(file, mic_smpt_show, inode->i_private);
126}
127
128static int mic_smpt_debug_release(struct inode *inode, struct file *file)
129{
130 return single_release(inode, file);
131}
132
133static const struct file_operations smpt_file_ops = {
134 .owner = THIS_MODULE,
135 .open = mic_smpt_debug_open,
136 .read = seq_read,
137 .llseek = seq_lseek,
138 .release = mic_smpt_debug_release
139};
140
141static int mic_soft_reset_show(struct seq_file *s, void *pos)
142{
143 struct mic_device *mdev = s->private;
144
145 mic_stop(mdev, true);
146 return 0;
147}
148
149static int mic_soft_reset_debug_open(struct inode *inode, struct file *file)
150{
151 return single_open(file, mic_soft_reset_show, inode->i_private);
152}
153
154static int mic_soft_reset_debug_release(struct inode *inode, struct file *file)
155{
156 return single_release(inode, file);
157}
158
159static const struct file_operations soft_reset_ops = {
160 .owner = THIS_MODULE,
161 .open = mic_soft_reset_debug_open,
162 .read = seq_read,
163 .llseek = seq_lseek,
164 .release = mic_soft_reset_debug_release
165};
166
167static int mic_post_code_show(struct seq_file *s, void *pos)
168{
169 struct mic_device *mdev = s->private;
170 u32 reg = mdev->ops->get_postcode(mdev);
171
172 seq_printf(s, "%c%c", reg & 0xff, (reg >> 8) & 0xff);
173 return 0;
174}
175
176static int mic_post_code_debug_open(struct inode *inode, struct file *file)
177{
178 return single_open(file, mic_post_code_show, inode->i_private);
179}
180
181static int mic_post_code_debug_release(struct inode *inode, struct file *file)
182{
183 return single_release(inode, file);
184}
185
186static const struct file_operations post_code_ops = {
187 .owner = THIS_MODULE,
188 .open = mic_post_code_debug_open,
189 .read = seq_read,
190 .llseek = seq_lseek,
191 .release = mic_post_code_debug_release
192};
193
194static int mic_dp_show(struct seq_file *s, void *pos)
195{
196 struct mic_device *mdev = s->private;
197 struct mic_device_desc *d;
198 struct mic_device_ctrl *dc;
199 struct mic_vqconfig *vqconfig;
200 __u32 *features;
201 __u8 *config;
202 struct mic_bootparam *bootparam = mdev->dp;
203 int i, j;
204
205 seq_printf(s, "Bootparam: magic 0x%x\n",
206 bootparam->magic);
207 seq_printf(s, "Bootparam: h2c_shutdown_db %d\n",
208 bootparam->h2c_shutdown_db);
209 seq_printf(s, "Bootparam: h2c_config_db %d\n",
210 bootparam->h2c_config_db);
211 seq_printf(s, "Bootparam: c2h_shutdown_db %d\n",
212 bootparam->c2h_shutdown_db);
213 seq_printf(s, "Bootparam: shutdown_status %d\n",
214 bootparam->shutdown_status);
215 seq_printf(s, "Bootparam: shutdown_card %d\n",
216 bootparam->shutdown_card);
217
218 for (i = sizeof(*bootparam); i < MIC_DP_SIZE;
219 i += mic_total_desc_size(d)) {
220 d = mdev->dp + i;
221 dc = (void *)d + mic_aligned_desc_size(d);
222
223 /* end of list */
224 if (d->type == 0)
225 break;
226
227 if (d->type == -1)
228 continue;
229
230 seq_printf(s, "Type %d ", d->type);
231 seq_printf(s, "Num VQ %d ", d->num_vq);
232 seq_printf(s, "Feature Len %d\n", d->feature_len);
233 seq_printf(s, "Config Len %d ", d->config_len);
234 seq_printf(s, "Shutdown Status %d\n", d->status);
235
236 for (j = 0; j < d->num_vq; j++) {
237 vqconfig = mic_vq_config(d) + j;
238 seq_printf(s, "vqconfig[%d]: ", j);
239 seq_printf(s, "address 0x%llx ", vqconfig->address);
240 seq_printf(s, "num %d ", vqconfig->num);
241 seq_printf(s, "used address 0x%llx\n",
242 vqconfig->used_address);
243 }
244
245 features = (__u32 *)mic_vq_features(d);
246 seq_printf(s, "Features: Host 0x%x ", features[0]);
247 seq_printf(s, "Guest 0x%x\n", features[1]);
248
249 config = mic_vq_configspace(d);
250 for (j = 0; j < d->config_len; j++)
251 seq_printf(s, "config[%d]=%d\n", j, config[j]);
252
253 seq_puts(s, "Device control:\n");
254 seq_printf(s, "Config Change %d ", dc->config_change);
255 seq_printf(s, "Vdev reset %d\n", dc->vdev_reset);
256 seq_printf(s, "Guest Ack %d ", dc->guest_ack);
257 seq_printf(s, "Host ack %d\n", dc->host_ack);
258 seq_printf(s, "Used address updated %d ",
259 dc->used_address_updated);
260 seq_printf(s, "Vdev 0x%llx\n", dc->vdev);
261 seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db);
262 seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db);
263 }
264
265 return 0;
266}
267
268static int mic_dp_debug_open(struct inode *inode, struct file *file)
269{
270 return single_open(file, mic_dp_show, inode->i_private);
271}
272
273static int mic_dp_debug_release(struct inode *inode, struct file *file)
274{
275 return single_release(inode, file);
276}
277
278static const struct file_operations dp_ops = {
279 .owner = THIS_MODULE,
280 .open = mic_dp_debug_open,
281 .read = seq_read,
282 .llseek = seq_lseek,
283 .release = mic_dp_debug_release
284};
285
286static int mic_vdev_info_show(struct seq_file *s, void *unused)
287{
288 struct mic_device *mdev = s->private;
289 struct list_head *pos, *tmp;
290 struct mic_vdev *mvdev;
291 int i, j;
292
293 mutex_lock(&mdev->mic_mutex);
294 list_for_each_safe(pos, tmp, &mdev->vdev_list) {
295 mvdev = list_entry(pos, struct mic_vdev, list);
296 seq_printf(s, "VDEV type %d state %s in %ld out %ld\n",
297 mvdev->virtio_id,
298 mic_vdevup(mvdev) ? "UP" : "DOWN",
299 mvdev->in_bytes,
300 mvdev->out_bytes);
301 for (i = 0; i < MIC_MAX_VRINGS; i++) {
302 struct vring_desc *desc;
303 struct vring_avail *avail;
304 struct vring_used *used;
305 struct mic_vringh *mvr = &mvdev->mvr[i];
306 struct vringh *vrh = &mvr->vrh;
307 int num = vrh->vring.num;
308 if (!num)
309 continue;
310 desc = vrh->vring.desc;
311 seq_printf(s, "vring i %d avail_idx %d",
312 i, mvr->vring.info->avail_idx & (num - 1));
313 seq_printf(s, " vring i %d avail_idx %d\n",
314 i, mvr->vring.info->avail_idx);
315 seq_printf(s, "vrh i %d weak_barriers %d",
316 i, vrh->weak_barriers);
317 seq_printf(s, " last_avail_idx %d last_used_idx %d",
318 vrh->last_avail_idx, vrh->last_used_idx);
319 seq_printf(s, " completed %d\n", vrh->completed);
320 for (j = 0; j < num; j++) {
321 seq_printf(s, "desc[%d] addr 0x%llx len %d",
322 j, desc->addr, desc->len);
323 seq_printf(s, " flags 0x%x next %d\n",
324 desc->flags, desc->next);
325 desc++;
326 }
327 avail = vrh->vring.avail;
328 seq_printf(s, "avail flags 0x%x idx %d\n",
329 avail->flags, avail->idx & (num - 1));
330 seq_printf(s, "avail flags 0x%x idx %d\n",
331 avail->flags, avail->idx);
332 for (j = 0; j < num; j++)
333 seq_printf(s, "avail ring[%d] %d\n",
334 j, avail->ring[j]);
335 used = vrh->vring.used;
336 seq_printf(s, "used flags 0x%x idx %d\n",
337 used->flags, used->idx & (num - 1));
338 seq_printf(s, "used flags 0x%x idx %d\n",
339 used->flags, used->idx);
340 for (j = 0; j < num; j++)
341 seq_printf(s, "used ring[%d] id %d len %d\n",
342 j, used->ring[j].id,
343 used->ring[j].len);
344 }
345 }
346 mutex_unlock(&mdev->mic_mutex);
347
348 return 0;
349}
350
351static int mic_vdev_info_debug_open(struct inode *inode, struct file *file)
352{
353 return single_open(file, mic_vdev_info_show, inode->i_private);
354}
355
356static int mic_vdev_info_debug_release(struct inode *inode, struct file *file)
357{
358 return single_release(inode, file);
359}
360
361static const struct file_operations vdev_info_ops = {
362 .owner = THIS_MODULE,
363 .open = mic_vdev_info_debug_open,
364 .read = seq_read,
365 .llseek = seq_lseek,
366 .release = mic_vdev_info_debug_release
367};
368
369static int mic_msi_irq_info_show(struct seq_file *s, void *pos)
370{
371 struct mic_device *mdev = s->private;
372 int reg;
373 int i, j;
374 u16 entry;
375 u16 vector;
376 struct pci_dev *pdev = container_of(mdev->sdev->parent,
377 struct pci_dev, dev);
378
379 if (pci_dev_msi_enabled(pdev)) {
380 for (i = 0; i < mdev->irq_info.num_vectors; i++) {
381 if (pdev->msix_enabled) {
382 entry = mdev->irq_info.msix_entries[i].entry;
383 vector = mdev->irq_info.msix_entries[i].vector;
384 } else {
385 entry = 0;
386 vector = pdev->irq;
387 }
388
389 reg = mdev->intr_ops->read_msi_to_src_map(mdev, entry);
390
391 seq_printf(s, "%s %-10d %s %-10d MXAR[%d]: %08X\n",
392 "IRQ:", vector, "Entry:", entry, i, reg);
393
394 seq_printf(s, "%-10s", "offset:");
395 for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
396 seq_printf(s, "%4d ", j);
397 seq_puts(s, "\n");
398
399
400 seq_printf(s, "%-10s", "count:");
401 for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
402 seq_printf(s, "%4d ",
403 (mdev->irq_info.mic_msi_map[i] &
404 BIT(j)) ? 1 : 0);
405 seq_puts(s, "\n\n");
406 }
407 } else {
408 seq_puts(s, "MSI/MSIx interrupts not enabled\n");
409 }
410
411 return 0;
412}
413
414static int mic_msi_irq_info_debug_open(struct inode *inode, struct file *file)
415{
416 return single_open(file, mic_msi_irq_info_show, inode->i_private);
417}
418
419static int
420mic_msi_irq_info_debug_release(struct inode *inode, struct file *file)
421{
422 return single_release(inode, file);
423}
424
425static const struct file_operations msi_irq_info_ops = {
426 .owner = THIS_MODULE,
427 .open = mic_msi_irq_info_debug_open,
428 .read = seq_read,
429 .llseek = seq_lseek,
430 .release = mic_msi_irq_info_debug_release
431};
432
433/**
434 * mic_create_debug_dir - Initialize MIC debugfs entries.
435 */
436void mic_create_debug_dir(struct mic_device *mdev)
437{
438 if (!mic_dbg)
439 return;
440
441 mdev->dbg_dir = debugfs_create_dir(dev_name(mdev->sdev), mic_dbg);
442 if (!mdev->dbg_dir)
443 return;
444
445 debugfs_create_file("log_buf", 0444, mdev->dbg_dir, mdev, &log_buf_ops);
446
447 debugfs_create_file("smpt", 0444, mdev->dbg_dir, mdev, &smpt_file_ops);
448
449 debugfs_create_file("soft_reset", 0444, mdev->dbg_dir, mdev,
450 &soft_reset_ops);
451
452 debugfs_create_file("post_code", 0444, mdev->dbg_dir, mdev,
453 &post_code_ops);
454
455 debugfs_create_file("dp", 0444, mdev->dbg_dir, mdev, &dp_ops);
456
457 debugfs_create_file("vdev_info", 0444, mdev->dbg_dir, mdev,
458 &vdev_info_ops);
459
460 debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir, mdev,
461 &msi_irq_info_ops);
462}
463
464/**
465 * mic_delete_debug_dir - Uninitialize MIC debugfs entries.
466 */
467void mic_delete_debug_dir(struct mic_device *mdev)
468{
469 if (!mdev->dbg_dir)
470 return;
471
472 debugfs_remove_recursive(mdev->dbg_dir);
473}
474
475/**
476 * mic_init_debugfs - Initialize global debugfs entry.
477 */
478void __init mic_init_debugfs(void)
479{
480 mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
481 if (!mic_dbg)
482 pr_err("can't create debugfs dir\n");
483}
484
485/**
486 * mic_exit_debugfs - Uninitialize global debugfs entry
487 */
488void mic_exit_debugfs(void)
489{
490 debugfs_remove(mic_dbg);
491}
diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h
new file mode 100644
index 000000000000..3574cc375bb9
--- /dev/null
+++ b/drivers/misc/mic/host/mic_device.h
@@ -0,0 +1,203 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#ifndef _MIC_DEVICE_H_
22#define _MIC_DEVICE_H_
23
24#include <linux/cdev.h>
25#include <linux/idr.h>
26#include <linux/notifier.h>
27
28#include "mic_intr.h"
29
30/* The maximum number of MIC devices supported in a single host system. */
31#define MIC_MAX_NUM_DEVS 256
32
33/**
34 * enum mic_hw_family - The hardware family to which a device belongs.
35 */
36enum mic_hw_family {
37 MIC_FAMILY_X100 = 0,
38 MIC_FAMILY_UNKNOWN
39};
40
41/**
42 * enum mic_stepping - MIC stepping ids.
43 */
44enum mic_stepping {
45 MIC_A0_STEP = 0x0,
46 MIC_B0_STEP = 0x10,
47 MIC_B1_STEP = 0x11,
48 MIC_C0_STEP = 0x20,
49};
50
51/**
52 * struct mic_device - MIC device information for each card.
53 *
54 * @mmio: MMIO bar information.
55 * @aper: Aperture bar information.
56 * @family: The MIC family to which this device belongs.
57 * @ops: MIC HW specific operations.
58 * @id: The unique device id for this MIC device.
59 * @stepping: Stepping ID.
60 * @attr_group: Pointer to list of sysfs attribute groups.
61 * @sdev: Device for sysfs entries.
62 * @mic_mutex: Mutex for synchronizing access to mic_device.
63 * @intr_ops: HW specific interrupt operations.
64 * @smpt_ops: Hardware specific SMPT operations.
65 * @smpt: MIC SMPT information.
66 * @intr_info: H/W specific interrupt information.
67 * @irq_info: The OS specific irq information
68 * @dbg_dir: debugfs directory of this MIC device.
69 * @cmdline: Kernel command line.
70 * @firmware: Firmware file name.
71 * @ramdisk: Ramdisk file name.
72 * @bootmode: Boot mode i.e. "linux" or "elf" for flash updates.
73 * @bootaddr: MIC boot address.
74 * @reset_trigger_work: Work for triggering reset requests.
75 * @shutdown_work: Work for handling shutdown interrupts.
76 * @state: MIC state.
77 * @shutdown_status: MIC status reported by card for shutdown/crashes.
78 * @state_sysfs: Sysfs dirent for notifying ring 3 about MIC state changes.
79 * @reset_wait: Waitqueue for sleeping while reset completes.
80 * @log_buf_addr: Log buffer address for MIC.
81 * @log_buf_len: Log buffer length address for MIC.
82 * @dp: virtio device page
83 * @dp_dma_addr: virtio device page DMA address.
84 * @shutdown_db: shutdown doorbell.
85 * @shutdown_cookie: shutdown cookie.
86 * @cdev: Character device for MIC.
87 * @vdev_list: list of virtio devices.
88 * @pm_notifier: Handles PM notifications from the OS.
89 */
90struct mic_device {
91 struct mic_mw mmio;
92 struct mic_mw aper;
93 enum mic_hw_family family;
94 struct mic_hw_ops *ops;
95 int id;
96 enum mic_stepping stepping;
97 const struct attribute_group **attr_group;
98 struct device *sdev;
99 struct mutex mic_mutex;
100 struct mic_hw_intr_ops *intr_ops;
101 struct mic_smpt_ops *smpt_ops;
102 struct mic_smpt_info *smpt;
103 struct mic_intr_info *intr_info;
104 struct mic_irq_info irq_info;
105 struct dentry *dbg_dir;
106 char *cmdline;
107 char *firmware;
108 char *ramdisk;
109 char *bootmode;
110 u32 bootaddr;
111 struct work_struct reset_trigger_work;
112 struct work_struct shutdown_work;
113 u8 state;
114 u8 shutdown_status;
115 struct sysfs_dirent *state_sysfs;
116 struct completion reset_wait;
117 void *log_buf_addr;
118 int *log_buf_len;
119 void *dp;
120 dma_addr_t dp_dma_addr;
121 int shutdown_db;
122 struct mic_irq *shutdown_cookie;
123 struct cdev cdev;
124 struct list_head vdev_list;
125 struct notifier_block pm_notifier;
126};
127
128/**
129 * struct mic_hw_ops - MIC HW specific operations.
130 * @aper_bar: Aperture bar resource number.
131 * @mmio_bar: MMIO bar resource number.
132 * @read_spad: Read from scratch pad register.
133 * @write_spad: Write to scratch pad register.
134 * @send_intr: Send an interrupt for a particular doorbell on the card.
135 * @ack_interrupt: Hardware specific operations to ack the h/w on
136 * receipt of an interrupt.
137 * @reset: Reset the remote processor.
138 * @reset_fw_ready: Reset firmware ready field.
139 * @is_fw_ready: Check if firmware is ready for OS download.
140 * @send_firmware_intr: Send an interrupt to the card firmware.
141 * @load_mic_fw: Load firmware segments required to boot the card
142 * into card memory. This includes the kernel, command line, ramdisk etc.
143 * @get_postcode: Get post code status from firmware.
144 */
145struct mic_hw_ops {
146 u8 aper_bar;
147 u8 mmio_bar;
148 u32 (*read_spad)(struct mic_device *mdev, unsigned int idx);
149 void (*write_spad)(struct mic_device *mdev, unsigned int idx, u32 val);
150 void (*send_intr)(struct mic_device *mdev, int doorbell);
151 u32 (*ack_interrupt)(struct mic_device *mdev);
152 void (*reset)(struct mic_device *mdev);
153 void (*reset_fw_ready)(struct mic_device *mdev);
154 bool (*is_fw_ready)(struct mic_device *mdev);
155 void (*send_firmware_intr)(struct mic_device *mdev);
156 int (*load_mic_fw)(struct mic_device *mdev, const char *buf);
157 u32 (*get_postcode)(struct mic_device *mdev);
158};
159
160/**
161 * mic_mmio_read - read from an MMIO register.
162 * @mw: MMIO register base virtual address.
163 * @offset: register offset.
164 *
165 * RETURNS: register value.
166 */
167static inline u32 mic_mmio_read(struct mic_mw *mw, u32 offset)
168{
169 return ioread32(mw->va + offset);
170}
171
172/**
173 * mic_mmio_write - write to an MMIO register.
174 * @mw: MMIO register base virtual address.
175 * @val: the data value to put into the register
176 * @offset: register offset.
177 *
178 * RETURNS: none.
179 */
180static inline void
181mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
182{
183 iowrite32(val, mw->va + offset);
184}
185
186void mic_sysfs_init(struct mic_device *mdev);
187int mic_start(struct mic_device *mdev, const char *buf);
188void mic_stop(struct mic_device *mdev, bool force);
189void mic_shutdown(struct mic_device *mdev);
190void mic_reset_delayed_work(struct work_struct *work);
191void mic_reset_trigger_work(struct work_struct *work);
192void mic_shutdown_work(struct work_struct *work);
193void mic_bootparam_init(struct mic_device *mdev);
194void mic_set_state(struct mic_device *mdev, u8 state);
195void mic_set_shutdown_status(struct mic_device *mdev, u8 status);
196void mic_create_debug_dir(struct mic_device *dev);
197void mic_delete_debug_dir(struct mic_device *dev);
198void __init mic_init_debugfs(void);
199void mic_exit_debugfs(void);
200void mic_prepare_suspend(struct mic_device *mdev);
201void mic_complete_resume(struct mic_device *mdev);
202void mic_suspend(struct mic_device *mdev);
203#endif
diff --git a/drivers/misc/mic/host/mic_fops.c b/drivers/misc/mic/host/mic_fops.c
new file mode 100644
index 000000000000..85776d7327f3
--- /dev/null
+++ b/drivers/misc/mic/host/mic_fops.c
@@ -0,0 +1,222 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#include <linux/poll.h>
22#include <linux/pci.h>
23
24#include <linux/mic_common.h>
25#include "../common/mic_dev.h"
26#include "mic_device.h"
27#include "mic_fops.h"
28#include "mic_virtio.h"
29
30int mic_open(struct inode *inode, struct file *f)
31{
32 struct mic_vdev *mvdev;
33 struct mic_device *mdev = container_of(inode->i_cdev,
34 struct mic_device, cdev);
35
36 mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL);
37 if (!mvdev)
38 return -ENOMEM;
39
40 init_waitqueue_head(&mvdev->waitq);
41 INIT_LIST_HEAD(&mvdev->list);
42 mvdev->mdev = mdev;
43 mvdev->virtio_id = -1;
44
45 f->private_data = mvdev;
46 return 0;
47}
48
49int mic_release(struct inode *inode, struct file *f)
50{
51 struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
52
53 if (-1 != mvdev->virtio_id)
54 mic_virtio_del_device(mvdev);
55 f->private_data = NULL;
56 kfree(mvdev);
57 return 0;
58}
59
60long mic_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
61{
62 struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
63 void __user *argp = (void __user *)arg;
64 int ret;
65
66 switch (cmd) {
67 case MIC_VIRTIO_ADD_DEVICE:
68 {
69 ret = mic_virtio_add_device(mvdev, argp);
70 if (ret < 0) {
71 dev_err(mic_dev(mvdev),
72 "%s %d errno ret %d\n",
73 __func__, __LINE__, ret);
74 return ret;
75 }
76 break;
77 }
78 case MIC_VIRTIO_COPY_DESC:
79 {
80 struct mic_copy_desc copy;
81
82 ret = mic_vdev_inited(mvdev);
83 if (ret)
84 return ret;
85
86 if (copy_from_user(&copy, argp, sizeof(copy)))
87 return -EFAULT;
88
89 dev_dbg(mic_dev(mvdev),
90 "%s %d === iovcnt 0x%x vr_idx 0x%x update_used %d\n",
91 __func__, __LINE__, copy.iovcnt, copy.vr_idx,
92 copy.update_used);
93
94 ret = mic_virtio_copy_desc(mvdev, &copy);
95 if (ret < 0) {
96 dev_err(mic_dev(mvdev),
97 "%s %d errno ret %d\n",
98 __func__, __LINE__, ret);
99 return ret;
100 }
101 if (copy_to_user(
102 &((struct mic_copy_desc __user *)argp)->out_len,
103 &copy.out_len, sizeof(copy.out_len))) {
104 dev_err(mic_dev(mvdev), "%s %d errno ret %d\n",
105 __func__, __LINE__, -EFAULT);
106 return -EFAULT;
107 }
108 break;
109 }
110 case MIC_VIRTIO_CONFIG_CHANGE:
111 {
112 ret = mic_vdev_inited(mvdev);
113 if (ret)
114 return ret;
115
116 ret = mic_virtio_config_change(mvdev, argp);
117 if (ret < 0) {
118 dev_err(mic_dev(mvdev),
119 "%s %d errno ret %d\n",
120 __func__, __LINE__, ret);
121 return ret;
122 }
123 break;
124 }
125 default:
126 return -ENOIOCTLCMD;
127 };
128 return 0;
129}
130
131/*
132 * We return POLLIN | POLLOUT from poll when new buffers are enqueued, and
133 * not when previously enqueued buffers may be available. This means that
134 * in the card->host (TX) path, when userspace is unblocked by poll it
135 * must drain all available descriptors or it can stall.
136 */
137unsigned int mic_poll(struct file *f, poll_table *wait)
138{
139 struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
140 int mask = 0;
141
142 poll_wait(f, &mvdev->waitq, wait);
143
144 if (mic_vdev_inited(mvdev)) {
145 mask = POLLERR;
146 } else if (mvdev->poll_wake) {
147 mvdev->poll_wake = 0;
148 mask = POLLIN | POLLOUT;
149 }
150
151 return mask;
152}
153
154static inline int
155mic_query_offset(struct mic_vdev *mvdev, unsigned long offset,
156 unsigned long *size, unsigned long *pa)
157{
158 struct mic_device *mdev = mvdev->mdev;
159 unsigned long start = MIC_DP_SIZE;
160 int i;
161
162 /*
163 * MMAP interface is as follows:
164 * offset region
165 * 0x0 virtio device_page
166 * 0x1000 first vring
167 * 0x1000 + size of 1st vring second vring
168 * ....
169 */
170 if (!offset) {
171 *pa = virt_to_phys(mdev->dp);
172 *size = MIC_DP_SIZE;
173 return 0;
174 }
175
176 for (i = 0; i < mvdev->dd->num_vq; i++) {
177 struct mic_vringh *mvr = &mvdev->mvr[i];
178 if (offset == start) {
179 *pa = virt_to_phys(mvr->vring.va);
180 *size = mvr->vring.len;
181 return 0;
182 }
183 start += mvr->vring.len;
184 }
185 return -1;
186}
187
188/*
189 * Maps the device page and virtio rings to user space for readonly access.
190 */
191int
192mic_mmap(struct file *f, struct vm_area_struct *vma)
193{
194 struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
195 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
196 unsigned long pa, size = vma->vm_end - vma->vm_start, size_rem = size;
197 int i, err;
198
199 err = mic_vdev_inited(mvdev);
200 if (err)
201 return err;
202
203 if (vma->vm_flags & VM_WRITE)
204 return -EACCES;
205
206 while (size_rem) {
207 i = mic_query_offset(mvdev, offset, &size, &pa);
208 if (i < 0)
209 return -EINVAL;
210 err = remap_pfn_range(vma, vma->vm_start + offset,
211 pa >> PAGE_SHIFT, size, vma->vm_page_prot);
212 if (err)
213 return err;
214 dev_dbg(mic_dev(mvdev),
215 "%s %d type %d size 0x%lx off 0x%lx pa 0x%lx vma 0x%lx\n",
216 __func__, __LINE__, mvdev->virtio_id, size, offset,
217 pa, vma->vm_start + offset);
218 size_rem -= size;
219 offset += size;
220 }
221 return 0;
222}
diff --git a/drivers/misc/mic/host/mic_fops.h b/drivers/misc/mic/host/mic_fops.h
new file mode 100644
index 000000000000..dc3893dff667
--- /dev/null
+++ b/drivers/misc/mic/host/mic_fops.h
@@ -0,0 +1,32 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#ifndef _MIC_FOPS_H_
22#define _MIC_FOPS_H_
23
24int mic_open(struct inode *inode, struct file *filp);
25int mic_release(struct inode *inode, struct file *filp);
26ssize_t mic_read(struct file *filp, char __user *buf,
27 size_t count, loff_t *pos);
28long mic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
29int mic_mmap(struct file *f, struct vm_area_struct *vma);
30unsigned int mic_poll(struct file *f, poll_table *wait);
31
32#endif
diff --git a/drivers/misc/mic/host/mic_intr.c b/drivers/misc/mic/host/mic_intr.c
new file mode 100644
index 000000000000..f9c29bc918bc
--- /dev/null
+++ b/drivers/misc/mic/host/mic_intr.c
@@ -0,0 +1,630 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#include <linux/pci.h>
22#include <linux/interrupt.h>
23
24#include "../common/mic_dev.h"
25#include "mic_device.h"
26
27/*
28 * mic_invoke_callback - Invoke callback functions registered for
29 * the corresponding source id.
30 *
31 * @mdev: pointer to the mic_device instance
32 * @idx: The interrupt source id.
33 *
34 * Returns none.
35 */
36static inline void mic_invoke_callback(struct mic_device *mdev, int idx)
37{
38 struct mic_intr_cb *intr_cb;
39 struct pci_dev *pdev = container_of(mdev->sdev->parent,
40 struct pci_dev, dev);
41
42 spin_lock(&mdev->irq_info.mic_intr_lock);
43 list_for_each_entry(intr_cb, &mdev->irq_info.cb_list[idx], list)
44 if (intr_cb->func)
45 intr_cb->func(pdev->irq, intr_cb->data);
46 spin_unlock(&mdev->irq_info.mic_intr_lock);
47}
48
49/**
50 * mic_interrupt - Generic interrupt handler for
51 * MSI and INTx based interrupts.
52 */
53static irqreturn_t mic_interrupt(int irq, void *dev)
54{
55 struct mic_device *mdev = dev;
56 struct mic_intr_info *info = mdev->intr_info;
57 u32 mask;
58 int i;
59
60 mask = mdev->ops->ack_interrupt(mdev);
61 if (!mask)
62 return IRQ_NONE;
63
64 for (i = info->intr_start_idx[MIC_INTR_DB];
65 i < info->intr_len[MIC_INTR_DB]; i++)
66 if (mask & BIT(i))
67 mic_invoke_callback(mdev, i);
68
69 return IRQ_HANDLED;
70}
71
72/* Return the interrupt offset from the index. Index is 0 based. */
73static u16 mic_map_src_to_offset(struct mic_device *mdev,
74 int intr_src, enum mic_intr_type type)
75{
76 if (type >= MIC_NUM_INTR_TYPES)
77 return MIC_NUM_OFFSETS;
78 if (intr_src >= mdev->intr_info->intr_len[type])
79 return MIC_NUM_OFFSETS;
80
81 return mdev->intr_info->intr_start_idx[type] + intr_src;
82}
83
84/* Return next available msix_entry. */
85static struct msix_entry *mic_get_available_vector(struct mic_device *mdev)
86{
87 int i;
88 struct mic_irq_info *info = &mdev->irq_info;
89
90 for (i = 0; i < info->num_vectors; i++)
91 if (!info->mic_msi_map[i])
92 return &info->msix_entries[i];
93 return NULL;
94}
95
96/**
97 * mic_register_intr_callback - Register a callback handler for the
98 * given source id.
99 *
100 * @mdev: pointer to the mic_device instance
101 * @idx: The source id to be registered.
102 * @func: The function to be called when the source id receives
103 * the interrupt.
104 * @data: Private data of the requester.
105 * Return the callback structure that was registered or an
106 * appropriate error on failure.
107 */
108static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev,
109 u8 idx, irqreturn_t (*func) (int irq, void *dev),
110 void *data)
111{
112 struct mic_intr_cb *intr_cb;
113 unsigned long flags;
114 int rc;
115 intr_cb = kmalloc(sizeof(*intr_cb), GFP_KERNEL);
116
117 if (!intr_cb)
118 return ERR_PTR(-ENOMEM);
119
120 intr_cb->func = func;
121 intr_cb->data = data;
122 intr_cb->cb_id = ida_simple_get(&mdev->irq_info.cb_ida,
123 0, 0, GFP_KERNEL);
124 if (intr_cb->cb_id < 0) {
125 rc = intr_cb->cb_id;
126 goto ida_fail;
127 }
128
129 spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
130 list_add_tail(&intr_cb->list, &mdev->irq_info.cb_list[idx]);
131 spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
132
133 return intr_cb;
134ida_fail:
135 kfree(intr_cb);
136 return ERR_PTR(rc);
137}
138
139/**
140 * mic_unregister_intr_callback - Unregister the callback handler
141 * identified by its callback id.
142 *
143 * @mdev: pointer to the mic_device instance
144 * @idx: The callback structure id to be unregistered.
145 * Return the source id that was unregistered or MIC_NUM_OFFSETS if no
146 * such callback handler was found.
147 */
148static u8 mic_unregister_intr_callback(struct mic_device *mdev, u32 idx)
149{
150 struct list_head *pos, *tmp;
151 struct mic_intr_cb *intr_cb;
152 unsigned long flags;
153 int i;
154
155 for (i = 0; i < MIC_NUM_OFFSETS; i++) {
156 spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
157 list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
158 intr_cb = list_entry(pos, struct mic_intr_cb, list);
159 if (intr_cb->cb_id == idx) {
160 list_del(pos);
161 ida_simple_remove(&mdev->irq_info.cb_ida,
162 intr_cb->cb_id);
163 kfree(intr_cb);
164 spin_unlock_irqrestore(
165 &mdev->irq_info.mic_intr_lock, flags);
166 return i;
167 }
168 }
169 spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
170 }
171 return MIC_NUM_OFFSETS;
172}
173
174/**
175 * mic_setup_msix - Initializes MSIx interrupts.
176 *
177 * @mdev: pointer to mic_device instance
178 *
179 *
180 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
181 */
182static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev)
183{
184 int rc, i;
185 int entry_size = sizeof(*mdev->irq_info.msix_entries);
186
187 mdev->irq_info.msix_entries = kmalloc_array(MIC_MIN_MSIX,
188 entry_size, GFP_KERNEL);
189 if (!mdev->irq_info.msix_entries) {
190 rc = -ENOMEM;
191 goto err_nomem1;
192 }
193
194 for (i = 0; i < MIC_MIN_MSIX; i++)
195 mdev->irq_info.msix_entries[i].entry = i;
196
197 rc = pci_enable_msix(pdev, mdev->irq_info.msix_entries,
198 MIC_MIN_MSIX);
199 if (rc) {
200 dev_dbg(&pdev->dev, "Error enabling MSIx. rc = %d\n", rc);
201 goto err_enable_msix;
202 }
203
204 mdev->irq_info.num_vectors = MIC_MIN_MSIX;
205 mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
206 mdev->irq_info.num_vectors), GFP_KERNEL);
207
208 if (!mdev->irq_info.mic_msi_map) {
209 rc = -ENOMEM;
210 goto err_nomem2;
211 }
212
213 dev_dbg(mdev->sdev->parent,
214 "%d MSIx irqs setup\n", mdev->irq_info.num_vectors);
215 return 0;
216err_nomem2:
217 pci_disable_msix(pdev);
218err_enable_msix:
219 kfree(mdev->irq_info.msix_entries);
220err_nomem1:
221 mdev->irq_info.num_vectors = 0;
222 return rc;
223}
224
225/**
226 * mic_setup_callbacks - Initialize data structures needed
227 * to handle callbacks.
228 *
229 * @mdev: pointer to mic_device instance
230 */
231static int mic_setup_callbacks(struct mic_device *mdev)
232{
233 int i;
234
235 mdev->irq_info.cb_list = kmalloc_array(MIC_NUM_OFFSETS,
236 sizeof(*mdev->irq_info.cb_list),
237 GFP_KERNEL);
238 if (!mdev->irq_info.cb_list)
239 return -ENOMEM;
240
241 for (i = 0; i < MIC_NUM_OFFSETS; i++)
242 INIT_LIST_HEAD(&mdev->irq_info.cb_list[i]);
243 ida_init(&mdev->irq_info.cb_ida);
244 spin_lock_init(&mdev->irq_info.mic_intr_lock);
245 return 0;
246}
247
248/**
249 * mic_release_callbacks - Uninitialize data structures needed
250 * to handle callbacks.
251 *
252 * @mdev: pointer to mic_device instance
253 */
254static void mic_release_callbacks(struct mic_device *mdev)
255{
256 unsigned long flags;
257 struct list_head *pos, *tmp;
258 struct mic_intr_cb *intr_cb;
259 int i;
260
261 for (i = 0; i < MIC_NUM_OFFSETS; i++) {
262 spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
263
264 if (list_empty(&mdev->irq_info.cb_list[i])) {
265 spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock,
266 flags);
267 break;
268 }
269
270 list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
271 intr_cb = list_entry(pos, struct mic_intr_cb, list);
272 list_del(pos);
273 ida_simple_remove(&mdev->irq_info.cb_ida,
274 intr_cb->cb_id);
275 kfree(intr_cb);
276 }
277 spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
278 }
279 ida_destroy(&mdev->irq_info.cb_ida);
280 kfree(mdev->irq_info.cb_list);
281}
282
283/**
284 * mic_setup_msi - Initializes MSI interrupts.
285 *
286 * @mdev: pointer to mic_device instance
287 * @pdev: PCI device structure
288 *
289 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
290 */
291static int mic_setup_msi(struct mic_device *mdev, struct pci_dev *pdev)
292{
293 int rc;
294
295 rc = pci_enable_msi(pdev);
296 if (rc) {
297 dev_dbg(&pdev->dev, "Error enabling MSI. rc = %d\n", rc);
298 return rc;
299 }
300
301 mdev->irq_info.num_vectors = 1;
302 mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
303 mdev->irq_info.num_vectors), GFP_KERNEL);
304
305 if (!mdev->irq_info.mic_msi_map) {
306 rc = -ENOMEM;
307 goto err_nomem1;
308 }
309
310 rc = mic_setup_callbacks(mdev);
311 if (rc) {
312 dev_err(&pdev->dev, "Error setting up callbacks\n");
313 goto err_nomem2;
314 }
315
316 rc = request_irq(pdev->irq, mic_interrupt, 0 , "mic-msi", mdev);
317 if (rc) {
318 dev_err(&pdev->dev, "Error allocating MSI interrupt\n");
319 goto err_irq_req_fail;
320 }
321
322 dev_dbg(&pdev->dev, "%d MSI irqs setup\n", mdev->irq_info.num_vectors);
323 return 0;
324err_irq_req_fail:
325 mic_release_callbacks(mdev);
326err_nomem2:
327 kfree(mdev->irq_info.mic_msi_map);
328err_nomem1:
329 pci_disable_msi(pdev);
330 mdev->irq_info.num_vectors = 0;
331 return rc;
332}
333
334/**
335 * mic_setup_intx - Initializes legacy interrupts.
336 *
337 * @mdev: pointer to mic_device instance
338 * @pdev: PCI device structure
339 *
340 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
341 */
342static int mic_setup_intx(struct mic_device *mdev, struct pci_dev *pdev)
343{
344 int rc;
345
346 pci_msi_off(pdev);
347
348 /* Enable intx */
349 pci_intx(pdev, 1);
350 rc = mic_setup_callbacks(mdev);
351 if (rc) {
352 dev_err(&pdev->dev, "Error setting up callbacks\n");
353 goto err_nomem;
354 }
355
356 rc = request_irq(pdev->irq, mic_interrupt,
357 IRQF_SHARED, "mic-intx", mdev);
358 if (rc)
359 goto err;
360
361 dev_dbg(&pdev->dev, "intx irq setup\n");
362 return 0;
363err:
364 mic_release_callbacks(mdev);
365err_nomem:
366 return rc;
367}
368
369/**
370 * mic_next_db - Retrieve the next doorbell interrupt source id.
371 * The id is picked sequentially from the available pool of
372 * doorlbell ids.
373 *
374 * @mdev: pointer to the mic_device instance.
375 *
376 * Returns the next doorbell interrupt source.
377 */
378int mic_next_db(struct mic_device *mdev)
379{
380 int next_db;
381
382 next_db = mdev->irq_info.next_avail_src %
383 mdev->intr_info->intr_len[MIC_INTR_DB];
384 mdev->irq_info.next_avail_src++;
385 return next_db;
386}
387
388#define COOKIE_ID_SHIFT 16
389#define GET_ENTRY(cookie) ((cookie) & 0xFFFF)
390#define GET_OFFSET(cookie) ((cookie) >> COOKIE_ID_SHIFT)
391#define MK_COOKIE(x, y) ((x) | (y) << COOKIE_ID_SHIFT)
392
393/**
394 * mic_request_irq - request an irq. mic_mutex needs
395 * to be held before calling this function.
396 *
397 * @mdev: pointer to mic_device instance
398 * @func: The callback function that handles the interrupt.
399 * The function needs to call ack_interrupts
400 * (mdev->ops->ack_interrupt(mdev)) when handling the interrupts.
401 * @name: The ASCII name of the callee requesting the irq.
402 * @data: private data that is returned back when calling the
403 * function handler.
404 * @intr_src: The source id of the requester. Its the doorbell id
405 * for Doorbell interrupts and DMA channel id for DMA interrupts.
406 * @type: The type of interrupt. Values defined in mic_intr_type
407 *
408 * returns: The cookie that is transparent to the caller. Passed
409 * back when calling mic_free_irq. An appropriate error code
410 * is returned on failure. Caller needs to use IS_ERR(return_val)
411 * to check for failure and PTR_ERR(return_val) to obtained the
412 * error code.
413 *
414 */
415struct mic_irq *mic_request_irq(struct mic_device *mdev,
416 irqreturn_t (*func)(int irq, void *dev),
417 const char *name, void *data, int intr_src,
418 enum mic_intr_type type)
419{
420 u16 offset;
421 int rc = 0;
422 struct msix_entry *msix = NULL;
423 unsigned long cookie = 0;
424 u16 entry;
425 struct mic_intr_cb *intr_cb;
426 struct pci_dev *pdev = container_of(mdev->sdev->parent,
427 struct pci_dev, dev);
428
429 offset = mic_map_src_to_offset(mdev, intr_src, type);
430 if (offset >= MIC_NUM_OFFSETS) {
431 dev_err(mdev->sdev->parent,
432 "Error mapping index %d to a valid source id.\n",
433 intr_src);
434 rc = -EINVAL;
435 goto err;
436 }
437
438 if (mdev->irq_info.num_vectors > 1) {
439 msix = mic_get_available_vector(mdev);
440 if (!msix) {
441 dev_err(mdev->sdev->parent,
442 "No MSIx vectors available for use.\n");
443 rc = -ENOSPC;
444 goto err;
445 }
446
447 rc = request_irq(msix->vector, func, 0, name, data);
448 if (rc) {
449 dev_dbg(mdev->sdev->parent,
450 "request irq failed rc = %d\n", rc);
451 goto err;
452 }
453 entry = msix->entry;
454 mdev->irq_info.mic_msi_map[entry] |= BIT(offset);
455 mdev->intr_ops->program_msi_to_src_map(mdev,
456 entry, offset, true);
457 cookie = MK_COOKIE(entry, offset);
458 dev_dbg(mdev->sdev->parent, "irq: %d assigned for src: %d\n",
459 msix->vector, intr_src);
460 } else {
461 intr_cb = mic_register_intr_callback(mdev,
462 offset, func, data);
463 if (IS_ERR(intr_cb)) {
464 dev_err(mdev->sdev->parent,
465 "No available callback entries for use\n");
466 rc = PTR_ERR(intr_cb);
467 goto err;
468 }
469
470 entry = 0;
471 if (pci_dev_msi_enabled(pdev)) {
472 mdev->irq_info.mic_msi_map[entry] |= (1 << offset);
473 mdev->intr_ops->program_msi_to_src_map(mdev,
474 entry, offset, true);
475 }
476 cookie = MK_COOKIE(entry, intr_cb->cb_id);
477 dev_dbg(mdev->sdev->parent, "callback %d registered for src: %d\n",
478 intr_cb->cb_id, intr_src);
479 }
480 return (struct mic_irq *)cookie;
481err:
482 return ERR_PTR(rc);
483}
484
485/**
486 * mic_free_irq - free irq. mic_mutex
487 * needs to be held before calling this function.
488 *
489 * @mdev: pointer to mic_device instance
490 * @cookie: cookie obtained during a successful call to mic_request_irq
491 * @data: private data specified by the calling function during the
492 * mic_request_irq
493 *
494 * returns: none.
495 */
496void mic_free_irq(struct mic_device *mdev,
497 struct mic_irq *cookie, void *data)
498{
499 u32 offset;
500 u32 entry;
501 u8 src_id;
502 unsigned int irq;
503 struct pci_dev *pdev = container_of(mdev->sdev->parent,
504 struct pci_dev, dev);
505
506 entry = GET_ENTRY((unsigned long)cookie);
507 offset = GET_OFFSET((unsigned long)cookie);
508 if (mdev->irq_info.num_vectors > 1) {
509 if (entry >= mdev->irq_info.num_vectors) {
510 dev_warn(mdev->sdev->parent,
511 "entry %d should be < num_irq %d\n",
512 entry, mdev->irq_info.num_vectors);
513 return;
514 }
515 irq = mdev->irq_info.msix_entries[entry].vector;
516 free_irq(irq, data);
517 mdev->irq_info.mic_msi_map[entry] &= ~(BIT(offset));
518 mdev->intr_ops->program_msi_to_src_map(mdev,
519 entry, offset, false);
520
521 dev_dbg(mdev->sdev->parent, "irq: %d freed\n", irq);
522 } else {
523 irq = pdev->irq;
524 src_id = mic_unregister_intr_callback(mdev, offset);
525 if (src_id >= MIC_NUM_OFFSETS) {
526 dev_warn(mdev->sdev->parent, "Error unregistering callback\n");
527 return;
528 }
529 if (pci_dev_msi_enabled(pdev)) {
530 mdev->irq_info.mic_msi_map[entry] &= ~(BIT(src_id));
531 mdev->intr_ops->program_msi_to_src_map(mdev,
532 entry, src_id, false);
533 }
534 dev_dbg(mdev->sdev->parent, "callback %d unregistered for src: %d\n",
535 offset, src_id);
536 }
537}
538
539/**
540 * mic_setup_interrupts - Initializes interrupts.
541 *
542 * @mdev: pointer to mic_device instance
543 * @pdev: PCI device structure
544 *
545 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
546 */
547int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
548{
549 int rc;
550
551 rc = mic_setup_msix(mdev, pdev);
552 if (!rc)
553 goto done;
554
555 rc = mic_setup_msi(mdev, pdev);
556 if (!rc)
557 goto done;
558
559 rc = mic_setup_intx(mdev, pdev);
560 if (rc) {
561 dev_err(mdev->sdev->parent, "no usable interrupts\n");
562 return rc;
563 }
564done:
565 mdev->intr_ops->enable_interrupts(mdev);
566 return 0;
567}
568
569/**
570 * mic_free_interrupts - Frees interrupts setup by mic_setup_interrupts
571 *
572 * @mdev: pointer to mic_device instance
573 * @pdev: PCI device structure
574 *
575 * returns none.
576 */
577void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
578{
579 int i;
580
581 mdev->intr_ops->disable_interrupts(mdev);
582 if (mdev->irq_info.num_vectors > 1) {
583 for (i = 0; i < mdev->irq_info.num_vectors; i++) {
584 if (mdev->irq_info.mic_msi_map[i])
585 dev_warn(&pdev->dev, "irq %d may still be in use.\n",
586 mdev->irq_info.msix_entries[i].vector);
587 }
588 kfree(mdev->irq_info.mic_msi_map);
589 kfree(mdev->irq_info.msix_entries);
590 pci_disable_msix(pdev);
591 } else {
592 if (pci_dev_msi_enabled(pdev)) {
593 free_irq(pdev->irq, mdev);
594 kfree(mdev->irq_info.mic_msi_map);
595 pci_disable_msi(pdev);
596 } else {
597 free_irq(pdev->irq, mdev);
598 }
599 mic_release_callbacks(mdev);
600 }
601}
602
603/**
604 * mic_intr_restore - Restore MIC interrupt registers.
605 *
606 * @mdev: pointer to mic_device instance.
607 *
608 * Restore the interrupt registers to values previously
609 * stored in the SW data structures. mic_mutex needs to
610 * be held before calling this function.
611 *
612 * returns None.
613 */
614void mic_intr_restore(struct mic_device *mdev)
615{
616 int entry, offset;
617 struct pci_dev *pdev = container_of(mdev->sdev->parent,
618 struct pci_dev, dev);
619
620 if (!pci_dev_msi_enabled(pdev))
621 return;
622
623 for (entry = 0; entry < mdev->irq_info.num_vectors; entry++) {
624 for (offset = 0; offset < MIC_NUM_OFFSETS; offset++) {
625 if (mdev->irq_info.mic_msi_map[entry] & BIT(offset))
626 mdev->intr_ops->program_msi_to_src_map(mdev,
627 entry, offset, true);
628 }
629 }
630}
diff --git a/drivers/misc/mic/host/mic_intr.h b/drivers/misc/mic/host/mic_intr.h
new file mode 100644
index 000000000000..6091aa97e116
--- /dev/null
+++ b/drivers/misc/mic/host/mic_intr.h
@@ -0,0 +1,137 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#ifndef _MIC_INTR_H_
22#define _MIC_INTR_H_
23
24/*
25 * The minimum number of msix vectors required for normal operation.
26 * 3 for virtio network, console and block devices.
27 * 1 for card shutdown notifications.
28 */
29#define MIC_MIN_MSIX 4
30#define MIC_NUM_OFFSETS 32
31
32/**
33 * mic_intr_source - The type of source that will generate
34 * the interrupt.The number of types needs to be in sync with
35 * MIC_NUM_INTR_TYPES
36 *
37 * MIC_INTR_DB: The source is a doorbell
38 * MIC_INTR_DMA: The source is a DMA channel
39 * MIC_INTR_ERR: The source is an error interrupt e.g. SBOX ERR
40 * MIC_NUM_INTR_TYPES: Total number of interrupt sources.
41 */
42enum mic_intr_type {
43 MIC_INTR_DB = 0,
44 MIC_INTR_DMA,
45 MIC_INTR_ERR,
46 MIC_NUM_INTR_TYPES
47};
48
49/**
50 * struct mic_intr_info - Contains h/w specific interrupt sources
51 * information.
52 *
53 * @intr_start_idx: Contains the starting indexes of the
54 * interrupt types.
55 * @intr_len: Contains the length of the interrupt types.
56 */
57struct mic_intr_info {
58 u16 intr_start_idx[MIC_NUM_INTR_TYPES];
59 u16 intr_len[MIC_NUM_INTR_TYPES];
60};
61
62/**
63 * struct mic_irq_info - OS specific irq information
64 *
65 * @next_avail_src: next available doorbell that can be assigned.
66 * @msix_entries: msix entries allocated while setting up MSI-x
67 * @mic_msi_map: The MSI/MSI-x mapping information.
68 * @num_vectors: The number of MSI/MSI-x vectors that have been allocated.
69 * @cb_ida: callback ID allocator to track the callbacks registered.
70 * @mic_intr_lock: spinlock to protect the interrupt callback list.
71 * @cb_list: Array of callback lists one for each source.
72 */
73struct mic_irq_info {
74 int next_avail_src;
75 struct msix_entry *msix_entries;
76 u32 *mic_msi_map;
77 u16 num_vectors;
78 struct ida cb_ida;
79 spinlock_t mic_intr_lock;
80 struct list_head *cb_list;
81};
82
83/**
84 * struct mic_intr_cb - Interrupt callback structure.
85 *
86 * @func: The callback function
87 * @data: Private data of the requester.
88 * @cb_id: The callback id. Identifies this callback.
89 * @list: list head pointing to the next callback structure.
90 */
91struct mic_intr_cb {
92 irqreturn_t (*func) (int irq, void *data);
93 void *data;
94 int cb_id;
95 struct list_head list;
96};
97
98/**
99 * struct mic_irq - opaque pointer used as cookie
100 */
101struct mic_irq;
102
103/* Forward declaration */
104struct mic_device;
105
106/**
107 * struct mic_hw_intr_ops: MIC HW specific interrupt operations
108 * @intr_init: Initialize H/W specific interrupt information.
109 * @enable_interrupts: Enable interrupts from the hardware.
110 * @disable_interrupts: Disable interrupts from the hardware.
111 * @program_msi_to_src_map: Update MSI mapping registers with
112 * irq information.
113 * @read_msi_to_src_map: Read MSI mapping registers containing
114 * irq information.
115 */
116struct mic_hw_intr_ops {
117 void (*intr_init)(struct mic_device *mdev);
118 void (*enable_interrupts)(struct mic_device *mdev);
119 void (*disable_interrupts)(struct mic_device *mdev);
120 void (*program_msi_to_src_map) (struct mic_device *mdev,
121 int idx, int intr_src, bool set);
122 u32 (*read_msi_to_src_map) (struct mic_device *mdev,
123 int idx);
124};
125
126int mic_next_db(struct mic_device *mdev);
127struct mic_irq *mic_request_irq(struct mic_device *mdev,
128 irqreturn_t (*func)(int irq, void *data),
129 const char *name, void *data, int intr_src,
130 enum mic_intr_type type);
131
132void mic_free_irq(struct mic_device *mdev,
133 struct mic_irq *cookie, void *data);
134int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
135void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
136void mic_intr_restore(struct mic_device *mdev);
137#endif
diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c
new file mode 100644
index 000000000000..b3520859abd3
--- /dev/null
+++ b/drivers/misc/mic/host/mic_main.c
@@ -0,0 +1,537 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 * Global TODO's across the driver to be added after initial base
21 * patches are accepted upstream:
22 * 1) Enable DMA support.
23 * 2) Enable per vring interrupt support.
24 */
25#include <linux/fs.h>
26#include <linux/module.h>
27#include <linux/pci.h>
28#include <linux/poll.h>
29#include <linux/suspend.h>
30
31#include <linux/mic_common.h>
32#include "../common/mic_dev.h"
33#include "mic_device.h"
34#include "mic_x100.h"
35#include "mic_smpt.h"
36#include "mic_fops.h"
37#include "mic_virtio.h"
38
39static const char mic_driver_name[] = "mic";
40
41static DEFINE_PCI_DEVICE_TABLE(mic_pci_tbl) = {
42 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2250)},
43 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2251)},
44 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2252)},
45 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2253)},
46 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2254)},
47 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2255)},
48 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2256)},
49 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2257)},
50 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2258)},
51 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2259)},
52 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225a)},
53 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225b)},
54 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225c)},
55 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225d)},
56 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225e)},
57
58 /* required last entry */
59 { 0, }
60};
61
62MODULE_DEVICE_TABLE(pci, mic_pci_tbl);
63
64/* ID allocator for MIC devices */
65static struct ida g_mic_ida;
66/* Class of MIC devices for sysfs accessibility. */
67static struct class *g_mic_class;
68/* Base device node number for MIC devices */
69static dev_t g_mic_devno;
70
71static const struct file_operations mic_fops = {
72 .open = mic_open,
73 .release = mic_release,
74 .unlocked_ioctl = mic_ioctl,
75 .poll = mic_poll,
76 .mmap = mic_mmap,
77 .owner = THIS_MODULE,
78};
79
80/* Initialize the device page */
81static int mic_dp_init(struct mic_device *mdev)
82{
83 mdev->dp = kzalloc(MIC_DP_SIZE, GFP_KERNEL);
84 if (!mdev->dp) {
85 dev_err(mdev->sdev->parent, "%s %d err %d\n",
86 __func__, __LINE__, -ENOMEM);
87 return -ENOMEM;
88 }
89
90 mdev->dp_dma_addr = mic_map_single(mdev,
91 mdev->dp, MIC_DP_SIZE);
92 if (mic_map_error(mdev->dp_dma_addr)) {
93 kfree(mdev->dp);
94 dev_err(mdev->sdev->parent, "%s %d err %d\n",
95 __func__, __LINE__, -ENOMEM);
96 return -ENOMEM;
97 }
98 mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
99 mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
100 return 0;
101}
102
103/* Uninitialize the device page */
104static void mic_dp_uninit(struct mic_device *mdev)
105{
106 mic_unmap_single(mdev, mdev->dp_dma_addr, MIC_DP_SIZE);
107 kfree(mdev->dp);
108}
109
110/**
111 * mic_shutdown_db - Shutdown doorbell interrupt handler.
112 */
113static irqreturn_t mic_shutdown_db(int irq, void *data)
114{
115 struct mic_device *mdev = data;
116 struct mic_bootparam *bootparam = mdev->dp;
117
118 mdev->ops->ack_interrupt(mdev);
119
120 switch (bootparam->shutdown_status) {
121 case MIC_HALTED:
122 case MIC_POWER_OFF:
123 case MIC_RESTART:
124 /* Fall through */
125 case MIC_CRASHED:
126 schedule_work(&mdev->shutdown_work);
127 break;
128 default:
129 break;
130 };
131 return IRQ_HANDLED;
132}
133
134/**
135 * mic_ops_init: Initialize HW specific operation tables.
136 *
137 * @mdev: pointer to mic_device instance
138 *
139 * returns none.
140 */
141static void mic_ops_init(struct mic_device *mdev)
142{
143 switch (mdev->family) {
144 case MIC_FAMILY_X100:
145 mdev->ops = &mic_x100_ops;
146 mdev->intr_ops = &mic_x100_intr_ops;
147 mdev->smpt_ops = &mic_x100_smpt_ops;
148 break;
149 default:
150 break;
151 }
152}
153
154/**
155 * mic_get_family - Determine hardware family to which this MIC belongs.
156 *
157 * @pdev: The pci device structure
158 *
159 * returns family.
160 */
161static enum mic_hw_family mic_get_family(struct pci_dev *pdev)
162{
163 enum mic_hw_family family;
164
165 switch (pdev->device) {
166 case MIC_X100_PCI_DEVICE_2250:
167 case MIC_X100_PCI_DEVICE_2251:
168 case MIC_X100_PCI_DEVICE_2252:
169 case MIC_X100_PCI_DEVICE_2253:
170 case MIC_X100_PCI_DEVICE_2254:
171 case MIC_X100_PCI_DEVICE_2255:
172 case MIC_X100_PCI_DEVICE_2256:
173 case MIC_X100_PCI_DEVICE_2257:
174 case MIC_X100_PCI_DEVICE_2258:
175 case MIC_X100_PCI_DEVICE_2259:
176 case MIC_X100_PCI_DEVICE_225a:
177 case MIC_X100_PCI_DEVICE_225b:
178 case MIC_X100_PCI_DEVICE_225c:
179 case MIC_X100_PCI_DEVICE_225d:
180 case MIC_X100_PCI_DEVICE_225e:
181 family = MIC_FAMILY_X100;
182 break;
183 default:
184 family = MIC_FAMILY_UNKNOWN;
185 break;
186 }
187 return family;
188}
189
190/**
191* mic_pm_notifier: Notifier callback function that handles
192* PM notifications.
193*
194* @notifier_block: The notifier structure.
195* @pm_event: The event for which the driver was notified.
196* @unused: Meaningless. Always NULL.
197*
198* returns NOTIFY_DONE
199*/
200static int mic_pm_notifier(struct notifier_block *notifier,
201 unsigned long pm_event, void *unused)
202{
203 struct mic_device *mdev = container_of(notifier,
204 struct mic_device, pm_notifier);
205
206 switch (pm_event) {
207 case PM_HIBERNATION_PREPARE:
208 /* Fall through */
209 case PM_SUSPEND_PREPARE:
210 mic_prepare_suspend(mdev);
211 break;
212 case PM_POST_HIBERNATION:
213 /* Fall through */
214 case PM_POST_SUSPEND:
215 /* Fall through */
216 case PM_POST_RESTORE:
217 mic_complete_resume(mdev);
218 break;
219 case PM_RESTORE_PREPARE:
220 break;
221 default:
222 break;
223 }
224 return NOTIFY_DONE;
225}
226
227/**
228 * mic_device_init - Allocates and initializes the MIC device structure
229 *
230 * @mdev: pointer to mic_device instance
231 * @pdev: The pci device structure
232 *
233 * returns none.
234 */
235static int
236mic_device_init(struct mic_device *mdev, struct pci_dev *pdev)
237{
238 int rc;
239
240 mdev->family = mic_get_family(pdev);
241 mdev->stepping = pdev->revision;
242 mic_ops_init(mdev);
243 mic_sysfs_init(mdev);
244 mutex_init(&mdev->mic_mutex);
245 mdev->irq_info.next_avail_src = 0;
246 INIT_WORK(&mdev->reset_trigger_work, mic_reset_trigger_work);
247 INIT_WORK(&mdev->shutdown_work, mic_shutdown_work);
248 init_completion(&mdev->reset_wait);
249 INIT_LIST_HEAD(&mdev->vdev_list);
250 mdev->pm_notifier.notifier_call = mic_pm_notifier;
251 rc = register_pm_notifier(&mdev->pm_notifier);
252 if (rc) {
253 dev_err(&pdev->dev, "register_pm_notifier failed rc %d\n",
254 rc);
255 goto register_pm_notifier_fail;
256 }
257 return 0;
258register_pm_notifier_fail:
259 flush_work(&mdev->shutdown_work);
260 flush_work(&mdev->reset_trigger_work);
261 return rc;
262}
263
264/**
265 * mic_device_uninit - Frees resources allocated during mic_device_init(..)
266 *
267 * @mdev: pointer to mic_device instance
268 *
269 * returns none
270 */
271static void mic_device_uninit(struct mic_device *mdev)
272{
273 /* The cmdline sysfs entry might have allocated cmdline */
274 kfree(mdev->cmdline);
275 kfree(mdev->firmware);
276 kfree(mdev->ramdisk);
277 kfree(mdev->bootmode);
278 flush_work(&mdev->reset_trigger_work);
279 flush_work(&mdev->shutdown_work);
280 unregister_pm_notifier(&mdev->pm_notifier);
281}
282
283/**
284 * mic_probe - Device Initialization Routine
285 *
286 * @pdev: PCI device structure
287 * @ent: entry in mic_pci_tbl
288 *
289 * returns 0 on success, < 0 on failure.
290 */
291static int mic_probe(struct pci_dev *pdev,
292 const struct pci_device_id *ent)
293{
294 int rc;
295 struct mic_device *mdev;
296
297 mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
298 if (!mdev) {
299 rc = -ENOMEM;
300 dev_err(&pdev->dev, "mdev kmalloc failed rc %d\n", rc);
301 goto mdev_alloc_fail;
302 }
303 mdev->id = ida_simple_get(&g_mic_ida, 0, MIC_MAX_NUM_DEVS, GFP_KERNEL);
304 if (mdev->id < 0) {
305 rc = mdev->id;
306 dev_err(&pdev->dev, "ida_simple_get failed rc %d\n", rc);
307 goto ida_fail;
308 }
309
310 rc = mic_device_init(mdev, pdev);
311 if (rc) {
312 dev_err(&pdev->dev, "mic_device_init failed rc %d\n", rc);
313 goto device_init_fail;
314 }
315
316 rc = pci_enable_device(pdev);
317 if (rc) {
318 dev_err(&pdev->dev, "failed to enable pci device.\n");
319 goto uninit_device;
320 }
321
322 pci_set_master(pdev);
323
324 rc = pci_request_regions(pdev, mic_driver_name);
325 if (rc) {
326 dev_err(&pdev->dev, "failed to get pci regions.\n");
327 goto disable_device;
328 }
329
330 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
331 if (rc) {
332 dev_err(&pdev->dev, "Cannot set DMA mask\n");
333 goto release_regions;
334 }
335
336 mdev->mmio.pa = pci_resource_start(pdev, mdev->ops->mmio_bar);
337 mdev->mmio.len = pci_resource_len(pdev, mdev->ops->mmio_bar);
338 mdev->mmio.va = pci_ioremap_bar(pdev, mdev->ops->mmio_bar);
339 if (!mdev->mmio.va) {
340 dev_err(&pdev->dev, "Cannot remap MMIO BAR\n");
341 rc = -EIO;
342 goto release_regions;
343 }
344
345 mdev->aper.pa = pci_resource_start(pdev, mdev->ops->aper_bar);
346 mdev->aper.len = pci_resource_len(pdev, mdev->ops->aper_bar);
347 mdev->aper.va = ioremap_wc(mdev->aper.pa, mdev->aper.len);
348 if (!mdev->aper.va) {
349 dev_err(&pdev->dev, "Cannot remap Aperture BAR\n");
350 rc = -EIO;
351 goto unmap_mmio;
352 }
353
354 mdev->intr_ops->intr_init(mdev);
355 rc = mic_setup_interrupts(mdev, pdev);
356 if (rc) {
357 dev_err(&pdev->dev, "mic_setup_interrupts failed %d\n", rc);
358 goto unmap_aper;
359 }
360 rc = mic_smpt_init(mdev);
361 if (rc) {
362 dev_err(&pdev->dev, "smpt_init failed %d\n", rc);
363 goto free_interrupts;
364 }
365
366 pci_set_drvdata(pdev, mdev);
367
368 mdev->sdev = device_create_with_groups(g_mic_class, &pdev->dev,
369 MKDEV(MAJOR(g_mic_devno), mdev->id), NULL,
370 mdev->attr_group, "mic%d", mdev->id);
371 if (IS_ERR(mdev->sdev)) {
372 rc = PTR_ERR(mdev->sdev);
373 dev_err(&pdev->dev,
374 "device_create_with_groups failed rc %d\n", rc);
375 goto smpt_uninit;
376 }
377 mdev->state_sysfs = sysfs_get_dirent(mdev->sdev->kobj.sd,
378 NULL, "state");
379 if (!mdev->state_sysfs) {
380 rc = -ENODEV;
381 dev_err(&pdev->dev, "sysfs_get_dirent failed rc %d\n", rc);
382 goto destroy_device;
383 }
384
385 rc = mic_dp_init(mdev);
386 if (rc) {
387 dev_err(&pdev->dev, "mic_dp_init failed rc %d\n", rc);
388 goto sysfs_put;
389 }
390 mutex_lock(&mdev->mic_mutex);
391
392 mdev->shutdown_db = mic_next_db(mdev);
393 mdev->shutdown_cookie = mic_request_irq(mdev, mic_shutdown_db,
394 "shutdown-interrupt", mdev, mdev->shutdown_db, MIC_INTR_DB);
395 if (IS_ERR(mdev->shutdown_cookie)) {
396 rc = PTR_ERR(mdev->shutdown_cookie);
397 mutex_unlock(&mdev->mic_mutex);
398 goto dp_uninit;
399 }
400 mutex_unlock(&mdev->mic_mutex);
401 mic_bootparam_init(mdev);
402
403 mic_create_debug_dir(mdev);
404 cdev_init(&mdev->cdev, &mic_fops);
405 mdev->cdev.owner = THIS_MODULE;
406 rc = cdev_add(&mdev->cdev, MKDEV(MAJOR(g_mic_devno), mdev->id), 1);
407 if (rc) {
408 dev_err(&pdev->dev, "cdev_add err id %d rc %d\n", mdev->id, rc);
409 goto cleanup_debug_dir;
410 }
411 return 0;
412cleanup_debug_dir:
413 mic_delete_debug_dir(mdev);
414 mutex_lock(&mdev->mic_mutex);
415 mic_free_irq(mdev, mdev->shutdown_cookie, mdev);
416 mutex_unlock(&mdev->mic_mutex);
417dp_uninit:
418 mic_dp_uninit(mdev);
419sysfs_put:
420 sysfs_put(mdev->state_sysfs);
421destroy_device:
422 device_destroy(g_mic_class, MKDEV(MAJOR(g_mic_devno), mdev->id));
423smpt_uninit:
424 mic_smpt_uninit(mdev);
425free_interrupts:
426 mic_free_interrupts(mdev, pdev);
427unmap_aper:
428 iounmap(mdev->aper.va);
429unmap_mmio:
430 iounmap(mdev->mmio.va);
431release_regions:
432 pci_release_regions(pdev);
433disable_device:
434 pci_disable_device(pdev);
435uninit_device:
436 mic_device_uninit(mdev);
437device_init_fail:
438 ida_simple_remove(&g_mic_ida, mdev->id);
439ida_fail:
440 kfree(mdev);
441mdev_alloc_fail:
442 dev_err(&pdev->dev, "Probe failed rc %d\n", rc);
443 return rc;
444}
445
446/**
447 * mic_remove - Device Removal Routine
448 * mic_remove is called by the PCI subsystem to alert the driver
449 * that it should release a PCI device.
450 *
451 * @pdev: PCI device structure
452 */
453static void mic_remove(struct pci_dev *pdev)
454{
455 struct mic_device *mdev;
456
457 mdev = pci_get_drvdata(pdev);
458 if (!mdev)
459 return;
460
461 mic_stop(mdev, false);
462 cdev_del(&mdev->cdev);
463 mic_delete_debug_dir(mdev);
464 mutex_lock(&mdev->mic_mutex);
465 mic_free_irq(mdev, mdev->shutdown_cookie, mdev);
466 mutex_unlock(&mdev->mic_mutex);
467 flush_work(&mdev->shutdown_work);
468 mic_dp_uninit(mdev);
469 sysfs_put(mdev->state_sysfs);
470 device_destroy(g_mic_class, MKDEV(MAJOR(g_mic_devno), mdev->id));
471 mic_smpt_uninit(mdev);
472 mic_free_interrupts(mdev, pdev);
473 iounmap(mdev->mmio.va);
474 iounmap(mdev->aper.va);
475 mic_device_uninit(mdev);
476 pci_release_regions(pdev);
477 pci_disable_device(pdev);
478 ida_simple_remove(&g_mic_ida, mdev->id);
479 kfree(mdev);
480}
481static struct pci_driver mic_driver = {
482 .name = mic_driver_name,
483 .id_table = mic_pci_tbl,
484 .probe = mic_probe,
485 .remove = mic_remove
486};
487
488static int __init mic_init(void)
489{
490 int ret;
491
492 ret = alloc_chrdev_region(&g_mic_devno, 0,
493 MIC_MAX_NUM_DEVS, mic_driver_name);
494 if (ret) {
495 pr_err("alloc_chrdev_region failed ret %d\n", ret);
496 goto error;
497 }
498
499 g_mic_class = class_create(THIS_MODULE, mic_driver_name);
500 if (IS_ERR(g_mic_class)) {
501 ret = PTR_ERR(g_mic_class);
502 pr_err("class_create failed ret %d\n", ret);
503 goto cleanup_chrdev;
504 }
505
506 mic_init_debugfs();
507 ida_init(&g_mic_ida);
508 ret = pci_register_driver(&mic_driver);
509 if (ret) {
510 pr_err("pci_register_driver failed ret %d\n", ret);
511 goto cleanup_debugfs;
512 }
513 return ret;
514cleanup_debugfs:
515 mic_exit_debugfs();
516 class_destroy(g_mic_class);
517cleanup_chrdev:
518 unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS);
519error:
520 return ret;
521}
522
523static void __exit mic_exit(void)
524{
525 pci_unregister_driver(&mic_driver);
526 ida_destroy(&g_mic_ida);
527 mic_exit_debugfs();
528 class_destroy(g_mic_class);
529 unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS);
530}
531
532module_init(mic_init);
533module_exit(mic_exit);
534
535MODULE_AUTHOR("Intel Corporation");
536MODULE_DESCRIPTION("Intel(R) MIC X100 Host driver");
537MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/host/mic_smpt.c b/drivers/misc/mic/host/mic_smpt.c
new file mode 100644
index 000000000000..fae474c4899e
--- /dev/null
+++ b/drivers/misc/mic/host/mic_smpt.c
@@ -0,0 +1,442 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#include <linux/pci.h>
22
23#include "../common/mic_dev.h"
24#include "mic_device.h"
25#include "mic_smpt.h"
26
27static inline u64 mic_system_page_mask(struct mic_device *mdev)
28{
29 return (1ULL << mdev->smpt->info.page_shift) - 1ULL;
30}
31
32static inline u8 mic_sys_addr_to_smpt(struct mic_device *mdev, dma_addr_t pa)
33{
34 return (pa - mdev->smpt->info.base) >> mdev->smpt->info.page_shift;
35}
36
37static inline u64 mic_smpt_to_pa(struct mic_device *mdev, u8 index)
38{
39 return mdev->smpt->info.base + (index * mdev->smpt->info.page_size);
40}
41
42static inline u64 mic_smpt_offset(struct mic_device *mdev, dma_addr_t pa)
43{
44 return pa & mic_system_page_mask(mdev);
45}
46
47static inline u64 mic_smpt_align_low(struct mic_device *mdev, dma_addr_t pa)
48{
49 return ALIGN(pa - mic_system_page_mask(mdev),
50 mdev->smpt->info.page_size);
51}
52
53static inline u64 mic_smpt_align_high(struct mic_device *mdev, dma_addr_t pa)
54{
55 return ALIGN(pa, mdev->smpt->info.page_size);
56}
57
58/* Total Cumulative system memory accessible by MIC across all SMPT entries */
59static inline u64 mic_max_system_memory(struct mic_device *mdev)
60{
61 return mdev->smpt->info.num_reg * mdev->smpt->info.page_size;
62}
63
64/* Maximum system memory address accessible by MIC */
65static inline u64 mic_max_system_addr(struct mic_device *mdev)
66{
67 return mdev->smpt->info.base + mic_max_system_memory(mdev) - 1ULL;
68}
69
70/* Check if the DMA address is a MIC system memory address */
71static inline bool
72mic_is_system_addr(struct mic_device *mdev, dma_addr_t pa)
73{
74 return pa >= mdev->smpt->info.base && pa <= mic_max_system_addr(mdev);
75}
76
77/* Populate an SMPT entry and update the reference counts. */
78static void mic_add_smpt_entry(int spt, s64 *ref, u64 addr,
79 int entries, struct mic_device *mdev)
80{
81 struct mic_smpt_info *smpt_info = mdev->smpt;
82 int i;
83
84 for (i = spt; i < spt + entries; i++,
85 addr += smpt_info->info.page_size) {
86 if (!smpt_info->entry[i].ref_count &&
87 (smpt_info->entry[i].dma_addr != addr)) {
88 mdev->smpt_ops->set(mdev, addr, i);
89 smpt_info->entry[i].dma_addr = addr;
90 }
91 smpt_info->entry[i].ref_count += ref[i - spt];
92 }
93}
94
95/*
96 * Find an available MIC address in MIC SMPT address space
97 * for a given DMA address and size.
98 */
99static dma_addr_t mic_smpt_op(struct mic_device *mdev, u64 dma_addr,
100 int entries, s64 *ref, size_t size)
101{
102 int spt;
103 int ae = 0;
104 int i;
105 unsigned long flags;
106 dma_addr_t mic_addr = 0;
107 dma_addr_t addr = dma_addr;
108 struct mic_smpt_info *smpt_info = mdev->smpt;
109
110 spin_lock_irqsave(&smpt_info->smpt_lock, flags);
111
112 /* find existing entries */
113 for (i = 0; i < smpt_info->info.num_reg; i++) {
114 if (smpt_info->entry[i].dma_addr == addr) {
115 ae++;
116 addr += smpt_info->info.page_size;
117 } else if (ae) /* cannot find contiguous entries */
118 goto not_found;
119
120 if (ae == entries)
121 goto found;
122 }
123
124 /* find free entry */
125 for (ae = 0, i = 0; i < smpt_info->info.num_reg; i++) {
126 ae = (smpt_info->entry[i].ref_count == 0) ? ae + 1 : 0;
127 if (ae == entries)
128 goto found;
129 }
130
131not_found:
132 spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
133 return mic_addr;
134
135found:
136 spt = i - entries + 1;
137 mic_addr = mic_smpt_to_pa(mdev, spt);
138 mic_add_smpt_entry(spt, ref, dma_addr, entries, mdev);
139 smpt_info->map_count++;
140 smpt_info->ref_count += (s64)size;
141 spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
142 return mic_addr;
143}
144
145/*
146 * Returns number of smpt entries needed for dma_addr to dma_addr + size
147 * also returns the reference count array for each of those entries
148 * and the starting smpt address
149 */
150static int mic_get_smpt_ref_count(struct mic_device *mdev, dma_addr_t dma_addr,
151 size_t size, s64 *ref, u64 *smpt_start)
152{
153 u64 start = dma_addr;
154 u64 end = dma_addr + size;
155 int i = 0;
156
157 while (start < end) {
158 ref[i++] = min(mic_smpt_align_high(mdev, start + 1),
159 end) - start;
160 start = mic_smpt_align_high(mdev, start + 1);
161 }
162
163 if (smpt_start)
164 *smpt_start = mic_smpt_align_low(mdev, dma_addr);
165
166 return i;
167}
168
169/*
170 * mic_to_dma_addr - Converts a MIC address to a DMA address.
171 *
172 * @mdev: pointer to mic_device instance.
173 * @mic_addr: MIC address.
174 *
175 * returns a DMA address.
176 */
177static dma_addr_t
178mic_to_dma_addr(struct mic_device *mdev, dma_addr_t mic_addr)
179{
180 struct mic_smpt_info *smpt_info = mdev->smpt;
181 int spt;
182 dma_addr_t dma_addr;
183
184 if (!mic_is_system_addr(mdev, mic_addr)) {
185 dev_err(mdev->sdev->parent,
186 "mic_addr is invalid. mic_addr = 0x%llx\n", mic_addr);
187 return -EINVAL;
188 }
189 spt = mic_sys_addr_to_smpt(mdev, mic_addr);
190 dma_addr = smpt_info->entry[spt].dma_addr +
191 mic_smpt_offset(mdev, mic_addr);
192 return dma_addr;
193}
194
195/**
196 * mic_map - Maps a DMA address to a MIC physical address.
197 *
198 * @mdev: pointer to mic_device instance.
199 * @dma_addr: DMA address.
200 * @size: Size of the region to be mapped.
201 *
202 * This API converts the DMA address provided to a DMA address understood
203 * by MIC. Caller should check for errors by calling mic_map_error(..).
204 *
205 * returns DMA address as required by MIC.
206 */
207dma_addr_t mic_map(struct mic_device *mdev, dma_addr_t dma_addr, size_t size)
208{
209 dma_addr_t mic_addr = 0;
210 int num_entries;
211 s64 *ref;
212 u64 smpt_start;
213
214 if (!size || size > mic_max_system_memory(mdev))
215 return mic_addr;
216
217 ref = kmalloc(mdev->smpt->info.num_reg * sizeof(s64), GFP_KERNEL);
218 if (!ref)
219 return mic_addr;
220
221 num_entries = mic_get_smpt_ref_count(mdev, dma_addr, size,
222 ref, &smpt_start);
223
224 /* Set the smpt table appropriately and get 16G aligned mic address */
225 mic_addr = mic_smpt_op(mdev, smpt_start, num_entries, ref, size);
226
227 kfree(ref);
228
229 /*
230 * If mic_addr is zero then its an error case
231 * since mic_addr can never be zero.
232 * else generate mic_addr by adding the 16G offset in dma_addr
233 */
234 if (!mic_addr && MIC_FAMILY_X100 == mdev->family) {
235 dev_err(mdev->sdev->parent,
236 "mic_map failed dma_addr 0x%llx size 0x%lx\n",
237 dma_addr, size);
238 return mic_addr;
239 } else {
240 return mic_addr + mic_smpt_offset(mdev, dma_addr);
241 }
242}
243
244/**
245 * mic_unmap - Unmaps a MIC physical address.
246 *
247 * @mdev: pointer to mic_device instance.
248 * @mic_addr: MIC physical address.
249 * @size: Size of the region to be unmapped.
250 *
251 * This API unmaps the mappings created by mic_map(..).
252 *
253 * returns None.
254 */
255void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
256{
257 struct mic_smpt_info *smpt_info = mdev->smpt;
258 s64 *ref;
259 int num_smpt;
260 int spt;
261 int i;
262 unsigned long flags;
263
264 if (!size)
265 return;
266
267 if (!mic_is_system_addr(mdev, mic_addr)) {
268 dev_err(mdev->sdev->parent,
269 "invalid address: 0x%llx\n", mic_addr);
270 return;
271 }
272
273 spt = mic_sys_addr_to_smpt(mdev, mic_addr);
274 ref = kmalloc(mdev->smpt->info.num_reg * sizeof(s64), GFP_KERNEL);
275 if (!ref)
276 return;
277
278 /* Get number of smpt entries to be mapped, ref count array */
279 num_smpt = mic_get_smpt_ref_count(mdev, mic_addr, size, ref, NULL);
280
281 spin_lock_irqsave(&smpt_info->smpt_lock, flags);
282 smpt_info->unmap_count++;
283 smpt_info->ref_count -= (s64)size;
284
285 for (i = spt; i < spt + num_smpt; i++) {
286 smpt_info->entry[i].ref_count -= ref[i - spt];
287 if (smpt_info->entry[i].ref_count < 0)
288 dev_warn(mdev->sdev->parent,
289 "ref count for entry %d is negative\n", i);
290 }
291 spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
292 kfree(ref);
293}
294
295/**
296 * mic_map_single - Maps a virtual address to a MIC physical address.
297 *
298 * @mdev: pointer to mic_device instance.
299 * @va: Kernel direct mapped virtual address.
300 * @size: Size of the region to be mapped.
301 *
302 * This API calls pci_map_single(..) for the direct mapped virtual address
303 * and then converts the DMA address provided to a DMA address understood
304 * by MIC. Caller should check for errors by calling mic_map_error(..).
305 *
306 * returns DMA address as required by MIC.
307 */
308dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size)
309{
310 dma_addr_t mic_addr = 0;
311 struct pci_dev *pdev = container_of(mdev->sdev->parent,
312 struct pci_dev, dev);
313 dma_addr_t dma_addr =
314 pci_map_single(pdev, va, size, PCI_DMA_BIDIRECTIONAL);
315
316 if (!pci_dma_mapping_error(pdev, dma_addr)) {
317 mic_addr = mic_map(mdev, dma_addr, size);
318 if (!mic_addr) {
319 dev_err(mdev->sdev->parent,
320 "mic_map failed dma_addr 0x%llx size 0x%lx\n",
321 dma_addr, size);
322 pci_unmap_single(pdev, dma_addr,
323 size, PCI_DMA_BIDIRECTIONAL);
324 }
325 }
326 return mic_addr;
327}
328
329/**
330 * mic_unmap_single - Unmaps a MIC physical address.
331 *
332 * @mdev: pointer to mic_device instance.
333 * @mic_addr: MIC physical address.
334 * @size: Size of the region to be unmapped.
335 *
336 * This API unmaps the mappings created by mic_map_single(..).
337 *
338 * returns None.
339 */
340void
341mic_unmap_single(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
342{
343 struct pci_dev *pdev = container_of(mdev->sdev->parent,
344 struct pci_dev, dev);
345 dma_addr_t dma_addr = mic_to_dma_addr(mdev, mic_addr);
346 mic_unmap(mdev, mic_addr, size);
347 pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
348}
349
350/**
351 * mic_smpt_init - Initialize MIC System Memory Page Tables.
352 *
353 * @mdev: pointer to mic_device instance.
354 *
355 * returns 0 for success and -errno for error.
356 */
357int mic_smpt_init(struct mic_device *mdev)
358{
359 int i, err = 0;
360 dma_addr_t dma_addr;
361 struct mic_smpt_info *smpt_info;
362
363 mdev->smpt = kmalloc(sizeof(*mdev->smpt), GFP_KERNEL);
364 if (!mdev->smpt)
365 return -ENOMEM;
366
367 smpt_info = mdev->smpt;
368 mdev->smpt_ops->init(mdev);
369 smpt_info->entry = kmalloc_array(smpt_info->info.num_reg,
370 sizeof(*smpt_info->entry), GFP_KERNEL);
371 if (!smpt_info->entry) {
372 err = -ENOMEM;
373 goto free_smpt;
374 }
375 spin_lock_init(&smpt_info->smpt_lock);
376 for (i = 0; i < smpt_info->info.num_reg; i++) {
377 dma_addr = i * smpt_info->info.page_size;
378 smpt_info->entry[i].dma_addr = dma_addr;
379 smpt_info->entry[i].ref_count = 0;
380 mdev->smpt_ops->set(mdev, dma_addr, i);
381 }
382 smpt_info->ref_count = 0;
383 smpt_info->map_count = 0;
384 smpt_info->unmap_count = 0;
385 return 0;
386free_smpt:
387 kfree(smpt_info);
388 return err;
389}
390
391/**
392 * mic_smpt_uninit - UnInitialize MIC System Memory Page Tables.
393 *
394 * @mdev: pointer to mic_device instance.
395 *
396 * returns None.
397 */
398void mic_smpt_uninit(struct mic_device *mdev)
399{
400 struct mic_smpt_info *smpt_info = mdev->smpt;
401 int i;
402
403 dev_dbg(mdev->sdev->parent,
404 "nodeid %d SMPT ref count %lld map %lld unmap %lld\n",
405 mdev->id, smpt_info->ref_count,
406 smpt_info->map_count, smpt_info->unmap_count);
407
408 for (i = 0; i < smpt_info->info.num_reg; i++) {
409 dev_dbg(mdev->sdev->parent,
410 "SMPT entry[%d] dma_addr = 0x%llx ref_count = %lld\n",
411 i, smpt_info->entry[i].dma_addr,
412 smpt_info->entry[i].ref_count);
413 if (smpt_info->entry[i].ref_count)
414 dev_warn(mdev->sdev->parent,
415 "ref count for entry %d is not zero\n", i);
416 }
417 kfree(smpt_info->entry);
418 kfree(smpt_info);
419}
420
421/**
422 * mic_smpt_restore - Restore MIC System Memory Page Tables.
423 *
424 * @mdev: pointer to mic_device instance.
425 *
426 * Restore the SMPT registers to values previously stored in the
427 * SW data structures. Some MIC steppings lose register state
428 * across resets and this API should be called for performing
429 * a restore operation if required.
430 *
431 * returns None.
432 */
433void mic_smpt_restore(struct mic_device *mdev)
434{
435 int i;
436 dma_addr_t dma_addr;
437
438 for (i = 0; i < mdev->smpt->info.num_reg; i++) {
439 dma_addr = mdev->smpt->entry[i].dma_addr;
440 mdev->smpt_ops->set(mdev, dma_addr, i);
441 }
442}
diff --git a/drivers/misc/mic/host/mic_smpt.h b/drivers/misc/mic/host/mic_smpt.h
new file mode 100644
index 000000000000..51970abfe7df
--- /dev/null
+++ b/drivers/misc/mic/host/mic_smpt.h
@@ -0,0 +1,98 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#ifndef MIC_SMPT_H
22#define MIC_SMPT_H
23/**
24 * struct mic_smpt_ops - MIC HW specific SMPT operations.
25 * @init: Initialize hardware specific SMPT information in mic_smpt_hw_info.
26 * @set: Set the value for a particular SMPT entry.
27 */
28struct mic_smpt_ops {
29 void (*init)(struct mic_device *mdev);
30 void (*set)(struct mic_device *mdev, dma_addr_t dma_addr, u8 index);
31};
32
33/**
34 * struct mic_smpt - MIC SMPT entry information.
35 * @dma_addr: Base DMA address for this SMPT entry.
36 * @ref_count: Number of active mappings for this SMPT entry in bytes.
37 */
38struct mic_smpt {
39 dma_addr_t dma_addr;
40 s64 ref_count;
41};
42
43/**
44 * struct mic_smpt_hw_info - MIC SMPT hardware specific information.
45 * @num_reg: Number of SMPT registers.
46 * @page_shift: System memory page shift.
47 * @page_size: System memory page size.
48 * @base: System address base.
49 */
50struct mic_smpt_hw_info {
51 u8 num_reg;
52 u8 page_shift;
53 u64 page_size;
54 u64 base;
55};
56
57/**
58 * struct mic_smpt_info - MIC SMPT information.
59 * @entry: Array of SMPT entries.
60 * @smpt_lock: Spin lock protecting access to SMPT data structures.
61 * @info: Hardware specific SMPT information.
62 * @ref_count: Number of active SMPT mappings (for debug).
63 * @map_count: Number of SMPT mappings created (for debug).
64 * @unmap_count: Number of SMPT mappings destroyed (for debug).
65 */
66struct mic_smpt_info {
67 struct mic_smpt *entry;
68 spinlock_t smpt_lock;
69 struct mic_smpt_hw_info info;
70 s64 ref_count;
71 s64 map_count;
72 s64 unmap_count;
73};
74
75dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size);
76void mic_unmap_single(struct mic_device *mdev,
77 dma_addr_t mic_addr, size_t size);
78dma_addr_t mic_map(struct mic_device *mdev,
79 dma_addr_t dma_addr, size_t size);
80void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size);
81
82/**
83 * mic_map_error - Check a MIC address for errors.
84 *
85 * @mdev: pointer to mic_device instance.
86 *
87 * returns Whether there was an error during mic_map..(..) APIs.
88 */
89static inline bool mic_map_error(dma_addr_t mic_addr)
90{
91 return !mic_addr;
92}
93
94int mic_smpt_init(struct mic_device *mdev);
95void mic_smpt_uninit(struct mic_device *mdev);
96void mic_smpt_restore(struct mic_device *mdev);
97
98#endif
diff --git a/drivers/misc/mic/host/mic_sysfs.c b/drivers/misc/mic/host/mic_sysfs.c
new file mode 100644
index 000000000000..6dd864e4a617
--- /dev/null
+++ b/drivers/misc/mic/host/mic_sysfs.c
@@ -0,0 +1,459 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#include <linux/pci.h>
22
23#include <linux/mic_common.h>
24#include "../common/mic_dev.h"
25#include "mic_device.h"
26
27/*
28 * A state-to-string lookup table, for exposing a human readable state
29 * via sysfs. Always keep in sync with enum mic_states
30 */
31static const char * const mic_state_string[] = {
32 [MIC_OFFLINE] = "offline",
33 [MIC_ONLINE] = "online",
34 [MIC_SHUTTING_DOWN] = "shutting_down",
35 [MIC_RESET_FAILED] = "reset_failed",
36 [MIC_SUSPENDING] = "suspending",
37 [MIC_SUSPENDED] = "suspended",
38};
39
40/*
41 * A shutdown-status-to-string lookup table, for exposing a human
42 * readable state via sysfs. Always keep in sync with enum mic_shutdown_status
43 */
44static const char * const mic_shutdown_status_string[] = {
45 [MIC_NOP] = "nop",
46 [MIC_CRASHED] = "crashed",
47 [MIC_HALTED] = "halted",
48 [MIC_POWER_OFF] = "poweroff",
49 [MIC_RESTART] = "restart",
50};
51
52void mic_set_shutdown_status(struct mic_device *mdev, u8 shutdown_status)
53{
54 dev_dbg(mdev->sdev->parent, "Shutdown Status %s -> %s\n",
55 mic_shutdown_status_string[mdev->shutdown_status],
56 mic_shutdown_status_string[shutdown_status]);
57 mdev->shutdown_status = shutdown_status;
58}
59
60void mic_set_state(struct mic_device *mdev, u8 state)
61{
62 dev_dbg(mdev->sdev->parent, "State %s -> %s\n",
63 mic_state_string[mdev->state],
64 mic_state_string[state]);
65 mdev->state = state;
66 sysfs_notify_dirent(mdev->state_sysfs);
67}
68
69static ssize_t
70family_show(struct device *dev, struct device_attribute *attr, char *buf)
71{
72 static const char x100[] = "x100";
73 static const char unknown[] = "Unknown";
74 const char *card = NULL;
75 struct mic_device *mdev = dev_get_drvdata(dev->parent);
76
77 if (!mdev)
78 return -EINVAL;
79
80 switch (mdev->family) {
81 case MIC_FAMILY_X100:
82 card = x100;
83 break;
84 default:
85 card = unknown;
86 break;
87 }
88 return scnprintf(buf, PAGE_SIZE, "%s\n", card);
89}
90static DEVICE_ATTR_RO(family);
91
92static ssize_t
93stepping_show(struct device *dev, struct device_attribute *attr, char *buf)
94{
95 struct mic_device *mdev = dev_get_drvdata(dev->parent);
96 char *string = "??";
97
98 if (!mdev)
99 return -EINVAL;
100
101 switch (mdev->stepping) {
102 case MIC_A0_STEP:
103 string = "A0";
104 break;
105 case MIC_B0_STEP:
106 string = "B0";
107 break;
108 case MIC_B1_STEP:
109 string = "B1";
110 break;
111 case MIC_C0_STEP:
112 string = "C0";
113 break;
114 default:
115 break;
116 }
117 return scnprintf(buf, PAGE_SIZE, "%s\n", string);
118}
119static DEVICE_ATTR_RO(stepping);
120
121static ssize_t
122state_show(struct device *dev, struct device_attribute *attr, char *buf)
123{
124 struct mic_device *mdev = dev_get_drvdata(dev->parent);
125
126 if (!mdev || mdev->state >= MIC_LAST)
127 return -EINVAL;
128
129 return scnprintf(buf, PAGE_SIZE, "%s\n",
130 mic_state_string[mdev->state]);
131}
132
133static ssize_t
134state_store(struct device *dev, struct device_attribute *attr,
135 const char *buf, size_t count)
136{
137 int rc = 0;
138 struct mic_device *mdev = dev_get_drvdata(dev->parent);
139 if (!mdev)
140 return -EINVAL;
141 if (sysfs_streq(buf, "boot")) {
142 rc = mic_start(mdev, buf);
143 if (rc) {
144 dev_err(mdev->sdev->parent,
145 "mic_boot failed rc %d\n", rc);
146 count = rc;
147 }
148 goto done;
149 }
150
151 if (sysfs_streq(buf, "reset")) {
152 schedule_work(&mdev->reset_trigger_work);
153 goto done;
154 }
155
156 if (sysfs_streq(buf, "shutdown")) {
157 mic_shutdown(mdev);
158 goto done;
159 }
160
161 if (sysfs_streq(buf, "suspend")) {
162 mic_suspend(mdev);
163 goto done;
164 }
165
166 count = -EINVAL;
167done:
168 return count;
169}
170static DEVICE_ATTR_RW(state);
171
172static ssize_t shutdown_status_show(struct device *dev,
173 struct device_attribute *attr, char *buf)
174{
175 struct mic_device *mdev = dev_get_drvdata(dev->parent);
176
177 if (!mdev || mdev->shutdown_status >= MIC_STATUS_LAST)
178 return -EINVAL;
179
180 return scnprintf(buf, PAGE_SIZE, "%s\n",
181 mic_shutdown_status_string[mdev->shutdown_status]);
182}
183static DEVICE_ATTR_RO(shutdown_status);
184
185static ssize_t
186cmdline_show(struct device *dev, struct device_attribute *attr, char *buf)
187{
188 struct mic_device *mdev = dev_get_drvdata(dev->parent);
189 char *cmdline;
190
191 if (!mdev)
192 return -EINVAL;
193
194 cmdline = mdev->cmdline;
195
196 if (cmdline)
197 return scnprintf(buf, PAGE_SIZE, "%s\n", cmdline);
198 return 0;
199}
200
201static ssize_t
202cmdline_store(struct device *dev, struct device_attribute *attr,
203 const char *buf, size_t count)
204{
205 struct mic_device *mdev = dev_get_drvdata(dev->parent);
206
207 if (!mdev)
208 return -EINVAL;
209
210 mutex_lock(&mdev->mic_mutex);
211 kfree(mdev->cmdline);
212
213 mdev->cmdline = kmalloc(count + 1, GFP_KERNEL);
214 if (!mdev->cmdline) {
215 count = -ENOMEM;
216 goto unlock;
217 }
218
219 strncpy(mdev->cmdline, buf, count);
220
221 if (mdev->cmdline[count - 1] == '\n')
222 mdev->cmdline[count - 1] = '\0';
223 else
224 mdev->cmdline[count] = '\0';
225unlock:
226 mutex_unlock(&mdev->mic_mutex);
227 return count;
228}
229static DEVICE_ATTR_RW(cmdline);
230
231static ssize_t
232firmware_show(struct device *dev, struct device_attribute *attr, char *buf)
233{
234 struct mic_device *mdev = dev_get_drvdata(dev->parent);
235 char *firmware;
236
237 if (!mdev)
238 return -EINVAL;
239
240 firmware = mdev->firmware;
241
242 if (firmware)
243 return scnprintf(buf, PAGE_SIZE, "%s\n", firmware);
244 return 0;
245}
246
247static ssize_t
248firmware_store(struct device *dev, struct device_attribute *attr,
249 const char *buf, size_t count)
250{
251 struct mic_device *mdev = dev_get_drvdata(dev->parent);
252
253 if (!mdev)
254 return -EINVAL;
255
256 mutex_lock(&mdev->mic_mutex);
257 kfree(mdev->firmware);
258
259 mdev->firmware = kmalloc(count + 1, GFP_KERNEL);
260 if (!mdev->firmware) {
261 count = -ENOMEM;
262 goto unlock;
263 }
264 strncpy(mdev->firmware, buf, count);
265
266 if (mdev->firmware[count - 1] == '\n')
267 mdev->firmware[count - 1] = '\0';
268 else
269 mdev->firmware[count] = '\0';
270unlock:
271 mutex_unlock(&mdev->mic_mutex);
272 return count;
273}
274static DEVICE_ATTR_RW(firmware);
275
276static ssize_t
277ramdisk_show(struct device *dev, struct device_attribute *attr, char *buf)
278{
279 struct mic_device *mdev = dev_get_drvdata(dev->parent);
280 char *ramdisk;
281
282 if (!mdev)
283 return -EINVAL;
284
285 ramdisk = mdev->ramdisk;
286
287 if (ramdisk)
288 return scnprintf(buf, PAGE_SIZE, "%s\n", ramdisk);
289 return 0;
290}
291
292static ssize_t
293ramdisk_store(struct device *dev, struct device_attribute *attr,
294 const char *buf, size_t count)
295{
296 struct mic_device *mdev = dev_get_drvdata(dev->parent);
297
298 if (!mdev)
299 return -EINVAL;
300
301 mutex_lock(&mdev->mic_mutex);
302 kfree(mdev->ramdisk);
303
304 mdev->ramdisk = kmalloc(count + 1, GFP_KERNEL);
305 if (!mdev->ramdisk) {
306 count = -ENOMEM;
307 goto unlock;
308 }
309
310 strncpy(mdev->ramdisk, buf, count);
311
312 if (mdev->ramdisk[count - 1] == '\n')
313 mdev->ramdisk[count - 1] = '\0';
314 else
315 mdev->ramdisk[count] = '\0';
316unlock:
317 mutex_unlock(&mdev->mic_mutex);
318 return count;
319}
320static DEVICE_ATTR_RW(ramdisk);
321
322static ssize_t
323bootmode_show(struct device *dev, struct device_attribute *attr, char *buf)
324{
325 struct mic_device *mdev = dev_get_drvdata(dev->parent);
326 char *bootmode;
327
328 if (!mdev)
329 return -EINVAL;
330
331 bootmode = mdev->bootmode;
332
333 if (bootmode)
334 return scnprintf(buf, PAGE_SIZE, "%s\n", bootmode);
335 return 0;
336}
337
338static ssize_t
339bootmode_store(struct device *dev, struct device_attribute *attr,
340 const char *buf, size_t count)
341{
342 struct mic_device *mdev = dev_get_drvdata(dev->parent);
343
344 if (!mdev)
345 return -EINVAL;
346
347 if (!sysfs_streq(buf, "linux") && !sysfs_streq(buf, "elf"))
348 return -EINVAL;
349
350 mutex_lock(&mdev->mic_mutex);
351 kfree(mdev->bootmode);
352
353 mdev->bootmode = kmalloc(count + 1, GFP_KERNEL);
354 if (!mdev->bootmode) {
355 count = -ENOMEM;
356 goto unlock;
357 }
358
359 strncpy(mdev->bootmode, buf, count);
360
361 if (mdev->bootmode[count - 1] == '\n')
362 mdev->bootmode[count - 1] = '\0';
363 else
364 mdev->bootmode[count] = '\0';
365unlock:
366 mutex_unlock(&mdev->mic_mutex);
367 return count;
368}
369static DEVICE_ATTR_RW(bootmode);
370
371static ssize_t
372log_buf_addr_show(struct device *dev, struct device_attribute *attr,
373 char *buf)
374{
375 struct mic_device *mdev = dev_get_drvdata(dev->parent);
376
377 if (!mdev)
378 return -EINVAL;
379
380 return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_addr);
381}
382
383static ssize_t
384log_buf_addr_store(struct device *dev, struct device_attribute *attr,
385 const char *buf, size_t count)
386{
387 struct mic_device *mdev = dev_get_drvdata(dev->parent);
388 int ret;
389 unsigned long addr;
390
391 if (!mdev)
392 return -EINVAL;
393
394 ret = kstrtoul(buf, 16, &addr);
395 if (ret)
396 goto exit;
397
398 mdev->log_buf_addr = (void *)addr;
399 ret = count;
400exit:
401 return ret;
402}
403static DEVICE_ATTR_RW(log_buf_addr);
404
405static ssize_t
406log_buf_len_show(struct device *dev, struct device_attribute *attr,
407 char *buf)
408{
409 struct mic_device *mdev = dev_get_drvdata(dev->parent);
410
411 if (!mdev)
412 return -EINVAL;
413
414 return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_len);
415}
416
417static ssize_t
418log_buf_len_store(struct device *dev, struct device_attribute *attr,
419 const char *buf, size_t count)
420{
421 struct mic_device *mdev = dev_get_drvdata(dev->parent);
422 int ret;
423 unsigned long addr;
424
425 if (!mdev)
426 return -EINVAL;
427
428 ret = kstrtoul(buf, 16, &addr);
429 if (ret)
430 goto exit;
431
432 mdev->log_buf_len = (int *)addr;
433 ret = count;
434exit:
435 return ret;
436}
437static DEVICE_ATTR_RW(log_buf_len);
438
439static struct attribute *mic_default_attrs[] = {
440 &dev_attr_family.attr,
441 &dev_attr_stepping.attr,
442 &dev_attr_state.attr,
443 &dev_attr_shutdown_status.attr,
444 &dev_attr_cmdline.attr,
445 &dev_attr_firmware.attr,
446 &dev_attr_ramdisk.attr,
447 &dev_attr_bootmode.attr,
448 &dev_attr_log_buf_addr.attr,
449 &dev_attr_log_buf_len.attr,
450
451 NULL
452};
453
454ATTRIBUTE_GROUPS(mic_default);
455
456void mic_sysfs_init(struct mic_device *mdev)
457{
458 mdev->attr_group = mic_default_groups;
459}
diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c
new file mode 100644
index 000000000000..5b8494bd1e00
--- /dev/null
+++ b/drivers/misc/mic/host/mic_virtio.c
@@ -0,0 +1,700 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#include <linux/pci.h>
22#include <linux/sched.h>
23#include <linux/uaccess.h>
24
25#include <linux/mic_common.h>
26#include "../common/mic_dev.h"
27#include "mic_device.h"
28#include "mic_smpt.h"
29#include "mic_virtio.h"
30
31/*
32 * Initiates the copies across the PCIe bus from card memory to
33 * a user space buffer.
34 */
35static int mic_virtio_copy_to_user(struct mic_vdev *mvdev,
36 void __user *ubuf, size_t len, u64 addr)
37{
38 int err;
39 void __iomem *dbuf = mvdev->mdev->aper.va + addr;
40 /*
41 * We are copying from IO below an should ideally use something
42 * like copy_to_user_fromio(..) if it existed.
43 */
44 if (copy_to_user(ubuf, dbuf, len)) {
45 err = -EFAULT;
46 dev_err(mic_dev(mvdev), "%s %d err %d\n",
47 __func__, __LINE__, err);
48 goto err;
49 }
50 mvdev->in_bytes += len;
51 err = 0;
52err:
53 return err;
54}
55
56/*
57 * Initiates copies across the PCIe bus from a user space
58 * buffer to card memory.
59 */
60static int mic_virtio_copy_from_user(struct mic_vdev *mvdev,
61 void __user *ubuf, size_t len, u64 addr)
62{
63 int err;
64 void __iomem *dbuf = mvdev->mdev->aper.va + addr;
65 /*
66 * We are copying to IO below and should ideally use something
67 * like copy_from_user_toio(..) if it existed.
68 */
69 if (copy_from_user(dbuf, ubuf, len)) {
70 err = -EFAULT;
71 dev_err(mic_dev(mvdev), "%s %d err %d\n",
72 __func__, __LINE__, err);
73 goto err;
74 }
75 mvdev->out_bytes += len;
76 err = 0;
77err:
78 return err;
79}
80
81#define MIC_VRINGH_READ true
82
83/* The function to call to notify the card about added buffers */
84static void mic_notify(struct vringh *vrh)
85{
86 struct mic_vringh *mvrh = container_of(vrh, struct mic_vringh, vrh);
87 struct mic_vdev *mvdev = mvrh->mvdev;
88 s8 db = mvdev->dc->h2c_vdev_db;
89
90 if (db != -1)
91 mvdev->mdev->ops->send_intr(mvdev->mdev, db);
92}
93
94/* Determine the total number of bytes consumed in a VRINGH KIOV */
95static inline u32 mic_vringh_iov_consumed(struct vringh_kiov *iov)
96{
97 int i;
98 u32 total = iov->consumed;
99
100 for (i = 0; i < iov->i; i++)
101 total += iov->iov[i].iov_len;
102 return total;
103}
104
105/*
106 * Traverse the VRINGH KIOV and issue the APIs to trigger the copies.
107 * This API is heavily based on the vringh_iov_xfer(..) implementation
108 * in vringh.c. The reason we cannot reuse vringh_iov_pull_kern(..)
109 * and vringh_iov_push_kern(..) directly is because there is no
110 * way to override the VRINGH xfer(..) routines as of v3.10.
111 */
112static 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)
114{
115 int ret = 0;
116 size_t partlen, tot_len = 0;
117
118 while (len && iov->i < iov->used) {
119 partlen = min(iov->iov[iov->i].iov_len, len);
120 if (read)
121 ret = mic_virtio_copy_to_user(mvdev,
122 ubuf, partlen,
123 (u64)iov->iov[iov->i].iov_base);
124 else
125 ret = mic_virtio_copy_from_user(mvdev,
126 ubuf, partlen,
127 (u64)iov->iov[iov->i].iov_base);
128 if (ret) {
129 dev_err(mic_dev(mvdev), "%s %d err %d\n",
130 __func__, __LINE__, ret);
131 break;
132 }
133 len -= partlen;
134 ubuf += partlen;
135 tot_len += partlen;
136 iov->consumed += partlen;
137 iov->iov[iov->i].iov_len -= partlen;
138 iov->iov[iov->i].iov_base += partlen;
139 if (!iov->iov[iov->i].iov_len) {
140 /* Fix up old iov element then increment. */
141 iov->iov[iov->i].iov_len = iov->consumed;
142 iov->iov[iov->i].iov_base -= iov->consumed;
143
144 iov->consumed = 0;
145 iov->i++;
146 }
147 }
148 *out_len = tot_len;
149 return ret;
150}
151
152/*
153 * Use the standard VRINGH infrastructure in the kernel to fetch new
154 * descriptors, initiate the copies and update the used ring.
155 */
156static int _mic_virtio_copy(struct mic_vdev *mvdev,
157 struct mic_copy_desc *copy)
158{
159 int ret = 0, iovcnt = copy->iovcnt;
160 struct iovec iov;
161 struct iovec __user *u_iov = copy->iov;
162 void __user *ubuf = NULL;
163 struct mic_vringh *mvr = &mvdev->mvr[copy->vr_idx];
164 struct vringh_kiov *riov = &mvr->riov;
165 struct vringh_kiov *wiov = &mvr->wiov;
166 struct vringh *vrh = &mvr->vrh;
167 u16 *head = &mvr->head;
168 struct mic_vring *vr = &mvr->vring;
169 size_t len = 0, out_len;
170
171 copy->out_len = 0;
172 /* Fetch a new IOVEC if all previous elements have been processed */
173 if (riov->i == riov->used && wiov->i == wiov->used) {
174 ret = vringh_getdesc_kern(vrh, riov, wiov,
175 head, GFP_KERNEL);
176 /* Check if there are available descriptors */
177 if (ret <= 0)
178 return ret;
179 }
180 while (iovcnt) {
181 if (!len) {
182 /* Copy over a new iovec from user space. */
183 ret = copy_from_user(&iov, u_iov, sizeof(*u_iov));
184 if (ret) {
185 ret = -EINVAL;
186 dev_err(mic_dev(mvdev), "%s %d err %d\n",
187 __func__, __LINE__, ret);
188 break;
189 }
190 len = iov.iov_len;
191 ubuf = iov.iov_base;
192 }
193 /* Issue all the read descriptors first */
194 ret = mic_vringh_copy(mvdev, riov, ubuf, len,
195 MIC_VRINGH_READ, &out_len);
196 if (ret) {
197 dev_err(mic_dev(mvdev), "%s %d err %d\n",
198 __func__, __LINE__, ret);
199 break;
200 }
201 len -= out_len;
202 ubuf += out_len;
203 copy->out_len += out_len;
204 /* Issue the write descriptors next */
205 ret = mic_vringh_copy(mvdev, wiov, ubuf, len,
206 !MIC_VRINGH_READ, &out_len);
207 if (ret) {
208 dev_err(mic_dev(mvdev), "%s %d err %d\n",
209 __func__, __LINE__, ret);
210 break;
211 }
212 len -= out_len;
213 ubuf += out_len;
214 copy->out_len += out_len;
215 if (!len) {
216 /* One user space iovec is now completed */
217 iovcnt--;
218 u_iov++;
219 }
220 /* Exit loop if all elements in KIOVs have been processed. */
221 if (riov->i == riov->used && wiov->i == wiov->used)
222 break;
223 }
224 /*
225 * Update the used ring if a descriptor was available and some data was
226 * copied in/out and the user asked for a used ring update.
227 */
228 if (*head != USHRT_MAX && copy->out_len && copy->update_used) {
229 u32 total = 0;
230
231 /* Determine the total data consumed */
232 total += mic_vringh_iov_consumed(riov);
233 total += mic_vringh_iov_consumed(wiov);
234 vringh_complete_kern(vrh, *head, total);
235 *head = USHRT_MAX;
236 if (vringh_need_notify_kern(vrh) > 0)
237 vringh_notify(vrh);
238 vringh_kiov_cleanup(riov);
239 vringh_kiov_cleanup(wiov);
240 /* Update avail idx for user space */
241 vr->info->avail_idx = vrh->last_avail_idx;
242 }
243 return ret;
244}
245
246static inline int mic_verify_copy_args(struct mic_vdev *mvdev,
247 struct mic_copy_desc *copy)
248{
249 if (copy->vr_idx >= mvdev->dd->num_vq) {
250 dev_err(mic_dev(mvdev), "%s %d err %d\n",
251 __func__, __LINE__, -EINVAL);
252 return -EINVAL;
253 }
254 return 0;
255}
256
257/* Copy a specified number of virtio descriptors in a chain */
258int mic_virtio_copy_desc(struct mic_vdev *mvdev,
259 struct mic_copy_desc *copy)
260{
261 int err;
262 struct mic_vringh *mvr = &mvdev->mvr[copy->vr_idx];
263
264 err = mic_verify_copy_args(mvdev, copy);
265 if (err)
266 return err;
267
268 mutex_lock(&mvr->vr_mutex);
269 if (!mic_vdevup(mvdev)) {
270 err = -ENODEV;
271 dev_err(mic_dev(mvdev), "%s %d err %d\n",
272 __func__, __LINE__, err);
273 goto err;
274 }
275 err = _mic_virtio_copy(mvdev, copy);
276 if (err) {
277 dev_err(mic_dev(mvdev), "%s %d err %d\n",
278 __func__, __LINE__, err);
279 }
280err:
281 mutex_unlock(&mvr->vr_mutex);
282 return err;
283}
284
285static void mic_virtio_init_post(struct mic_vdev *mvdev)
286{
287 struct mic_vqconfig *vqconfig = mic_vq_config(mvdev->dd);
288 int i;
289
290 for (i = 0; i < mvdev->dd->num_vq; i++) {
291 if (!le64_to_cpu(vqconfig[i].used_address)) {
292 dev_warn(mic_dev(mvdev), "used_address zero??\n");
293 continue;
294 }
295 mvdev->mvr[i].vrh.vring.used =
296 mvdev->mdev->aper.va +
297 le64_to_cpu(vqconfig[i].used_address);
298 }
299
300 mvdev->dc->used_address_updated = 0;
301
302 dev_dbg(mic_dev(mvdev), "%s: device type %d LINKUP\n",
303 __func__, mvdev->virtio_id);
304}
305
306static inline void mic_virtio_device_reset(struct mic_vdev *mvdev)
307{
308 int i;
309
310 dev_dbg(mic_dev(mvdev), "%s: status %d device type %d RESET\n",
311 __func__, mvdev->dd->status, mvdev->virtio_id);
312
313 for (i = 0; i < mvdev->dd->num_vq; i++)
314 /*
315 * Avoid lockdep false positive. The + 1 is for the mic
316 * mutex which is held in the reset devices code path.
317 */
318 mutex_lock_nested(&mvdev->mvr[i].vr_mutex, i + 1);
319
320 /* 0 status means "reset" */
321 mvdev->dd->status = 0;
322 mvdev->dc->vdev_reset = 0;
323 mvdev->dc->host_ack = 1;
324
325 for (i = 0; i < mvdev->dd->num_vq; i++) {
326 struct vringh *vrh = &mvdev->mvr[i].vrh;
327 mvdev->mvr[i].vring.info->avail_idx = 0;
328 vrh->completed = 0;
329 vrh->last_avail_idx = 0;
330 vrh->last_used_idx = 0;
331 }
332
333 for (i = 0; i < mvdev->dd->num_vq; i++)
334 mutex_unlock(&mvdev->mvr[i].vr_mutex);
335}
336
337void mic_virtio_reset_devices(struct mic_device *mdev)
338{
339 struct list_head *pos, *tmp;
340 struct mic_vdev *mvdev;
341
342 dev_dbg(mdev->sdev->parent, "%s\n", __func__);
343
344 list_for_each_safe(pos, tmp, &mdev->vdev_list) {
345 mvdev = list_entry(pos, struct mic_vdev, list);
346 mic_virtio_device_reset(mvdev);
347 mvdev->poll_wake = 1;
348 wake_up(&mvdev->waitq);
349 }
350}
351
352void mic_bh_handler(struct work_struct *work)
353{
354 struct mic_vdev *mvdev = container_of(work, struct mic_vdev,
355 virtio_bh_work);
356
357 if (mvdev->dc->used_address_updated)
358 mic_virtio_init_post(mvdev);
359
360 if (mvdev->dc->vdev_reset)
361 mic_virtio_device_reset(mvdev);
362
363 mvdev->poll_wake = 1;
364 wake_up(&mvdev->waitq);
365}
366
367static irqreturn_t mic_virtio_intr_handler(int irq, void *data)
368{
369 struct mic_vdev *mvdev = data;
370 struct mic_device *mdev = mvdev->mdev;
371
372 mdev->ops->ack_interrupt(mdev);
373 schedule_work(&mvdev->virtio_bh_work);
374 return IRQ_HANDLED;
375}
376
377int mic_virtio_config_change(struct mic_vdev *mvdev,
378 void __user *argp)
379{
380 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
381 int ret = 0, retry = 100, i;
382 struct mic_bootparam *bootparam = mvdev->mdev->dp;
383 s8 db = bootparam->h2c_config_db;
384
385 mutex_lock(&mvdev->mdev->mic_mutex);
386 for (i = 0; i < mvdev->dd->num_vq; i++)
387 mutex_lock_nested(&mvdev->mvr[i].vr_mutex, i + 1);
388
389 if (db == -1 || mvdev->dd->type == -1) {
390 ret = -EIO;
391 goto exit;
392 }
393
394 if (copy_from_user(mic_vq_configspace(mvdev->dd),
395 argp, mvdev->dd->config_len)) {
396 dev_err(mic_dev(mvdev), "%s %d err %d\n",
397 __func__, __LINE__, -EFAULT);
398 ret = -EFAULT;
399 goto exit;
400 }
401 mvdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED;
402 mvdev->mdev->ops->send_intr(mvdev->mdev, db);
403
404 for (i = retry; i--;) {
405 ret = wait_event_timeout(wake,
406 mvdev->dc->guest_ack, msecs_to_jiffies(100));
407 if (ret)
408 break;
409 }
410
411 dev_dbg(mic_dev(mvdev),
412 "%s %d retry: %d\n", __func__, __LINE__, retry);
413 mvdev->dc->config_change = 0;
414 mvdev->dc->guest_ack = 0;
415exit:
416 for (i = 0; i < mvdev->dd->num_vq; i++)
417 mutex_unlock(&mvdev->mvr[i].vr_mutex);
418 mutex_unlock(&mvdev->mdev->mic_mutex);
419 return ret;
420}
421
422static int mic_copy_dp_entry(struct mic_vdev *mvdev,
423 void __user *argp,
424 __u8 *type,
425 struct mic_device_desc **devpage)
426{
427 struct mic_device *mdev = mvdev->mdev;
428 struct mic_device_desc dd, *dd_config, *devp;
429 struct mic_vqconfig *vqconfig;
430 int ret = 0, i;
431 bool slot_found = false;
432
433 if (copy_from_user(&dd, argp, sizeof(dd))) {
434 dev_err(mic_dev(mvdev), "%s %d err %d\n",
435 __func__, __LINE__, -EFAULT);
436 return -EFAULT;
437 }
438
439 if (mic_aligned_desc_size(&dd) > MIC_MAX_DESC_BLK_SIZE ||
440 dd.num_vq > MIC_MAX_VRINGS) {
441 dev_err(mic_dev(mvdev), "%s %d err %d\n",
442 __func__, __LINE__, -EINVAL);
443 return -EINVAL;
444 }
445
446 dd_config = kmalloc(mic_desc_size(&dd), GFP_KERNEL);
447 if (dd_config == NULL) {
448 dev_err(mic_dev(mvdev), "%s %d err %d\n",
449 __func__, __LINE__, -ENOMEM);
450 return -ENOMEM;
451 }
452 if (copy_from_user(dd_config, argp, mic_desc_size(&dd))) {
453 ret = -EFAULT;
454 dev_err(mic_dev(mvdev), "%s %d err %d\n",
455 __func__, __LINE__, ret);
456 goto exit;
457 }
458
459 vqconfig = mic_vq_config(dd_config);
460 for (i = 0; i < dd.num_vq; i++) {
461 if (le16_to_cpu(vqconfig[i].num) > MIC_MAX_VRING_ENTRIES) {
462 ret = -EINVAL;
463 dev_err(mic_dev(mvdev), "%s %d err %d\n",
464 __func__, __LINE__, ret);
465 goto exit;
466 }
467 }
468
469 /* Find the first free device page entry */
470 for (i = mic_aligned_size(struct mic_bootparam);
471 i < MIC_DP_SIZE - mic_total_desc_size(dd_config);
472 i += mic_total_desc_size(devp)) {
473 devp = mdev->dp + i;
474 if (devp->type == 0 || devp->type == -1) {
475 slot_found = true;
476 break;
477 }
478 }
479 if (!slot_found) {
480 ret = -EINVAL;
481 dev_err(mic_dev(mvdev), "%s %d err %d\n",
482 __func__, __LINE__, ret);
483 goto exit;
484 }
485 /*
486 * Save off the type before doing the memcpy. Type will be set in the
487 * end after completing all initialization for the new device.
488 */
489 *type = dd_config->type;
490 dd_config->type = 0;
491 memcpy(devp, dd_config, mic_desc_size(dd_config));
492
493 *devpage = devp;
494exit:
495 kfree(dd_config);
496 return ret;
497}
498
499static void mic_init_device_ctrl(struct mic_vdev *mvdev,
500 struct mic_device_desc *devpage)
501{
502 struct mic_device_ctrl *dc;
503
504 dc = (void *)devpage + mic_aligned_desc_size(devpage);
505
506 dc->config_change = 0;
507 dc->guest_ack = 0;
508 dc->vdev_reset = 0;
509 dc->host_ack = 0;
510 dc->used_address_updated = 0;
511 dc->c2h_vdev_db = -1;
512 dc->h2c_vdev_db = -1;
513 mvdev->dc = dc;
514}
515
516int mic_virtio_add_device(struct mic_vdev *mvdev,
517 void __user *argp)
518{
519 struct mic_device *mdev = mvdev->mdev;
520 struct mic_device_desc *dd = NULL;
521 struct mic_vqconfig *vqconfig;
522 int vr_size, i, j, ret;
523 u8 type = 0;
524 s8 db;
525 char irqname[10];
526 struct mic_bootparam *bootparam = mdev->dp;
527 u16 num;
528
529 mutex_lock(&mdev->mic_mutex);
530
531 ret = mic_copy_dp_entry(mvdev, argp, &type, &dd);
532 if (ret) {
533 mutex_unlock(&mdev->mic_mutex);
534 return ret;
535 }
536
537 mic_init_device_ctrl(mvdev, dd);
538
539 mvdev->dd = dd;
540 mvdev->virtio_id = type;
541 vqconfig = mic_vq_config(dd);
542 INIT_WORK(&mvdev->virtio_bh_work, mic_bh_handler);
543
544 for (i = 0; i < dd->num_vq; i++) {
545 struct mic_vringh *mvr = &mvdev->mvr[i];
546 struct mic_vring *vr = &mvdev->mvr[i].vring;
547 num = le16_to_cpu(vqconfig[i].num);
548 mutex_init(&mvr->vr_mutex);
549 vr_size = PAGE_ALIGN(vring_size(num, MIC_VIRTIO_RING_ALIGN) +
550 sizeof(struct _mic_vring_info));
551 vr->va = (void *)
552 __get_free_pages(GFP_KERNEL | __GFP_ZERO,
553 get_order(vr_size));
554 if (!vr->va) {
555 ret = -ENOMEM;
556 dev_err(mic_dev(mvdev), "%s %d err %d\n",
557 __func__, __LINE__, ret);
558 goto err;
559 }
560 vr->len = vr_size;
561 vr->info = vr->va + vring_size(num, MIC_VIRTIO_RING_ALIGN);
562 vr->info->magic = MIC_MAGIC + mvdev->virtio_id + i;
563 vqconfig[i].address = mic_map_single(mdev,
564 vr->va, vr_size);
565 if (mic_map_error(vqconfig[i].address)) {
566 free_pages((unsigned long)vr->va, get_order(vr_size));
567 ret = -ENOMEM;
568 dev_err(mic_dev(mvdev), "%s %d err %d\n",
569 __func__, __LINE__, ret);
570 goto err;
571 }
572 vqconfig[i].address = cpu_to_le64(vqconfig[i].address);
573
574 vring_init(&vr->vr, num, vr->va, MIC_VIRTIO_RING_ALIGN);
575 ret = vringh_init_kern(&mvr->vrh,
576 *(u32 *)mic_vq_features(mvdev->dd), num, false,
577 vr->vr.desc, vr->vr.avail, vr->vr.used);
578 if (ret) {
579 dev_err(mic_dev(mvdev), "%s %d err %d\n",
580 __func__, __LINE__, ret);
581 goto err;
582 }
583 vringh_kiov_init(&mvr->riov, NULL, 0);
584 vringh_kiov_init(&mvr->wiov, NULL, 0);
585 mvr->head = USHRT_MAX;
586 mvr->mvdev = mvdev;
587 mvr->vrh.notify = mic_notify;
588 dev_dbg(mdev->sdev->parent,
589 "%s %d index %d va %p info %p vr_size 0x%x\n",
590 __func__, __LINE__, i, vr->va, vr->info, vr_size);
591 }
592
593 snprintf(irqname, sizeof(irqname), "mic%dvirtio%d", mdev->id,
594 mvdev->virtio_id);
595 mvdev->virtio_db = mic_next_db(mdev);
596 mvdev->virtio_cookie = mic_request_irq(mdev, mic_virtio_intr_handler,
597 irqname, mvdev, mvdev->virtio_db, MIC_INTR_DB);
598 if (IS_ERR(mvdev->virtio_cookie)) {
599 ret = PTR_ERR(mvdev->virtio_cookie);
600 dev_dbg(mdev->sdev->parent, "request irq failed\n");
601 goto err;
602 }
603
604 mvdev->dc->c2h_vdev_db = mvdev->virtio_db;
605
606 list_add_tail(&mvdev->list, &mdev->vdev_list);
607 /*
608 * Order the type update with previous stores. This write barrier
609 * is paired with the corresponding read barrier before the uncached
610 * system memory read of the type, on the card while scanning the
611 * device page.
612 */
613 smp_wmb();
614 dd->type = type;
615
616 dev_dbg(mdev->sdev->parent, "Added virtio device id %d\n", dd->type);
617
618 db = bootparam->h2c_config_db;
619 if (db != -1)
620 mdev->ops->send_intr(mdev, db);
621 mutex_unlock(&mdev->mic_mutex);
622 return 0;
623err:
624 vqconfig = mic_vq_config(dd);
625 for (j = 0; j < i; j++) {
626 struct mic_vringh *mvr = &mvdev->mvr[j];
627 mic_unmap_single(mdev, le64_to_cpu(vqconfig[j].address),
628 mvr->vring.len);
629 free_pages((unsigned long)mvr->vring.va,
630 get_order(mvr->vring.len));
631 }
632 mutex_unlock(&mdev->mic_mutex);
633 return ret;
634}
635
636void mic_virtio_del_device(struct mic_vdev *mvdev)
637{
638 struct list_head *pos, *tmp;
639 struct mic_vdev *tmp_mvdev;
640 struct mic_device *mdev = mvdev->mdev;
641 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
642 int i, ret, retry = 100;
643 struct mic_vqconfig *vqconfig;
644 struct mic_bootparam *bootparam = mdev->dp;
645 s8 db;
646
647 mutex_lock(&mdev->mic_mutex);
648 db = bootparam->h2c_config_db;
649 if (db == -1)
650 goto skip_hot_remove;
651 dev_dbg(mdev->sdev->parent,
652 "Requesting hot remove id %d\n", mvdev->virtio_id);
653 mvdev->dc->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE;
654 mdev->ops->send_intr(mdev, db);
655 for (i = retry; i--;) {
656 ret = wait_event_timeout(wake,
657 mvdev->dc->guest_ack, msecs_to_jiffies(100));
658 if (ret)
659 break;
660 }
661 dev_dbg(mdev->sdev->parent,
662 "Device id %d config_change %d guest_ack %d\n",
663 mvdev->virtio_id, mvdev->dc->config_change,
664 mvdev->dc->guest_ack);
665 mvdev->dc->config_change = 0;
666 mvdev->dc->guest_ack = 0;
667skip_hot_remove:
668 mic_free_irq(mdev, mvdev->virtio_cookie, mvdev);
669 flush_work(&mvdev->virtio_bh_work);
670 vqconfig = mic_vq_config(mvdev->dd);
671 for (i = 0; i < mvdev->dd->num_vq; i++) {
672 struct mic_vringh *mvr = &mvdev->mvr[i];
673 vringh_kiov_cleanup(&mvr->riov);
674 vringh_kiov_cleanup(&mvr->wiov);
675 mic_unmap_single(mdev, le64_to_cpu(vqconfig[i].address),
676 mvr->vring.len);
677 free_pages((unsigned long)mvr->vring.va,
678 get_order(mvr->vring.len));
679 }
680
681 list_for_each_safe(pos, tmp, &mdev->vdev_list) {
682 tmp_mvdev = list_entry(pos, struct mic_vdev, list);
683 if (tmp_mvdev == mvdev) {
684 list_del(pos);
685 dev_dbg(mdev->sdev->parent,
686 "Removing virtio device id %d\n",
687 mvdev->virtio_id);
688 break;
689 }
690 }
691 /*
692 * Order the type update with previous stores. This write barrier
693 * is paired with the corresponding read barrier before the uncached
694 * system memory read of the type, on the card while scanning the
695 * device page.
696 */
697 smp_wmb();
698 mvdev->dd->type = -1;
699 mutex_unlock(&mdev->mic_mutex);
700}
diff --git a/drivers/misc/mic/host/mic_virtio.h b/drivers/misc/mic/host/mic_virtio.h
new file mode 100644
index 000000000000..184f3c84805b
--- /dev/null
+++ b/drivers/misc/mic/host/mic_virtio.h
@@ -0,0 +1,138 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#ifndef MIC_VIRTIO_H
22#define MIC_VIRTIO_H
23
24#include <linux/virtio_config.h>
25#include <linux/mic_ioctl.h>
26
27/*
28 * Note on endianness.
29 * 1. Host can be both BE or LE
30 * 2. Guest/card is LE. Host uses le_to_cpu to access desc/avail
31 * rings and ioreadXX/iowriteXX to access used ring.
32 * 3. Device page exposed by host to guest contains LE values. Guest
33 * accesses these using ioreadXX/iowriteXX etc. This way in general we
34 * obey the virtio spec according to which guest works with native
35 * endianness and host is aware of guest endianness and does all
36 * required endianness conversion.
37 * 4. Data provided from user space to guest (in ADD_DEVICE and
38 * CONFIG_CHANGE ioctl's) is not interpreted by the driver and should be
39 * in guest endianness.
40 */
41
42/**
43 * struct mic_vringh - Virtio ring host information.
44 *
45 * @vring: The MIC vring used for setting up user space mappings.
46 * @vrh: The host VRINGH used for accessing the card vrings.
47 * @riov: The VRINGH read 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.
51 * @mvdev: Back pointer to MIC virtio device for vringh_notify(..).
52 */
53struct mic_vringh {
54 struct mic_vring vring;
55 struct vringh vrh;
56 struct vringh_kiov riov;
57 struct vringh_kiov wiov;
58 u16 head;
59 struct mutex vr_mutex;
60 struct mic_vdev *mvdev;
61};
62
63/**
64 * struct mic_vdev - Host information for a card Virtio device.
65 *
66 * @virtio_id - Virtio device id.
67 * @waitq - Waitqueue to allow ring3 apps to poll.
68 * @mdev - Back pointer to host MIC device.
69 * @poll_wake - Used for waking up threads blocked in poll.
70 * @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.
72 * @mvr - Store per VRING data structures.
73 * @virtio_bh_work - Work struct used to schedule virtio bottom half handling.
74 * @dd - Virtio device descriptor.
75 * @dc - Virtio device control fields.
76 * @list - List of Virtio devices.
77 * @virtio_db - The doorbell used by the card to interrupt the host.
78 * @virtio_cookie - The cookie returned while requesting interrupts.
79 */
80struct mic_vdev {
81 int virtio_id;
82 wait_queue_head_t waitq;
83 struct mic_device *mdev;
84 int poll_wake;
85 unsigned long out_bytes;
86 unsigned long in_bytes;
87 struct mic_vringh mvr[MIC_MAX_VRINGS];
88 struct work_struct virtio_bh_work;
89 struct mic_device_desc *dd;
90 struct mic_device_ctrl *dc;
91 struct list_head list;
92 int virtio_db;
93 struct mic_irq *virtio_cookie;
94};
95
96void mic_virtio_uninit(struct mic_device *mdev);
97int mic_virtio_add_device(struct mic_vdev *mvdev,
98 void __user *argp);
99void mic_virtio_del_device(struct mic_vdev *mvdev);
100int mic_virtio_config_change(struct mic_vdev *mvdev,
101 void __user *argp);
102int mic_virtio_copy_desc(struct mic_vdev *mvdev,
103 struct mic_copy_desc *request);
104void mic_virtio_reset_devices(struct mic_device *mdev);
105void mic_bh_handler(struct work_struct *work);
106
107/* Helper API to obtain the MIC PCIe device */
108static inline struct device *mic_dev(struct mic_vdev *mvdev)
109{
110 return mvdev->mdev->sdev->parent;
111}
112
113/* Helper API to check if a virtio device is initialized */
114static inline int mic_vdev_inited(struct mic_vdev *mvdev)
115{
116 /* Device has not been created yet */
117 if (!mvdev->dd || !mvdev->dd->type) {
118 dev_err(mic_dev(mvdev), "%s %d err %d\n",
119 __func__, __LINE__, -EINVAL);
120 return -EINVAL;
121 }
122
123 /* Device has been removed/deleted */
124 if (mvdev->dd->type == -1) {
125 dev_err(mic_dev(mvdev), "%s %d err %d\n",
126 __func__, __LINE__, -ENODEV);
127 return -ENODEV;
128 }
129
130 return 0;
131}
132
133/* Helper API to check if a virtio device is running */
134static inline bool mic_vdevup(struct mic_vdev *mvdev)
135{
136 return !!mvdev->dd->status;
137}
138#endif
diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c
new file mode 100644
index 000000000000..81e9541b784c
--- /dev/null
+++ b/drivers/misc/mic/host/mic_x100.c
@@ -0,0 +1,570 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#include <linux/fs.h>
22#include <linux/pci.h>
23#include <linux/sched.h>
24#include <linux/firmware.h>
25#include <linux/delay.h>
26
27#include "../common/mic_dev.h"
28#include "mic_device.h"
29#include "mic_x100.h"
30#include "mic_smpt.h"
31
32/**
33 * mic_x100_write_spad - write to the scratchpad register
34 * @mdev: pointer to mic_device instance
35 * @idx: index to the scratchpad register, 0 based
36 * @val: the data value to put into the register
37 *
38 * This function allows writing of a 32bit value to the indexed scratchpad
39 * register.
40 *
41 * RETURNS: none.
42 */
43static void
44mic_x100_write_spad(struct mic_device *mdev, unsigned int idx, u32 val)
45{
46 dev_dbg(mdev->sdev->parent, "Writing 0x%x to scratch pad index %d\n",
47 val, idx);
48 mic_mmio_write(&mdev->mmio, val,
49 MIC_X100_SBOX_BASE_ADDRESS +
50 MIC_X100_SBOX_SPAD0 + idx * 4);
51}
52
53/**
54 * mic_x100_read_spad - read from the scratchpad register
55 * @mdev: pointer to mic_device instance
56 * @idx: index to scratchpad register, 0 based
57 *
58 * This function allows reading of the 32bit scratchpad register.
59 *
60 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
61 */
62static u32
63mic_x100_read_spad(struct mic_device *mdev, unsigned int idx)
64{
65 u32 val = mic_mmio_read(&mdev->mmio,
66 MIC_X100_SBOX_BASE_ADDRESS +
67 MIC_X100_SBOX_SPAD0 + idx * 4);
68
69 dev_dbg(mdev->sdev->parent,
70 "Reading 0x%x from scratch pad index %d\n", val, idx);
71 return val;
72}
73
74/**
75 * mic_x100_enable_interrupts - Enable interrupts.
76 * @mdev: pointer to mic_device instance
77 */
78static void mic_x100_enable_interrupts(struct mic_device *mdev)
79{
80 u32 reg;
81 struct mic_mw *mw = &mdev->mmio;
82 u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
83 u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;
84
85 reg = mic_mmio_read(mw, sice0);
86 reg |= MIC_X100_SBOX_DBR_BITS(0xf) | MIC_X100_SBOX_DMA_BITS(0xff);
87 mic_mmio_write(mw, reg, sice0);
88
89 /*
90 * Enable auto-clear when enabling interrupts. Applicable only for
91 * MSI-x. Legacy and MSI mode cannot have auto-clear enabled.
92 */
93 if (mdev->irq_info.num_vectors > 1) {
94 reg = mic_mmio_read(mw, siac0);
95 reg |= MIC_X100_SBOX_DBR_BITS(0xf) |
96 MIC_X100_SBOX_DMA_BITS(0xff);
97 mic_mmio_write(mw, reg, siac0);
98 }
99}
100
101/**
102 * mic_x100_disable_interrupts - Disable interrupts.
103 * @mdev: pointer to mic_device instance
104 */
105static void mic_x100_disable_interrupts(struct mic_device *mdev)
106{
107 u32 reg;
108 struct mic_mw *mw = &mdev->mmio;
109 u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
110 u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;
111 u32 sicc0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICC0;
112
113 reg = mic_mmio_read(mw, sice0);
114 mic_mmio_write(mw, reg, sicc0);
115
116 if (mdev->irq_info.num_vectors > 1) {
117 reg = mic_mmio_read(mw, siac0);
118 reg &= ~(MIC_X100_SBOX_DBR_BITS(0xf) |
119 MIC_X100_SBOX_DMA_BITS(0xff));
120 mic_mmio_write(mw, reg, siac0);
121 }
122}
123
124/**
125 * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC.
126 * @mdev: pointer to mic_device instance
127 */
128static void mic_x100_send_sbox_intr(struct mic_device *mdev,
129 int doorbell)
130{
131 struct mic_mw *mw = &mdev->mmio;
132 u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
133 u32 apicicr_low = mic_mmio_read(mw, MIC_X100_SBOX_BASE_ADDRESS +
134 apic_icr_offset);
135
136 /* for MIC we need to make sure we "hit" the send_icr bit (13) */
137 apicicr_low = (apicicr_low | (1 << 13));
138
139 /* Ensure that the interrupt is ordered w.r.t. previous stores. */
140 wmb();
141 mic_mmio_write(mw, apicicr_low,
142 MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
143}
144
145/**
146 * mic_x100_send_rdmasr_intr - Send an RDMASR interrupt to MIC.
147 * @mdev: pointer to mic_device instance
148 */
149static void mic_x100_send_rdmasr_intr(struct mic_device *mdev,
150 int doorbell)
151{
152 int rdmasr_offset = MIC_X100_SBOX_RDMASR0 + (doorbell << 2);
153 /* Ensure that the interrupt is ordered w.r.t. previous stores. */
154 wmb();
155 mic_mmio_write(&mdev->mmio, 0,
156 MIC_X100_SBOX_BASE_ADDRESS + rdmasr_offset);
157}
158
159/**
160 * __mic_x100_send_intr - Send interrupt to MIC.
161 * @mdev: pointer to mic_device instance
162 * @doorbell: doorbell number.
163 */
164static void mic_x100_send_intr(struct mic_device *mdev, int doorbell)
165{
166 int rdmasr_db;
167 if (doorbell < MIC_X100_NUM_SBOX_IRQ) {
168 mic_x100_send_sbox_intr(mdev, doorbell);
169 } else {
170 rdmasr_db = doorbell - MIC_X100_NUM_SBOX_IRQ +
171 MIC_X100_RDMASR_IRQ_BASE;
172 mic_x100_send_rdmasr_intr(mdev, rdmasr_db);
173 }
174}
175
176/**
177 * mic_ack_interrupt - Device specific interrupt handling.
178 * @mdev: pointer to mic_device instance
179 *
180 * Returns: bitmask of doorbell events triggered.
181 */
182static u32 mic_x100_ack_interrupt(struct mic_device *mdev)
183{
184 u32 reg = 0;
185 struct mic_mw *mw = &mdev->mmio;
186 u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICR0;
187
188 /* Clear pending bit array. */
189 if (MIC_A0_STEP == mdev->stepping)
190 mic_mmio_write(mw, 1, MIC_X100_SBOX_BASE_ADDRESS +
191 MIC_X100_SBOX_MSIXPBACR);
192
193 if (mdev->irq_info.num_vectors <= 1) {
194 reg = mic_mmio_read(mw, sicr0);
195
196 if (unlikely(!reg))
197 goto done;
198
199 mic_mmio_write(mw, reg, sicr0);
200 }
201
202 if (mdev->stepping >= MIC_B0_STEP)
203 mdev->intr_ops->enable_interrupts(mdev);
204done:
205 return reg;
206}
207
208/**
209 * mic_x100_hw_intr_init - Initialize h/w specific interrupt
210 * information.
211 * @mdev: pointer to mic_device instance
212 */
213static void mic_x100_hw_intr_init(struct mic_device *mdev)
214{
215 mdev->intr_info = (struct mic_intr_info *)mic_x100_intr_init;
216}
217
218/**
219 * mic_x100_read_msi_to_src_map - read from the MSI mapping registers
220 * @mdev: pointer to mic_device instance
221 * @idx: index to the mapping register, 0 based
222 *
223 * This function allows reading of the 32bit MSI mapping register.
224 *
225 * RETURNS: The value in the register.
226 */
227static u32
228mic_x100_read_msi_to_src_map(struct mic_device *mdev, int idx)
229{
230 return mic_mmio_read(&mdev->mmio,
231 MIC_X100_SBOX_BASE_ADDRESS +
232 MIC_X100_SBOX_MXAR0 + idx * 4);
233}
234
235/**
236 * mic_x100_program_msi_to_src_map - program the MSI mapping registers
237 * @mdev: pointer to mic_device instance
238 * @idx: index to the mapping register, 0 based
239 * @offset: The bit offset in the register that needs to be updated.
240 * @set: boolean specifying if the bit in the specified offset needs
241 * to be set or cleared.
242 *
243 * RETURNS: None.
244 */
245static void
246mic_x100_program_msi_to_src_map(struct mic_device *mdev,
247 int idx, int offset, bool set)
248{
249 unsigned long reg;
250 struct mic_mw *mw = &mdev->mmio;
251 u32 mxar = MIC_X100_SBOX_BASE_ADDRESS +
252 MIC_X100_SBOX_MXAR0 + idx * 4;
253
254 reg = mic_mmio_read(mw, mxar);
255 if (set)
256 __set_bit(offset, &reg);
257 else
258 __clear_bit(offset, &reg);
259 mic_mmio_write(mw, reg, mxar);
260}
261
262/*
263 * mic_x100_reset_fw_ready - Reset Firmware ready status field.
264 * @mdev: pointer to mic_device instance
265 */
266static void mic_x100_reset_fw_ready(struct mic_device *mdev)
267{
268 mdev->ops->write_spad(mdev, MIC_X100_DOWNLOAD_INFO, 0);
269}
270
271/*
272 * mic_x100_is_fw_ready - Check if firmware is ready.
273 * @mdev: pointer to mic_device instance
274 */
275static bool mic_x100_is_fw_ready(struct mic_device *mdev)
276{
277 u32 scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
278 return MIC_X100_SPAD2_DOWNLOAD_STATUS(scratch2) ? true : false;
279}
280
281/**
282 * mic_x100_get_apic_id - Get bootstrap APIC ID.
283 * @mdev: pointer to mic_device instance
284 */
285static u32 mic_x100_get_apic_id(struct mic_device *mdev)
286{
287 u32 scratch2 = 0;
288
289 scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
290 return MIC_X100_SPAD2_APIC_ID(scratch2);
291}
292
293/**
294 * mic_x100_send_firmware_intr - Send an interrupt to the firmware on MIC.
295 * @mdev: pointer to mic_device instance
296 */
297static void mic_x100_send_firmware_intr(struct mic_device *mdev)
298{
299 u32 apicicr_low;
300 u64 apic_icr_offset = MIC_X100_SBOX_APICICR7;
301 int vector = MIC_X100_BSP_INTERRUPT_VECTOR;
302 struct mic_mw *mw = &mdev->mmio;
303
304 /*
305 * For MIC we need to make sure we "hit"
306 * the send_icr bit (13).
307 */
308 apicicr_low = (vector | (1 << 13));
309
310 mic_mmio_write(mw, mic_x100_get_apic_id(mdev),
311 MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset + 4);
312
313 /* Ensure that the interrupt is ordered w.r.t. previous stores. */
314 wmb();
315 mic_mmio_write(mw, apicicr_low,
316 MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
317}
318
319/**
320 * mic_x100_hw_reset - Reset the MIC device.
321 * @mdev: pointer to mic_device instance
322 */
323static void mic_x100_hw_reset(struct mic_device *mdev)
324{
325 u32 reset_reg;
326 u32 rgcr = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_RGCR;
327 struct mic_mw *mw = &mdev->mmio;
328
329 /* Ensure that the reset is ordered w.r.t. previous loads and stores */
330 mb();
331 /* Trigger reset */
332 reset_reg = mic_mmio_read(mw, rgcr);
333 reset_reg |= 0x1;
334 mic_mmio_write(mw, reset_reg, rgcr);
335 /*
336 * It seems we really want to delay at least 1 second
337 * after touching reset to prevent a lot of problems.
338 */
339 msleep(1000);
340}
341
342/**
343 * mic_x100_load_command_line - Load command line to MIC.
344 * @mdev: pointer to mic_device instance
345 * @fw: the firmware image
346 *
347 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
348 */
349static int
350mic_x100_load_command_line(struct mic_device *mdev, const struct firmware *fw)
351{
352 u32 len = 0;
353 u32 boot_mem;
354 char *buf;
355 void __iomem *cmd_line_va = mdev->aper.va + mdev->bootaddr + fw->size;
356#define CMDLINE_SIZE 2048
357
358 boot_mem = mdev->aper.len >> 20;
359 buf = kzalloc(CMDLINE_SIZE, GFP_KERNEL);
360 if (!buf) {
361 dev_err(mdev->sdev->parent,
362 "%s %d allocation failed\n", __func__, __LINE__);
363 return -ENOMEM;
364 }
365 len += snprintf(buf, CMDLINE_SIZE - len,
366 " mem=%dM", boot_mem);
367 if (mdev->cmdline)
368 snprintf(buf + len, CMDLINE_SIZE - len, " %s", mdev->cmdline);
369 memcpy_toio(cmd_line_va, buf, strlen(buf) + 1);
370 kfree(buf);
371 return 0;
372}
373
374/**
375 * mic_x100_load_ramdisk - Load ramdisk to MIC.
376 * @mdev: pointer to mic_device instance
377 *
378 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
379 */
380static int
381mic_x100_load_ramdisk(struct mic_device *mdev)
382{
383 const struct firmware *fw;
384 int rc;
385 struct boot_params __iomem *bp = mdev->aper.va + mdev->bootaddr;
386
387 rc = request_firmware(&fw,
388 mdev->ramdisk, mdev->sdev->parent);
389 if (rc < 0) {
390 dev_err(mdev->sdev->parent,
391 "ramdisk request_firmware failed: %d %s\n",
392 rc, mdev->ramdisk);
393 goto error;
394 }
395 /*
396 * Typically the bootaddr for card OS is 64M
397 * so copy over the ramdisk @ 128M.
398 */
399 memcpy_toio(mdev->aper.va + (mdev->bootaddr << 1), fw->data, fw->size);
400 iowrite32(cpu_to_le32(mdev->bootaddr << 1), &bp->hdr.ramdisk_image);
401 iowrite32(cpu_to_le32(fw->size), &bp->hdr.ramdisk_size);
402 release_firmware(fw);
403error:
404 return rc;
405}
406
407/**
408 * mic_x100_get_boot_addr - Get MIC boot address.
409 * @mdev: pointer to mic_device instance
410 *
411 * This function is called during firmware load to determine
412 * the address at which the OS should be downloaded in card
413 * memory i.e. GDDR.
414 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
415 */
416static int
417mic_x100_get_boot_addr(struct mic_device *mdev)
418{
419 u32 scratch2, boot_addr;
420 int rc = 0;
421
422 scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
423 boot_addr = MIC_X100_SPAD2_DOWNLOAD_ADDR(scratch2);
424 dev_dbg(mdev->sdev->parent, "%s %d boot_addr 0x%x\n",
425 __func__, __LINE__, boot_addr);
426 if (boot_addr > (1 << 31)) {
427 dev_err(mdev->sdev->parent,
428 "incorrect bootaddr 0x%x\n",
429 boot_addr);
430 rc = -EINVAL;
431 goto error;
432 }
433 mdev->bootaddr = boot_addr;
434error:
435 return rc;
436}
437
438/**
439 * mic_x100_load_firmware - Load firmware to MIC.
440 * @mdev: pointer to mic_device instance
441 * @buf: buffer containing boot string including firmware/ramdisk path.
442 *
443 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
444 */
445static int
446mic_x100_load_firmware(struct mic_device *mdev, const char *buf)
447{
448 int rc;
449 const struct firmware *fw;
450
451 rc = mic_x100_get_boot_addr(mdev);
452 if (rc)
453 goto error;
454 /* load OS */
455 rc = request_firmware(&fw, mdev->firmware, mdev->sdev->parent);
456 if (rc < 0) {
457 dev_err(mdev->sdev->parent,
458 "ramdisk request_firmware failed: %d %s\n",
459 rc, mdev->firmware);
460 goto error;
461 }
462 if (mdev->bootaddr > mdev->aper.len - fw->size) {
463 rc = -EINVAL;
464 dev_err(mdev->sdev->parent, "%s %d rc %d bootaddr 0x%x\n",
465 __func__, __LINE__, rc, mdev->bootaddr);
466 release_firmware(fw);
467 goto error;
468 }
469 memcpy_toio(mdev->aper.va + mdev->bootaddr, fw->data, fw->size);
470 mdev->ops->write_spad(mdev, MIC_X100_FW_SIZE, fw->size);
471 if (!strcmp(mdev->bootmode, "elf"))
472 goto done;
473 /* load command line */
474 rc = mic_x100_load_command_line(mdev, fw);
475 if (rc) {
476 dev_err(mdev->sdev->parent, "%s %d rc %d\n",
477 __func__, __LINE__, rc);
478 goto error;
479 }
480 release_firmware(fw);
481 /* load ramdisk */
482 if (mdev->ramdisk)
483 rc = mic_x100_load_ramdisk(mdev);
484error:
485 dev_dbg(mdev->sdev->parent, "%s %d rc %d\n", __func__, __LINE__, rc);
486done:
487 return rc;
488}
489
490/**
491 * mic_x100_get_postcode - Get postcode status from firmware.
492 * @mdev: pointer to mic_device instance
493 *
494 * RETURNS: postcode.
495 */
496static u32 mic_x100_get_postcode(struct mic_device *mdev)
497{
498 return mic_mmio_read(&mdev->mmio, MIC_X100_POSTCODE);
499}
500
501/**
502 * mic_x100_smpt_set - Update an SMPT entry with a DMA address.
503 * @mdev: pointer to mic_device instance
504 *
505 * RETURNS: none.
506 */
507static void
508mic_x100_smpt_set(struct mic_device *mdev, dma_addr_t dma_addr, u8 index)
509{
510#define SNOOP_ON (0 << 0)
511#define SNOOP_OFF (1 << 0)
512/*
513 * Sbox Smpt Reg Bits:
514 * Bits 31:2 Host address
515 * Bits 1 RSVD
516 * Bits 0 No snoop
517 */
518#define BUILD_SMPT(NO_SNOOP, HOST_ADDR) \
519 (u32)(((HOST_ADDR) << 2) | ((NO_SNOOP) & 0x01))
520
521 uint32_t smpt_reg_val = BUILD_SMPT(SNOOP_ON,
522 dma_addr >> mdev->smpt->info.page_shift);
523 mic_mmio_write(&mdev->mmio, smpt_reg_val,
524 MIC_X100_SBOX_BASE_ADDRESS +
525 MIC_X100_SBOX_SMPT00 + (4 * index));
526}
527
528/**
529 * mic_x100_smpt_hw_init - Initialize SMPT X100 specific fields.
530 * @mdev: pointer to mic_device instance
531 *
532 * RETURNS: none.
533 */
534static void mic_x100_smpt_hw_init(struct mic_device *mdev)
535{
536 struct mic_smpt_hw_info *info = &mdev->smpt->info;
537
538 info->num_reg = 32;
539 info->page_shift = 34;
540 info->page_size = (1ULL << info->page_shift);
541 info->base = 0x8000000000ULL;
542}
543
544struct mic_smpt_ops mic_x100_smpt_ops = {
545 .init = mic_x100_smpt_hw_init,
546 .set = mic_x100_smpt_set,
547};
548
549struct mic_hw_ops mic_x100_ops = {
550 .aper_bar = MIC_X100_APER_BAR,
551 .mmio_bar = MIC_X100_MMIO_BAR,
552 .read_spad = mic_x100_read_spad,
553 .write_spad = mic_x100_write_spad,
554 .send_intr = mic_x100_send_intr,
555 .ack_interrupt = mic_x100_ack_interrupt,
556 .reset = mic_x100_hw_reset,
557 .reset_fw_ready = mic_x100_reset_fw_ready,
558 .is_fw_ready = mic_x100_is_fw_ready,
559 .send_firmware_intr = mic_x100_send_firmware_intr,
560 .load_mic_fw = mic_x100_load_firmware,
561 .get_postcode = mic_x100_get_postcode,
562};
563
564struct mic_hw_intr_ops mic_x100_intr_ops = {
565 .intr_init = mic_x100_hw_intr_init,
566 .enable_interrupts = mic_x100_enable_interrupts,
567 .disable_interrupts = mic_x100_disable_interrupts,
568 .program_msi_to_src_map = mic_x100_program_msi_to_src_map,
569 .read_msi_to_src_map = mic_x100_read_msi_to_src_map,
570};
diff --git a/drivers/misc/mic/host/mic_x100.h b/drivers/misc/mic/host/mic_x100.h
new file mode 100644
index 000000000000..8b7daa182e54
--- /dev/null
+++ b/drivers/misc/mic/host/mic_x100.h
@@ -0,0 +1,98 @@
1/*
2 * Intel MIC Platform Software Stack (MPSS)
3 *
4 * Copyright(c) 2013 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 * Intel MIC Host driver.
19 *
20 */
21#ifndef _MIC_X100_HW_H_
22#define _MIC_X100_HW_H_
23
24#define MIC_X100_PCI_DEVICE_2250 0x2250
25#define MIC_X100_PCI_DEVICE_2251 0x2251
26#define MIC_X100_PCI_DEVICE_2252 0x2252
27#define MIC_X100_PCI_DEVICE_2253 0x2253
28#define MIC_X100_PCI_DEVICE_2254 0x2254
29#define MIC_X100_PCI_DEVICE_2255 0x2255
30#define MIC_X100_PCI_DEVICE_2256 0x2256
31#define MIC_X100_PCI_DEVICE_2257 0x2257
32#define MIC_X100_PCI_DEVICE_2258 0x2258
33#define MIC_X100_PCI_DEVICE_2259 0x2259
34#define MIC_X100_PCI_DEVICE_225a 0x225a
35#define MIC_X100_PCI_DEVICE_225b 0x225b
36#define MIC_X100_PCI_DEVICE_225c 0x225c
37#define MIC_X100_PCI_DEVICE_225d 0x225d
38#define MIC_X100_PCI_DEVICE_225e 0x225e
39
40#define MIC_X100_APER_BAR 0
41#define MIC_X100_MMIO_BAR 4
42
43#define MIC_X100_SBOX_BASE_ADDRESS 0x00010000
44#define MIC_X100_SBOX_SPAD0 0x0000AB20
45#define MIC_X100_SBOX_SICR0_DBR(x) ((x) & 0xf)
46#define MIC_X100_SBOX_SICR0_DMA(x) (((x) >> 8) & 0xff)
47#define MIC_X100_SBOX_SICE0_DBR(x) ((x) & 0xf)
48#define MIC_X100_SBOX_DBR_BITS(x) ((x) & 0xf)
49#define MIC_X100_SBOX_SICE0_DMA(x) (((x) >> 8) & 0xff)
50#define MIC_X100_SBOX_DMA_BITS(x) (((x) & 0xff) << 8)
51
52#define MIC_X100_SBOX_APICICR0 0x0000A9D0
53#define MIC_X100_SBOX_SICR0 0x00009004
54#define MIC_X100_SBOX_SICE0 0x0000900C
55#define MIC_X100_SBOX_SICC0 0x00009010
56#define MIC_X100_SBOX_SIAC0 0x00009014
57#define MIC_X100_SBOX_MSIXPBACR 0x00009084
58#define MIC_X100_SBOX_MXAR0 0x00009044
59#define MIC_X100_SBOX_SMPT00 0x00003100
60#define MIC_X100_SBOX_RDMASR0 0x0000B180
61
62#define MIC_X100_DOORBELL_IDX_START 0
63#define MIC_X100_NUM_DOORBELL 4
64#define MIC_X100_DMA_IDX_START 8
65#define MIC_X100_NUM_DMA 8
66#define MIC_X100_ERR_IDX_START 30
67#define MIC_X100_NUM_ERR 1
68
69#define MIC_X100_NUM_SBOX_IRQ 8
70#define MIC_X100_NUM_RDMASR_IRQ 8
71#define MIC_X100_RDMASR_IRQ_BASE 17
72#define MIC_X100_SPAD2_DOWNLOAD_STATUS(x) ((x) & 0x1)
73#define MIC_X100_SPAD2_APIC_ID(x) (((x) >> 1) & 0x1ff)
74#define MIC_X100_SPAD2_DOWNLOAD_ADDR(x) ((x) & 0xfffff000)
75#define MIC_X100_SBOX_APICICR7 0x0000AA08
76#define MIC_X100_SBOX_RGCR 0x00004010
77#define MIC_X100_SBOX_SDBIC0 0x0000CC90
78#define MIC_X100_DOWNLOAD_INFO 2
79#define MIC_X100_FW_SIZE 5
80#define MIC_X100_POSTCODE 0x242c
81
82static const u16 mic_x100_intr_init[] = {
83 MIC_X100_DOORBELL_IDX_START,
84 MIC_X100_DMA_IDX_START,
85 MIC_X100_ERR_IDX_START,
86 MIC_X100_NUM_DOORBELL,
87 MIC_X100_NUM_DMA,
88 MIC_X100_NUM_ERR,
89};
90
91/* Host->Card(bootstrap) Interrupt Vector */
92#define MIC_X100_BSP_INTERRUPT_VECTOR 229
93
94extern struct mic_hw_ops mic_x100_ops;
95extern struct mic_smpt_ops mic_x100_smpt_ops;
96extern struct mic_hw_intr_ops mic_x100_intr_ops;
97
98#endif