]>
Commit | Line | Data |
---|---|---|
3a6a9201 SD |
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> | |
42579226 | 23 | #include <linux/pci.h> |
3a6a9201 SD |
24 | |
25 | #include <linux/mic_common.h> | |
4aa79961 | 26 | #include "../common/mic_dev.h" |
3a6a9201 SD |
27 | #include "mic_device.h" |
28 | #include "mic_smpt.h" | |
f69bcbf3 | 29 | #include "mic_virtio.h" |
3a6a9201 SD |
30 | |
31 | /** | |
32 | * mic_reset - Reset the MIC device. | |
33 | * @mdev: pointer to mic_device instance | |
34 | */ | |
35 | static void mic_reset(struct mic_device *mdev) | |
36 | { | |
37 | int i; | |
38 | ||
39 | #define MIC_RESET_TO (45) | |
40 | ||
16735d02 | 41 | reinit_completion(&mdev->reset_wait); |
3a6a9201 SD |
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)) | |
af190494 | 47 | goto done; |
3a6a9201 SD |
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); | |
af190494 DC |
56 | done: |
57 | complete_all(&mdev->reset_wait); | |
3a6a9201 SD |
58 | } |
59 | ||
60 | /* Initialize the MIC bootparams */ | |
61 | void mic_bootparam_init(struct mic_device *mdev) | |
62 | { | |
63 | struct mic_bootparam *bootparam = mdev->dp; | |
64 | ||
173c0727 | 65 | bootparam->magic = cpu_to_le32(MIC_MAGIC); |
3a6a9201 SD |
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 | */ | |
81 | int mic_start(struct mic_device *mdev, const char *buf) | |
82 | { | |
83 | int rc; | |
84 | mutex_lock(&mdev->mic_mutex); | |
85 | retry: | |
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); | |
108 | unlock_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 | */ | |
120 | void mic_stop(struct mic_device *mdev, bool force) | |
121 | { | |
122 | mutex_lock(&mdev->mic_mutex); | |
123 | if (MIC_OFFLINE != mdev->state || force) { | |
f69bcbf3 | 124 | mic_virtio_reset_devices(mdev); |
3a6a9201 SD |
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); | |
af190494 DC |
130 | if (MIC_SUSPENDED != mdev->state) |
131 | mic_set_state(mdev, MIC_OFFLINE); | |
3a6a9201 SD |
132 | } |
133 | unlock: | |
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 | */ | |
143 | void 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 | */ | |
164 | void 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; | |
af190494 DC |
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) | |
3a6a9201 SD |
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 | */ | |
191 | void 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 | } | |
af190494 DC |
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 | */ | |
206 | void 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 | */ | |
229 | void 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 | */ | |
288 | void 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 | } |