.. | .. |
---|
19 | 19 | static void __ap_flush_queue(struct ap_queue *aq); |
---|
20 | 20 | |
---|
21 | 21 | /** |
---|
22 | | - * ap_queue_enable_interruption(): Enable interruption on an AP queue. |
---|
| 22 | + * ap_queue_enable_irq(): Enable interrupt support on this AP queue. |
---|
23 | 23 | * @qid: The AP queue number |
---|
24 | 24 | * @ind: the notification indicator byte |
---|
25 | 25 | * |
---|
.. | .. |
---|
27 | 27 | * value it waits a while and tests the AP queue if interrupts |
---|
28 | 28 | * have been switched on using ap_test_queue(). |
---|
29 | 29 | */ |
---|
30 | | -static int ap_queue_enable_interruption(struct ap_queue *aq, void *ind) |
---|
| 30 | +static int ap_queue_enable_irq(struct ap_queue *aq, void *ind) |
---|
31 | 31 | { |
---|
32 | 32 | struct ap_queue_status status; |
---|
33 | 33 | struct ap_qirq_ctrl qirqctrl = { 0 }; |
---|
.. | .. |
---|
69 | 69 | */ |
---|
70 | 70 | static inline struct ap_queue_status |
---|
71 | 71 | __ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length, |
---|
72 | | - unsigned int special) |
---|
| 72 | + int special) |
---|
73 | 73 | { |
---|
74 | | - if (special == 1) |
---|
| 74 | + if (special) |
---|
75 | 75 | qid |= 0x400000UL; |
---|
76 | 76 | return ap_nqap(qid, psmid, msg, length); |
---|
77 | 77 | } |
---|
.. | .. |
---|
119 | 119 | |
---|
120 | 120 | /* State machine definitions and helpers */ |
---|
121 | 121 | |
---|
122 | | -static enum ap_wait ap_sm_nop(struct ap_queue *aq) |
---|
| 122 | +static enum ap_sm_wait ap_sm_nop(struct ap_queue *aq) |
---|
123 | 123 | { |
---|
124 | | - return AP_WAIT_NONE; |
---|
| 124 | + return AP_SM_WAIT_NONE; |
---|
125 | 125 | } |
---|
126 | 126 | |
---|
127 | 127 | /** |
---|
.. | .. |
---|
129 | 129 | * not change the state of the device. |
---|
130 | 130 | * @aq: pointer to the AP queue |
---|
131 | 131 | * |
---|
132 | | - * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT |
---|
| 132 | + * Returns AP_SM_WAIT_NONE, AP_SM_WAIT_AGAIN, or AP_SM_WAIT_INTERRUPT |
---|
133 | 133 | */ |
---|
134 | 134 | static struct ap_queue_status ap_sm_recv(struct ap_queue *aq) |
---|
135 | 135 | { |
---|
136 | 136 | struct ap_queue_status status; |
---|
137 | 137 | struct ap_message *ap_msg; |
---|
| 138 | + bool found = false; |
---|
138 | 139 | |
---|
139 | 140 | status = ap_dqap(aq->qid, &aq->reply->psmid, |
---|
140 | | - aq->reply->message, aq->reply->length); |
---|
| 141 | + aq->reply->msg, aq->reply->len); |
---|
141 | 142 | switch (status.response_code) { |
---|
142 | 143 | case AP_RESPONSE_NORMAL: |
---|
143 | | - aq->queue_count--; |
---|
| 144 | + aq->queue_count = max_t(int, 0, aq->queue_count - 1); |
---|
| 145 | + if (!status.queue_empty && !aq->queue_count) |
---|
| 146 | + aq->queue_count++; |
---|
144 | 147 | if (aq->queue_count > 0) |
---|
145 | 148 | mod_timer(&aq->timeout, |
---|
146 | 149 | jiffies + aq->request_timeout); |
---|
.. | .. |
---|
150 | 153 | list_del_init(&ap_msg->list); |
---|
151 | 154 | aq->pendingq_count--; |
---|
152 | 155 | ap_msg->receive(aq, ap_msg, aq->reply); |
---|
| 156 | + found = true; |
---|
153 | 157 | break; |
---|
154 | 158 | } |
---|
| 159 | + if (!found) { |
---|
| 160 | + AP_DBF_WARN("%s unassociated reply psmid=0x%016llx on 0x%02x.%04x\n", |
---|
| 161 | + __func__, aq->reply->psmid, |
---|
| 162 | + AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid)); |
---|
| 163 | + } |
---|
| 164 | + fallthrough; |
---|
155 | 165 | case AP_RESPONSE_NO_PENDING_REPLY: |
---|
156 | 166 | if (!status.queue_empty || aq->queue_count <= 0) |
---|
157 | 167 | break; |
---|
.. | .. |
---|
171 | 181 | * ap_sm_read(): Receive pending reply messages from an AP queue. |
---|
172 | 182 | * @aq: pointer to the AP queue |
---|
173 | 183 | * |
---|
174 | | - * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT |
---|
| 184 | + * Returns AP_SM_WAIT_NONE, AP_SM_WAIT_AGAIN, or AP_SM_WAIT_INTERRUPT |
---|
175 | 185 | */ |
---|
176 | | -static enum ap_wait ap_sm_read(struct ap_queue *aq) |
---|
| 186 | +static enum ap_sm_wait ap_sm_read(struct ap_queue *aq) |
---|
177 | 187 | { |
---|
178 | 188 | struct ap_queue_status status; |
---|
179 | 189 | |
---|
180 | 190 | if (!aq->reply) |
---|
181 | | - return AP_WAIT_NONE; |
---|
| 191 | + return AP_SM_WAIT_NONE; |
---|
182 | 192 | status = ap_sm_recv(aq); |
---|
183 | 193 | switch (status.response_code) { |
---|
184 | 194 | case AP_RESPONSE_NORMAL: |
---|
185 | 195 | if (aq->queue_count > 0) { |
---|
186 | | - aq->state = AP_STATE_WORKING; |
---|
187 | | - return AP_WAIT_AGAIN; |
---|
| 196 | + aq->sm_state = AP_SM_STATE_WORKING; |
---|
| 197 | + return AP_SM_WAIT_AGAIN; |
---|
188 | 198 | } |
---|
189 | | - aq->state = AP_STATE_IDLE; |
---|
190 | | - return AP_WAIT_NONE; |
---|
| 199 | + aq->sm_state = AP_SM_STATE_IDLE; |
---|
| 200 | + return AP_SM_WAIT_NONE; |
---|
191 | 201 | case AP_RESPONSE_NO_PENDING_REPLY: |
---|
192 | 202 | if (aq->queue_count > 0) |
---|
193 | | - return AP_WAIT_INTERRUPT; |
---|
194 | | - aq->state = AP_STATE_IDLE; |
---|
195 | | - return AP_WAIT_NONE; |
---|
| 203 | + return aq->interrupt ? |
---|
| 204 | + AP_SM_WAIT_INTERRUPT : AP_SM_WAIT_TIMEOUT; |
---|
| 205 | + aq->sm_state = AP_SM_STATE_IDLE; |
---|
| 206 | + return AP_SM_WAIT_NONE; |
---|
196 | 207 | default: |
---|
197 | | - aq->state = AP_STATE_BORKED; |
---|
198 | | - return AP_WAIT_NONE; |
---|
199 | | - } |
---|
200 | | -} |
---|
201 | | - |
---|
202 | | -/** |
---|
203 | | - * ap_sm_suspend_read(): Receive pending reply messages from an AP queue |
---|
204 | | - * without changing the device state in between. In suspend mode we don't |
---|
205 | | - * allow sending new requests, therefore just fetch pending replies. |
---|
206 | | - * @aq: pointer to the AP queue |
---|
207 | | - * |
---|
208 | | - * Returns AP_WAIT_NONE or AP_WAIT_AGAIN |
---|
209 | | - */ |
---|
210 | | -static enum ap_wait ap_sm_suspend_read(struct ap_queue *aq) |
---|
211 | | -{ |
---|
212 | | - struct ap_queue_status status; |
---|
213 | | - |
---|
214 | | - if (!aq->reply) |
---|
215 | | - return AP_WAIT_NONE; |
---|
216 | | - status = ap_sm_recv(aq); |
---|
217 | | - switch (status.response_code) { |
---|
218 | | - case AP_RESPONSE_NORMAL: |
---|
219 | | - if (aq->queue_count > 0) |
---|
220 | | - return AP_WAIT_AGAIN; |
---|
221 | | - /* fall through */ |
---|
222 | | - default: |
---|
223 | | - return AP_WAIT_NONE; |
---|
| 208 | + aq->dev_state = AP_DEV_STATE_ERROR; |
---|
| 209 | + aq->last_err_rc = status.response_code; |
---|
| 210 | + AP_DBF_WARN("%s RC 0x%02x on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n", |
---|
| 211 | + __func__, status.response_code, |
---|
| 212 | + AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid)); |
---|
| 213 | + return AP_SM_WAIT_NONE; |
---|
224 | 214 | } |
---|
225 | 215 | } |
---|
226 | 216 | |
---|
.. | .. |
---|
228 | 218 | * ap_sm_write(): Send messages from the request queue to an AP queue. |
---|
229 | 219 | * @aq: pointer to the AP queue |
---|
230 | 220 | * |
---|
231 | | - * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT |
---|
| 221 | + * Returns AP_SM_WAIT_NONE, AP_SM_WAIT_AGAIN, or AP_SM_WAIT_INTERRUPT |
---|
232 | 222 | */ |
---|
233 | | -static enum ap_wait ap_sm_write(struct ap_queue *aq) |
---|
| 223 | +static enum ap_sm_wait ap_sm_write(struct ap_queue *aq) |
---|
234 | 224 | { |
---|
235 | 225 | struct ap_queue_status status; |
---|
236 | 226 | struct ap_message *ap_msg; |
---|
| 227 | + ap_qid_t qid = aq->qid; |
---|
237 | 228 | |
---|
238 | 229 | if (aq->requestq_count <= 0) |
---|
239 | | - return AP_WAIT_NONE; |
---|
| 230 | + return AP_SM_WAIT_NONE; |
---|
240 | 231 | /* Start the next request on the queue. */ |
---|
241 | 232 | ap_msg = list_entry(aq->requestq.next, struct ap_message, list); |
---|
242 | | - status = __ap_send(aq->qid, ap_msg->psmid, |
---|
243 | | - ap_msg->message, ap_msg->length, ap_msg->special); |
---|
| 233 | +#ifdef CONFIG_ZCRYPT_DEBUG |
---|
| 234 | + if (ap_msg->fi.action == AP_FI_ACTION_NQAP_QID_INVAL) { |
---|
| 235 | + AP_DBF_WARN("%s fi cmd 0x%04x: forcing invalid qid 0xFF00\n", |
---|
| 236 | + __func__, ap_msg->fi.cmd); |
---|
| 237 | + qid = 0xFF00; |
---|
| 238 | + } |
---|
| 239 | +#endif |
---|
| 240 | + status = __ap_send(qid, ap_msg->psmid, |
---|
| 241 | + ap_msg->msg, ap_msg->len, |
---|
| 242 | + ap_msg->flags & AP_MSG_FLAG_SPECIAL); |
---|
244 | 243 | switch (status.response_code) { |
---|
245 | 244 | case AP_RESPONSE_NORMAL: |
---|
246 | | - aq->queue_count++; |
---|
| 245 | + aq->queue_count = max_t(int, 1, aq->queue_count + 1); |
---|
247 | 246 | if (aq->queue_count == 1) |
---|
248 | 247 | mod_timer(&aq->timeout, jiffies + aq->request_timeout); |
---|
249 | 248 | list_move_tail(&ap_msg->list, &aq->pendingq); |
---|
250 | 249 | aq->requestq_count--; |
---|
251 | 250 | aq->pendingq_count++; |
---|
252 | 251 | if (aq->queue_count < aq->card->queue_depth) { |
---|
253 | | - aq->state = AP_STATE_WORKING; |
---|
254 | | - return AP_WAIT_AGAIN; |
---|
| 252 | + aq->sm_state = AP_SM_STATE_WORKING; |
---|
| 253 | + return AP_SM_WAIT_AGAIN; |
---|
255 | 254 | } |
---|
256 | | - /* fall through */ |
---|
| 255 | + fallthrough; |
---|
257 | 256 | case AP_RESPONSE_Q_FULL: |
---|
258 | | - aq->state = AP_STATE_QUEUE_FULL; |
---|
259 | | - return AP_WAIT_INTERRUPT; |
---|
| 257 | + aq->sm_state = AP_SM_STATE_QUEUE_FULL; |
---|
| 258 | + return aq->interrupt ? |
---|
| 259 | + AP_SM_WAIT_INTERRUPT : AP_SM_WAIT_TIMEOUT; |
---|
260 | 260 | case AP_RESPONSE_RESET_IN_PROGRESS: |
---|
261 | | - aq->state = AP_STATE_RESET_WAIT; |
---|
262 | | - return AP_WAIT_TIMEOUT; |
---|
| 261 | + aq->sm_state = AP_SM_STATE_RESET_WAIT; |
---|
| 262 | + return AP_SM_WAIT_TIMEOUT; |
---|
| 263 | + case AP_RESPONSE_INVALID_DOMAIN: |
---|
| 264 | + AP_DBF(DBF_WARN, "AP_RESPONSE_INVALID_DOMAIN on NQAP\n"); |
---|
| 265 | + fallthrough; |
---|
263 | 266 | case AP_RESPONSE_MESSAGE_TOO_BIG: |
---|
264 | 267 | case AP_RESPONSE_REQ_FAC_NOT_INST: |
---|
265 | 268 | list_del_init(&ap_msg->list); |
---|
266 | 269 | aq->requestq_count--; |
---|
267 | 270 | ap_msg->rc = -EINVAL; |
---|
268 | 271 | ap_msg->receive(aq, ap_msg, NULL); |
---|
269 | | - return AP_WAIT_AGAIN; |
---|
| 272 | + return AP_SM_WAIT_AGAIN; |
---|
270 | 273 | default: |
---|
271 | | - aq->state = AP_STATE_BORKED; |
---|
272 | | - return AP_WAIT_NONE; |
---|
| 274 | + aq->dev_state = AP_DEV_STATE_ERROR; |
---|
| 275 | + aq->last_err_rc = status.response_code; |
---|
| 276 | + AP_DBF_WARN("%s RC 0x%02x on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n", |
---|
| 277 | + __func__, status.response_code, |
---|
| 278 | + AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid)); |
---|
| 279 | + return AP_SM_WAIT_NONE; |
---|
273 | 280 | } |
---|
274 | 281 | } |
---|
275 | 282 | |
---|
.. | .. |
---|
277 | 284 | * ap_sm_read_write(): Send and receive messages to/from an AP queue. |
---|
278 | 285 | * @aq: pointer to the AP queue |
---|
279 | 286 | * |
---|
280 | | - * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT |
---|
| 287 | + * Returns AP_SM_WAIT_NONE, AP_SM_WAIT_AGAIN, or AP_SM_WAIT_INTERRUPT |
---|
281 | 288 | */ |
---|
282 | | -static enum ap_wait ap_sm_read_write(struct ap_queue *aq) |
---|
| 289 | +static enum ap_sm_wait ap_sm_read_write(struct ap_queue *aq) |
---|
283 | 290 | { |
---|
284 | 291 | return min(ap_sm_read(aq), ap_sm_write(aq)); |
---|
285 | 292 | } |
---|
.. | .. |
---|
290 | 297 | * |
---|
291 | 298 | * Submit the Reset command to an AP queue. |
---|
292 | 299 | */ |
---|
293 | | -static enum ap_wait ap_sm_reset(struct ap_queue *aq) |
---|
| 300 | +static enum ap_sm_wait ap_sm_reset(struct ap_queue *aq) |
---|
294 | 301 | { |
---|
295 | 302 | struct ap_queue_status status; |
---|
296 | 303 | |
---|
.. | .. |
---|
298 | 305 | switch (status.response_code) { |
---|
299 | 306 | case AP_RESPONSE_NORMAL: |
---|
300 | 307 | case AP_RESPONSE_RESET_IN_PROGRESS: |
---|
301 | | - aq->state = AP_STATE_RESET_WAIT; |
---|
302 | | - aq->interrupt = AP_INTR_DISABLED; |
---|
303 | | - return AP_WAIT_TIMEOUT; |
---|
304 | | - case AP_RESPONSE_BUSY: |
---|
305 | | - return AP_WAIT_TIMEOUT; |
---|
306 | | - case AP_RESPONSE_Q_NOT_AVAIL: |
---|
307 | | - case AP_RESPONSE_DECONFIGURED: |
---|
308 | | - case AP_RESPONSE_CHECKSTOPPED: |
---|
| 308 | + aq->sm_state = AP_SM_STATE_RESET_WAIT; |
---|
| 309 | + aq->interrupt = false; |
---|
| 310 | + return AP_SM_WAIT_TIMEOUT; |
---|
309 | 311 | default: |
---|
310 | | - aq->state = AP_STATE_BORKED; |
---|
311 | | - return AP_WAIT_NONE; |
---|
| 312 | + aq->dev_state = AP_DEV_STATE_ERROR; |
---|
| 313 | + aq->last_err_rc = status.response_code; |
---|
| 314 | + AP_DBF_WARN("%s RC 0x%02x on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n", |
---|
| 315 | + __func__, status.response_code, |
---|
| 316 | + AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid)); |
---|
| 317 | + return AP_SM_WAIT_NONE; |
---|
312 | 318 | } |
---|
313 | 319 | } |
---|
314 | 320 | |
---|
.. | .. |
---|
318 | 324 | * |
---|
319 | 325 | * Returns AP_POLL_IMMEDIATELY, AP_POLL_AFTER_TIMEROUT or 0. |
---|
320 | 326 | */ |
---|
321 | | -static enum ap_wait ap_sm_reset_wait(struct ap_queue *aq) |
---|
| 327 | +static enum ap_sm_wait ap_sm_reset_wait(struct ap_queue *aq) |
---|
322 | 328 | { |
---|
323 | 329 | struct ap_queue_status status; |
---|
324 | 330 | void *lsi_ptr; |
---|
.. | .. |
---|
333 | 339 | switch (status.response_code) { |
---|
334 | 340 | case AP_RESPONSE_NORMAL: |
---|
335 | 341 | lsi_ptr = ap_airq_ptr(); |
---|
336 | | - if (lsi_ptr && ap_queue_enable_interruption(aq, lsi_ptr) == 0) |
---|
337 | | - aq->state = AP_STATE_SETIRQ_WAIT; |
---|
| 342 | + if (lsi_ptr && ap_queue_enable_irq(aq, lsi_ptr) == 0) |
---|
| 343 | + aq->sm_state = AP_SM_STATE_SETIRQ_WAIT; |
---|
338 | 344 | else |
---|
339 | | - aq->state = (aq->queue_count > 0) ? |
---|
340 | | - AP_STATE_WORKING : AP_STATE_IDLE; |
---|
341 | | - return AP_WAIT_AGAIN; |
---|
| 345 | + aq->sm_state = (aq->queue_count > 0) ? |
---|
| 346 | + AP_SM_STATE_WORKING : AP_SM_STATE_IDLE; |
---|
| 347 | + return AP_SM_WAIT_AGAIN; |
---|
342 | 348 | case AP_RESPONSE_BUSY: |
---|
343 | 349 | case AP_RESPONSE_RESET_IN_PROGRESS: |
---|
344 | | - return AP_WAIT_TIMEOUT; |
---|
| 350 | + return AP_SM_WAIT_TIMEOUT; |
---|
345 | 351 | case AP_RESPONSE_Q_NOT_AVAIL: |
---|
346 | 352 | case AP_RESPONSE_DECONFIGURED: |
---|
347 | 353 | case AP_RESPONSE_CHECKSTOPPED: |
---|
348 | 354 | default: |
---|
349 | | - aq->state = AP_STATE_BORKED; |
---|
350 | | - return AP_WAIT_NONE; |
---|
| 355 | + aq->dev_state = AP_DEV_STATE_ERROR; |
---|
| 356 | + aq->last_err_rc = status.response_code; |
---|
| 357 | + AP_DBF_WARN("%s RC 0x%02x on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n", |
---|
| 358 | + __func__, status.response_code, |
---|
| 359 | + AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid)); |
---|
| 360 | + return AP_SM_WAIT_NONE; |
---|
351 | 361 | } |
---|
352 | 362 | } |
---|
353 | 363 | |
---|
.. | .. |
---|
357 | 367 | * |
---|
358 | 368 | * Returns AP_POLL_IMMEDIATELY, AP_POLL_AFTER_TIMEROUT or 0. |
---|
359 | 369 | */ |
---|
360 | | -static enum ap_wait ap_sm_setirq_wait(struct ap_queue *aq) |
---|
| 370 | +static enum ap_sm_wait ap_sm_setirq_wait(struct ap_queue *aq) |
---|
361 | 371 | { |
---|
362 | 372 | struct ap_queue_status status; |
---|
363 | 373 | |
---|
.. | .. |
---|
370 | 380 | |
---|
371 | 381 | if (status.irq_enabled == 1) { |
---|
372 | 382 | /* Irqs are now enabled */ |
---|
373 | | - aq->interrupt = AP_INTR_ENABLED; |
---|
374 | | - aq->state = (aq->queue_count > 0) ? |
---|
375 | | - AP_STATE_WORKING : AP_STATE_IDLE; |
---|
| 383 | + aq->interrupt = true; |
---|
| 384 | + aq->sm_state = (aq->queue_count > 0) ? |
---|
| 385 | + AP_SM_STATE_WORKING : AP_SM_STATE_IDLE; |
---|
376 | 386 | } |
---|
377 | 387 | |
---|
378 | 388 | switch (status.response_code) { |
---|
379 | 389 | case AP_RESPONSE_NORMAL: |
---|
380 | 390 | if (aq->queue_count > 0) |
---|
381 | | - return AP_WAIT_AGAIN; |
---|
382 | | - /* fallthrough */ |
---|
| 391 | + return AP_SM_WAIT_AGAIN; |
---|
| 392 | + fallthrough; |
---|
383 | 393 | case AP_RESPONSE_NO_PENDING_REPLY: |
---|
384 | | - return AP_WAIT_TIMEOUT; |
---|
| 394 | + return AP_SM_WAIT_TIMEOUT; |
---|
385 | 395 | default: |
---|
386 | | - aq->state = AP_STATE_BORKED; |
---|
387 | | - return AP_WAIT_NONE; |
---|
| 396 | + aq->dev_state = AP_DEV_STATE_ERROR; |
---|
| 397 | + aq->last_err_rc = status.response_code; |
---|
| 398 | + AP_DBF_WARN("%s RC 0x%02x on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n", |
---|
| 399 | + __func__, status.response_code, |
---|
| 400 | + AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid)); |
---|
| 401 | + return AP_SM_WAIT_NONE; |
---|
388 | 402 | } |
---|
389 | 403 | } |
---|
390 | 404 | |
---|
391 | 405 | /* |
---|
392 | 406 | * AP state machine jump table |
---|
393 | 407 | */ |
---|
394 | | -static ap_func_t *ap_jumptable[NR_AP_STATES][NR_AP_EVENTS] = { |
---|
395 | | - [AP_STATE_RESET_START] = { |
---|
396 | | - [AP_EVENT_POLL] = ap_sm_reset, |
---|
397 | | - [AP_EVENT_TIMEOUT] = ap_sm_nop, |
---|
| 408 | +static ap_func_t *ap_jumptable[NR_AP_SM_STATES][NR_AP_SM_EVENTS] = { |
---|
| 409 | + [AP_SM_STATE_RESET_START] = { |
---|
| 410 | + [AP_SM_EVENT_POLL] = ap_sm_reset, |
---|
| 411 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, |
---|
398 | 412 | }, |
---|
399 | | - [AP_STATE_RESET_WAIT] = { |
---|
400 | | - [AP_EVENT_POLL] = ap_sm_reset_wait, |
---|
401 | | - [AP_EVENT_TIMEOUT] = ap_sm_nop, |
---|
| 413 | + [AP_SM_STATE_RESET_WAIT] = { |
---|
| 414 | + [AP_SM_EVENT_POLL] = ap_sm_reset_wait, |
---|
| 415 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, |
---|
402 | 416 | }, |
---|
403 | | - [AP_STATE_SETIRQ_WAIT] = { |
---|
404 | | - [AP_EVENT_POLL] = ap_sm_setirq_wait, |
---|
405 | | - [AP_EVENT_TIMEOUT] = ap_sm_nop, |
---|
| 417 | + [AP_SM_STATE_SETIRQ_WAIT] = { |
---|
| 418 | + [AP_SM_EVENT_POLL] = ap_sm_setirq_wait, |
---|
| 419 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, |
---|
406 | 420 | }, |
---|
407 | | - [AP_STATE_IDLE] = { |
---|
408 | | - [AP_EVENT_POLL] = ap_sm_write, |
---|
409 | | - [AP_EVENT_TIMEOUT] = ap_sm_nop, |
---|
| 421 | + [AP_SM_STATE_IDLE] = { |
---|
| 422 | + [AP_SM_EVENT_POLL] = ap_sm_write, |
---|
| 423 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, |
---|
410 | 424 | }, |
---|
411 | | - [AP_STATE_WORKING] = { |
---|
412 | | - [AP_EVENT_POLL] = ap_sm_read_write, |
---|
413 | | - [AP_EVENT_TIMEOUT] = ap_sm_reset, |
---|
| 425 | + [AP_SM_STATE_WORKING] = { |
---|
| 426 | + [AP_SM_EVENT_POLL] = ap_sm_read_write, |
---|
| 427 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_reset, |
---|
414 | 428 | }, |
---|
415 | | - [AP_STATE_QUEUE_FULL] = { |
---|
416 | | - [AP_EVENT_POLL] = ap_sm_read, |
---|
417 | | - [AP_EVENT_TIMEOUT] = ap_sm_reset, |
---|
418 | | - }, |
---|
419 | | - [AP_STATE_SUSPEND_WAIT] = { |
---|
420 | | - [AP_EVENT_POLL] = ap_sm_suspend_read, |
---|
421 | | - [AP_EVENT_TIMEOUT] = ap_sm_nop, |
---|
422 | | - }, |
---|
423 | | - [AP_STATE_BORKED] = { |
---|
424 | | - [AP_EVENT_POLL] = ap_sm_nop, |
---|
425 | | - [AP_EVENT_TIMEOUT] = ap_sm_nop, |
---|
| 429 | + [AP_SM_STATE_QUEUE_FULL] = { |
---|
| 430 | + [AP_SM_EVENT_POLL] = ap_sm_read, |
---|
| 431 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_reset, |
---|
426 | 432 | }, |
---|
427 | 433 | }; |
---|
428 | 434 | |
---|
429 | | -enum ap_wait ap_sm_event(struct ap_queue *aq, enum ap_event event) |
---|
| 435 | +enum ap_sm_wait ap_sm_event(struct ap_queue *aq, enum ap_sm_event event) |
---|
430 | 436 | { |
---|
431 | | - return ap_jumptable[aq->state][event](aq); |
---|
| 437 | + if (aq->dev_state > AP_DEV_STATE_UNINITIATED) |
---|
| 438 | + return ap_jumptable[aq->sm_state][event](aq); |
---|
| 439 | + else |
---|
| 440 | + return AP_SM_WAIT_NONE; |
---|
432 | 441 | } |
---|
433 | 442 | |
---|
434 | | -enum ap_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_event event) |
---|
| 443 | +enum ap_sm_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_sm_event event) |
---|
435 | 444 | { |
---|
436 | | - enum ap_wait wait; |
---|
| 445 | + enum ap_sm_wait wait; |
---|
437 | 446 | |
---|
438 | | - while ((wait = ap_sm_event(aq, event)) == AP_WAIT_AGAIN) |
---|
| 447 | + while ((wait = ap_sm_event(aq, event)) == AP_SM_WAIT_AGAIN) |
---|
439 | 448 | ; |
---|
440 | 449 | return wait; |
---|
441 | 450 | } |
---|
442 | | - |
---|
443 | | -/* |
---|
444 | | - * Power management for queue devices |
---|
445 | | - */ |
---|
446 | | -void ap_queue_suspend(struct ap_device *ap_dev) |
---|
447 | | -{ |
---|
448 | | - struct ap_queue *aq = to_ap_queue(&ap_dev->device); |
---|
449 | | - |
---|
450 | | - /* Poll on the device until all requests are finished. */ |
---|
451 | | - spin_lock_bh(&aq->lock); |
---|
452 | | - aq->state = AP_STATE_SUSPEND_WAIT; |
---|
453 | | - while (ap_sm_event(aq, AP_EVENT_POLL) != AP_WAIT_NONE) |
---|
454 | | - ; |
---|
455 | | - aq->state = AP_STATE_BORKED; |
---|
456 | | - spin_unlock_bh(&aq->lock); |
---|
457 | | -} |
---|
458 | | -EXPORT_SYMBOL(ap_queue_suspend); |
---|
459 | | - |
---|
460 | | -void ap_queue_resume(struct ap_device *ap_dev) |
---|
461 | | -{ |
---|
462 | | -} |
---|
463 | | -EXPORT_SYMBOL(ap_queue_resume); |
---|
464 | 451 | |
---|
465 | 452 | /* |
---|
466 | 453 | * AP queue related attributes. |
---|
.. | .. |
---|
470 | 457 | char *buf) |
---|
471 | 458 | { |
---|
472 | 459 | struct ap_queue *aq = to_ap_queue(dev); |
---|
| 460 | + bool valid = false; |
---|
473 | 461 | u64 req_cnt; |
---|
474 | 462 | |
---|
475 | 463 | spin_lock_bh(&aq->lock); |
---|
476 | | - req_cnt = aq->total_request_count; |
---|
| 464 | + if (aq->dev_state > AP_DEV_STATE_UNINITIATED) { |
---|
| 465 | + req_cnt = aq->total_request_count; |
---|
| 466 | + valid = true; |
---|
| 467 | + } |
---|
477 | 468 | spin_unlock_bh(&aq->lock); |
---|
478 | | - return snprintf(buf, PAGE_SIZE, "%llu\n", req_cnt); |
---|
| 469 | + |
---|
| 470 | + if (valid) |
---|
| 471 | + return scnprintf(buf, PAGE_SIZE, "%llu\n", req_cnt); |
---|
| 472 | + else |
---|
| 473 | + return scnprintf(buf, PAGE_SIZE, "-\n"); |
---|
479 | 474 | } |
---|
480 | 475 | |
---|
481 | 476 | static ssize_t request_count_store(struct device *dev, |
---|
.. | .. |
---|
500 | 495 | unsigned int reqq_cnt = 0; |
---|
501 | 496 | |
---|
502 | 497 | spin_lock_bh(&aq->lock); |
---|
503 | | - reqq_cnt = aq->requestq_count; |
---|
| 498 | + if (aq->dev_state > AP_DEV_STATE_UNINITIATED) |
---|
| 499 | + reqq_cnt = aq->requestq_count; |
---|
504 | 500 | spin_unlock_bh(&aq->lock); |
---|
505 | | - return snprintf(buf, PAGE_SIZE, "%d\n", reqq_cnt); |
---|
| 501 | + return scnprintf(buf, PAGE_SIZE, "%d\n", reqq_cnt); |
---|
506 | 502 | } |
---|
507 | 503 | |
---|
508 | 504 | static DEVICE_ATTR_RO(requestq_count); |
---|
.. | .. |
---|
514 | 510 | unsigned int penq_cnt = 0; |
---|
515 | 511 | |
---|
516 | 512 | spin_lock_bh(&aq->lock); |
---|
517 | | - penq_cnt = aq->pendingq_count; |
---|
| 513 | + if (aq->dev_state > AP_DEV_STATE_UNINITIATED) |
---|
| 514 | + penq_cnt = aq->pendingq_count; |
---|
518 | 515 | spin_unlock_bh(&aq->lock); |
---|
519 | | - return snprintf(buf, PAGE_SIZE, "%d\n", penq_cnt); |
---|
| 516 | + return scnprintf(buf, PAGE_SIZE, "%d\n", penq_cnt); |
---|
520 | 517 | } |
---|
521 | 518 | |
---|
522 | 519 | static DEVICE_ATTR_RO(pendingq_count); |
---|
.. | .. |
---|
528 | 525 | int rc = 0; |
---|
529 | 526 | |
---|
530 | 527 | spin_lock_bh(&aq->lock); |
---|
531 | | - switch (aq->state) { |
---|
532 | | - case AP_STATE_RESET_START: |
---|
533 | | - case AP_STATE_RESET_WAIT: |
---|
534 | | - rc = snprintf(buf, PAGE_SIZE, "Reset in progress.\n"); |
---|
| 528 | + switch (aq->sm_state) { |
---|
| 529 | + case AP_SM_STATE_RESET_START: |
---|
| 530 | + case AP_SM_STATE_RESET_WAIT: |
---|
| 531 | + rc = scnprintf(buf, PAGE_SIZE, "Reset in progress.\n"); |
---|
535 | 532 | break; |
---|
536 | | - case AP_STATE_WORKING: |
---|
537 | | - case AP_STATE_QUEUE_FULL: |
---|
538 | | - rc = snprintf(buf, PAGE_SIZE, "Reset Timer armed.\n"); |
---|
| 533 | + case AP_SM_STATE_WORKING: |
---|
| 534 | + case AP_SM_STATE_QUEUE_FULL: |
---|
| 535 | + rc = scnprintf(buf, PAGE_SIZE, "Reset Timer armed.\n"); |
---|
539 | 536 | break; |
---|
540 | 537 | default: |
---|
541 | | - rc = snprintf(buf, PAGE_SIZE, "No Reset Timer set.\n"); |
---|
| 538 | + rc = scnprintf(buf, PAGE_SIZE, "No Reset Timer set.\n"); |
---|
542 | 539 | } |
---|
543 | 540 | spin_unlock_bh(&aq->lock); |
---|
544 | 541 | return rc; |
---|
.. | .. |
---|
552 | 549 | |
---|
553 | 550 | spin_lock_bh(&aq->lock); |
---|
554 | 551 | __ap_flush_queue(aq); |
---|
555 | | - aq->state = AP_STATE_RESET_START; |
---|
556 | | - ap_wait(ap_sm_event(aq, AP_EVENT_POLL)); |
---|
| 552 | + aq->sm_state = AP_SM_STATE_RESET_START; |
---|
| 553 | + ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL)); |
---|
557 | 554 | spin_unlock_bh(&aq->lock); |
---|
558 | 555 | |
---|
559 | 556 | AP_DBF(DBF_INFO, "reset queue=%02x.%04x triggered by user\n", |
---|
.. | .. |
---|
571 | 568 | int rc = 0; |
---|
572 | 569 | |
---|
573 | 570 | spin_lock_bh(&aq->lock); |
---|
574 | | - if (aq->state == AP_STATE_SETIRQ_WAIT) |
---|
575 | | - rc = snprintf(buf, PAGE_SIZE, "Enable Interrupt pending.\n"); |
---|
576 | | - else if (aq->interrupt == AP_INTR_ENABLED) |
---|
577 | | - rc = snprintf(buf, PAGE_SIZE, "Interrupts enabled.\n"); |
---|
| 571 | + if (aq->sm_state == AP_SM_STATE_SETIRQ_WAIT) |
---|
| 572 | + rc = scnprintf(buf, PAGE_SIZE, "Enable Interrupt pending.\n"); |
---|
| 573 | + else if (aq->interrupt) |
---|
| 574 | + rc = scnprintf(buf, PAGE_SIZE, "Interrupts enabled.\n"); |
---|
578 | 575 | else |
---|
579 | | - rc = snprintf(buf, PAGE_SIZE, "Interrupts disabled.\n"); |
---|
| 576 | + rc = scnprintf(buf, PAGE_SIZE, "Interrupts disabled.\n"); |
---|
580 | 577 | spin_unlock_bh(&aq->lock); |
---|
581 | 578 | return rc; |
---|
582 | 579 | } |
---|
583 | 580 | |
---|
584 | 581 | static DEVICE_ATTR_RO(interrupt); |
---|
| 582 | + |
---|
| 583 | +static ssize_t config_show(struct device *dev, |
---|
| 584 | + struct device_attribute *attr, char *buf) |
---|
| 585 | +{ |
---|
| 586 | + struct ap_queue *aq = to_ap_queue(dev); |
---|
| 587 | + int rc; |
---|
| 588 | + |
---|
| 589 | + spin_lock_bh(&aq->lock); |
---|
| 590 | + rc = scnprintf(buf, PAGE_SIZE, "%d\n", aq->config ? 1 : 0); |
---|
| 591 | + spin_unlock_bh(&aq->lock); |
---|
| 592 | + return rc; |
---|
| 593 | +} |
---|
| 594 | + |
---|
| 595 | +static DEVICE_ATTR_RO(config); |
---|
| 596 | + |
---|
| 597 | +#ifdef CONFIG_ZCRYPT_DEBUG |
---|
| 598 | +static ssize_t states_show(struct device *dev, |
---|
| 599 | + struct device_attribute *attr, char *buf) |
---|
| 600 | +{ |
---|
| 601 | + struct ap_queue *aq = to_ap_queue(dev); |
---|
| 602 | + int rc = 0; |
---|
| 603 | + |
---|
| 604 | + spin_lock_bh(&aq->lock); |
---|
| 605 | + /* queue device state */ |
---|
| 606 | + switch (aq->dev_state) { |
---|
| 607 | + case AP_DEV_STATE_UNINITIATED: |
---|
| 608 | + rc = scnprintf(buf, PAGE_SIZE, "UNINITIATED\n"); |
---|
| 609 | + break; |
---|
| 610 | + case AP_DEV_STATE_OPERATING: |
---|
| 611 | + rc = scnprintf(buf, PAGE_SIZE, "OPERATING"); |
---|
| 612 | + break; |
---|
| 613 | + case AP_DEV_STATE_SHUTDOWN: |
---|
| 614 | + rc = scnprintf(buf, PAGE_SIZE, "SHUTDOWN"); |
---|
| 615 | + break; |
---|
| 616 | + case AP_DEV_STATE_ERROR: |
---|
| 617 | + rc = scnprintf(buf, PAGE_SIZE, "ERROR"); |
---|
| 618 | + break; |
---|
| 619 | + default: |
---|
| 620 | + rc = scnprintf(buf, PAGE_SIZE, "UNKNOWN"); |
---|
| 621 | + } |
---|
| 622 | + /* state machine state */ |
---|
| 623 | + if (aq->dev_state) { |
---|
| 624 | + switch (aq->sm_state) { |
---|
| 625 | + case AP_SM_STATE_RESET_START: |
---|
| 626 | + rc += scnprintf(buf + rc, PAGE_SIZE - rc, |
---|
| 627 | + " [RESET_START]\n"); |
---|
| 628 | + break; |
---|
| 629 | + case AP_SM_STATE_RESET_WAIT: |
---|
| 630 | + rc += scnprintf(buf + rc, PAGE_SIZE - rc, |
---|
| 631 | + " [RESET_WAIT]\n"); |
---|
| 632 | + break; |
---|
| 633 | + case AP_SM_STATE_SETIRQ_WAIT: |
---|
| 634 | + rc += scnprintf(buf + rc, PAGE_SIZE - rc, |
---|
| 635 | + " [SETIRQ_WAIT]\n"); |
---|
| 636 | + break; |
---|
| 637 | + case AP_SM_STATE_IDLE: |
---|
| 638 | + rc += scnprintf(buf + rc, PAGE_SIZE - rc, |
---|
| 639 | + " [IDLE]\n"); |
---|
| 640 | + break; |
---|
| 641 | + case AP_SM_STATE_WORKING: |
---|
| 642 | + rc += scnprintf(buf + rc, PAGE_SIZE - rc, |
---|
| 643 | + " [WORKING]\n"); |
---|
| 644 | + break; |
---|
| 645 | + case AP_SM_STATE_QUEUE_FULL: |
---|
| 646 | + rc += scnprintf(buf + rc, PAGE_SIZE - rc, |
---|
| 647 | + " [FULL]\n"); |
---|
| 648 | + break; |
---|
| 649 | + default: |
---|
| 650 | + rc += scnprintf(buf + rc, PAGE_SIZE - rc, |
---|
| 651 | + " [UNKNOWN]\n"); |
---|
| 652 | + } |
---|
| 653 | + } |
---|
| 654 | + spin_unlock_bh(&aq->lock); |
---|
| 655 | + |
---|
| 656 | + return rc; |
---|
| 657 | +} |
---|
| 658 | +static DEVICE_ATTR_RO(states); |
---|
| 659 | + |
---|
| 660 | +static ssize_t last_err_rc_show(struct device *dev, |
---|
| 661 | + struct device_attribute *attr, char *buf) |
---|
| 662 | +{ |
---|
| 663 | + struct ap_queue *aq = to_ap_queue(dev); |
---|
| 664 | + int rc; |
---|
| 665 | + |
---|
| 666 | + spin_lock_bh(&aq->lock); |
---|
| 667 | + rc = aq->last_err_rc; |
---|
| 668 | + spin_unlock_bh(&aq->lock); |
---|
| 669 | + |
---|
| 670 | + switch (rc) { |
---|
| 671 | + case AP_RESPONSE_NORMAL: |
---|
| 672 | + return scnprintf(buf, PAGE_SIZE, "NORMAL\n"); |
---|
| 673 | + case AP_RESPONSE_Q_NOT_AVAIL: |
---|
| 674 | + return scnprintf(buf, PAGE_SIZE, "Q_NOT_AVAIL\n"); |
---|
| 675 | + case AP_RESPONSE_RESET_IN_PROGRESS: |
---|
| 676 | + return scnprintf(buf, PAGE_SIZE, "RESET_IN_PROGRESS\n"); |
---|
| 677 | + case AP_RESPONSE_DECONFIGURED: |
---|
| 678 | + return scnprintf(buf, PAGE_SIZE, "DECONFIGURED\n"); |
---|
| 679 | + case AP_RESPONSE_CHECKSTOPPED: |
---|
| 680 | + return scnprintf(buf, PAGE_SIZE, "CHECKSTOPPED\n"); |
---|
| 681 | + case AP_RESPONSE_BUSY: |
---|
| 682 | + return scnprintf(buf, PAGE_SIZE, "BUSY\n"); |
---|
| 683 | + case AP_RESPONSE_INVALID_ADDRESS: |
---|
| 684 | + return scnprintf(buf, PAGE_SIZE, "INVALID_ADDRESS\n"); |
---|
| 685 | + case AP_RESPONSE_OTHERWISE_CHANGED: |
---|
| 686 | + return scnprintf(buf, PAGE_SIZE, "OTHERWISE_CHANGED\n"); |
---|
| 687 | + case AP_RESPONSE_Q_FULL: |
---|
| 688 | + return scnprintf(buf, PAGE_SIZE, "Q_FULL/NO_PENDING_REPLY\n"); |
---|
| 689 | + case AP_RESPONSE_INDEX_TOO_BIG: |
---|
| 690 | + return scnprintf(buf, PAGE_SIZE, "INDEX_TOO_BIG\n"); |
---|
| 691 | + case AP_RESPONSE_NO_FIRST_PART: |
---|
| 692 | + return scnprintf(buf, PAGE_SIZE, "NO_FIRST_PART\n"); |
---|
| 693 | + case AP_RESPONSE_MESSAGE_TOO_BIG: |
---|
| 694 | + return scnprintf(buf, PAGE_SIZE, "MESSAGE_TOO_BIG\n"); |
---|
| 695 | + case AP_RESPONSE_REQ_FAC_NOT_INST: |
---|
| 696 | + return scnprintf(buf, PAGE_SIZE, "REQ_FAC_NOT_INST\n"); |
---|
| 697 | + default: |
---|
| 698 | + return scnprintf(buf, PAGE_SIZE, "response code %d\n", rc); |
---|
| 699 | + } |
---|
| 700 | +} |
---|
| 701 | +static DEVICE_ATTR_RO(last_err_rc); |
---|
| 702 | +#endif |
---|
585 | 703 | |
---|
586 | 704 | static struct attribute *ap_queue_dev_attrs[] = { |
---|
587 | 705 | &dev_attr_request_count.attr, |
---|
.. | .. |
---|
589 | 707 | &dev_attr_pendingq_count.attr, |
---|
590 | 708 | &dev_attr_reset.attr, |
---|
591 | 709 | &dev_attr_interrupt.attr, |
---|
| 710 | + &dev_attr_config.attr, |
---|
| 711 | +#ifdef CONFIG_ZCRYPT_DEBUG |
---|
| 712 | + &dev_attr_states.attr, |
---|
| 713 | + &dev_attr_last_err_rc.attr, |
---|
| 714 | +#endif |
---|
592 | 715 | NULL |
---|
593 | 716 | }; |
---|
594 | 717 | |
---|
.. | .. |
---|
610 | 733 | { |
---|
611 | 734 | struct ap_queue *aq = to_ap_queue(dev); |
---|
612 | 735 | |
---|
613 | | - if (!list_empty(&aq->list)) { |
---|
614 | | - spin_lock_bh(&ap_list_lock); |
---|
615 | | - list_del_init(&aq->list); |
---|
616 | | - spin_unlock_bh(&ap_list_lock); |
---|
617 | | - } |
---|
| 736 | + spin_lock_bh(&ap_queues_lock); |
---|
| 737 | + hash_del(&aq->hnode); |
---|
| 738 | + spin_unlock_bh(&ap_queues_lock); |
---|
| 739 | + |
---|
618 | 740 | kfree(aq); |
---|
619 | 741 | } |
---|
620 | 742 | |
---|
.. | .. |
---|
629 | 751 | aq->ap_dev.device.type = &ap_queue_type; |
---|
630 | 752 | aq->ap_dev.device_type = device_type; |
---|
631 | 753 | aq->qid = qid; |
---|
632 | | - aq->state = AP_STATE_RESET_START; |
---|
633 | | - aq->interrupt = AP_INTR_DISABLED; |
---|
| 754 | + aq->interrupt = false; |
---|
634 | 755 | spin_lock_init(&aq->lock); |
---|
635 | | - INIT_LIST_HEAD(&aq->list); |
---|
636 | 756 | INIT_LIST_HEAD(&aq->pendingq); |
---|
637 | 757 | INIT_LIST_HEAD(&aq->requestq); |
---|
638 | 758 | timer_setup(&aq->timeout, ap_request_timeout, 0); |
---|
.. | .. |
---|
645 | 765 | aq->reply = reply; |
---|
646 | 766 | |
---|
647 | 767 | spin_lock_bh(&aq->lock); |
---|
648 | | - ap_wait(ap_sm_event(aq, AP_EVENT_POLL)); |
---|
| 768 | + ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL)); |
---|
649 | 769 | spin_unlock_bh(&aq->lock); |
---|
650 | 770 | } |
---|
651 | 771 | EXPORT_SYMBOL(ap_queue_init_reply); |
---|
.. | .. |
---|
655 | 775 | * @aq: The AP device to queue the message to |
---|
656 | 776 | * @ap_msg: The message that is to be added |
---|
657 | 777 | */ |
---|
658 | | -void ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg) |
---|
| 778 | +int ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg) |
---|
659 | 779 | { |
---|
660 | | - /* For asynchronous message handling a valid receive-callback |
---|
661 | | - * is required. |
---|
662 | | - */ |
---|
| 780 | + int rc = 0; |
---|
| 781 | + |
---|
| 782 | + /* msg needs to have a valid receive-callback */ |
---|
663 | 783 | BUG_ON(!ap_msg->receive); |
---|
664 | 784 | |
---|
665 | 785 | spin_lock_bh(&aq->lock); |
---|
666 | | - /* Queue the message. */ |
---|
667 | | - list_add_tail(&ap_msg->list, &aq->requestq); |
---|
668 | | - aq->requestq_count++; |
---|
669 | | - aq->total_request_count++; |
---|
670 | | - atomic64_inc(&aq->card->total_request_count); |
---|
| 786 | + |
---|
| 787 | + /* only allow to queue new messages if device state is ok */ |
---|
| 788 | + if (aq->dev_state == AP_DEV_STATE_OPERATING) { |
---|
| 789 | + list_add_tail(&ap_msg->list, &aq->requestq); |
---|
| 790 | + aq->requestq_count++; |
---|
| 791 | + aq->total_request_count++; |
---|
| 792 | + atomic64_inc(&aq->card->total_request_count); |
---|
| 793 | + } else |
---|
| 794 | + rc = -ENODEV; |
---|
| 795 | + |
---|
671 | 796 | /* Send/receive as many request from the queue as possible. */ |
---|
672 | | - ap_wait(ap_sm_event_loop(aq, AP_EVENT_POLL)); |
---|
| 797 | + ap_wait(ap_sm_event_loop(aq, AP_SM_EVENT_POLL)); |
---|
| 798 | + |
---|
673 | 799 | spin_unlock_bh(&aq->lock); |
---|
| 800 | + |
---|
| 801 | + return rc; |
---|
674 | 802 | } |
---|
675 | 803 | EXPORT_SYMBOL(ap_queue_message); |
---|
676 | 804 | |
---|
.. | .. |
---|
725 | 853 | ap_msg->rc = -EAGAIN; |
---|
726 | 854 | ap_msg->receive(aq, ap_msg, NULL); |
---|
727 | 855 | } |
---|
| 856 | + aq->queue_count = 0; |
---|
728 | 857 | } |
---|
729 | 858 | |
---|
730 | 859 | void ap_flush_queue(struct ap_queue *aq) |
---|
.. | .. |
---|
735 | 864 | } |
---|
736 | 865 | EXPORT_SYMBOL(ap_flush_queue); |
---|
737 | 866 | |
---|
| 867 | +void ap_queue_prepare_remove(struct ap_queue *aq) |
---|
| 868 | +{ |
---|
| 869 | + spin_lock_bh(&aq->lock); |
---|
| 870 | + /* flush queue */ |
---|
| 871 | + __ap_flush_queue(aq); |
---|
| 872 | + /* move queue device state to SHUTDOWN in progress */ |
---|
| 873 | + aq->dev_state = AP_DEV_STATE_SHUTDOWN; |
---|
| 874 | + spin_unlock_bh(&aq->lock); |
---|
| 875 | + del_timer_sync(&aq->timeout); |
---|
| 876 | +} |
---|
| 877 | + |
---|
738 | 878 | void ap_queue_remove(struct ap_queue *aq) |
---|
739 | 879 | { |
---|
740 | | - ap_flush_queue(aq); |
---|
741 | | - del_timer_sync(&aq->timeout); |
---|
742 | | - |
---|
743 | | - /* reset with zero, also clears irq registration */ |
---|
| 880 | + /* |
---|
| 881 | + * all messages have been flushed and the device state |
---|
| 882 | + * is SHUTDOWN. Now reset with zero which also clears |
---|
| 883 | + * the irq registration and move the device state |
---|
| 884 | + * to the initial value AP_DEV_STATE_UNINITIATED. |
---|
| 885 | + */ |
---|
744 | 886 | spin_lock_bh(&aq->lock); |
---|
745 | 887 | ap_zapq(aq->qid); |
---|
746 | | - aq->state = AP_STATE_BORKED; |
---|
| 888 | + aq->dev_state = AP_DEV_STATE_UNINITIATED; |
---|
747 | 889 | spin_unlock_bh(&aq->lock); |
---|
748 | 890 | } |
---|
749 | | -EXPORT_SYMBOL(ap_queue_remove); |
---|
750 | 891 | |
---|
751 | | -void ap_queue_reinit_state(struct ap_queue *aq) |
---|
| 892 | +void ap_queue_init_state(struct ap_queue *aq) |
---|
752 | 893 | { |
---|
753 | 894 | spin_lock_bh(&aq->lock); |
---|
754 | | - aq->state = AP_STATE_RESET_START; |
---|
755 | | - ap_wait(ap_sm_event(aq, AP_EVENT_POLL)); |
---|
| 895 | + aq->dev_state = AP_DEV_STATE_OPERATING; |
---|
| 896 | + aq->sm_state = AP_SM_STATE_RESET_START; |
---|
| 897 | + ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL)); |
---|
756 | 898 | spin_unlock_bh(&aq->lock); |
---|
757 | 899 | } |
---|
758 | | -EXPORT_SYMBOL(ap_queue_reinit_state); |
---|
| 900 | +EXPORT_SYMBOL(ap_queue_init_state); |
---|