blob: 1294876bf7b406da1a739d308032b0efa4e0382c [file] [log] [blame]
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001/*
2 * linux/drivers/s390/crypto/ap_bus.c
3 *
4 * Copyright (C) 2006 IBM Corporation
5 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
6 * Martin Schwidefsky <schwidefsky@de.ibm.com>
7 * Ralph Wuerthner <rwuerthn@de.ibm.com>
Felix Beckcb17a632008-12-25 13:38:41 +01008 * Felix Beck <felix.beck@de.ibm.com>
Martin Schwidefsky1534c382006-09-20 15:58:25 +02009 *
10 * Adjunct processor bus.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
Martin Schwidefsky136f7a12008-12-25 13:39:46 +010027#define KMSG_COMPONENT "ap"
28#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
29
Martin Schwidefsky1534c382006-09-20 15:58:25 +020030#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/delay.h>
33#include <linux/err.h>
34#include <linux/interrupt.h>
35#include <linux/workqueue.h>
36#include <linux/notifier.h>
37#include <linux/kthread.h>
38#include <linux/mutex.h>
Ralph Wuerthner85eca852006-12-08 15:54:07 +010039#include <asm/reset.h>
Felix Beckcb17a632008-12-25 13:38:41 +010040#include <asm/airq.h>
41#include <asm/atomic.h>
42#include <asm/system.h>
43#include <asm/isc.h>
Felix Beckfe137232008-07-14 09:59:08 +020044#include <linux/hrtimer.h>
45#include <linux/ktime.h>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020046
47#include "ap_bus.h"
48
49/* Some prototypes. */
Al Viro4927b3f2006-12-06 19:18:20 +000050static void ap_scan_bus(struct work_struct *);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020051static void ap_poll_all(unsigned long);
Felix Beckfe137232008-07-14 09:59:08 +020052static enum hrtimer_restart ap_poll_timeout(struct hrtimer *);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020053static int ap_poll_thread_start(void);
54static void ap_poll_thread_stop(void);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +020055static void ap_request_timeout(unsigned long);
Felix Beckcb17a632008-12-25 13:38:41 +010056static inline void ap_schedule_poll_timer(void);
Felix Beck772f5472009-06-22 12:08:16 +020057static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags);
58static int ap_device_remove(struct device *dev);
59static int ap_device_probe(struct device *dev);
60static void ap_interrupt_handler(void *unused1, void *unused2);
61static void ap_reset(struct ap_device *ap_dev);
62static void ap_config_timeout(unsigned long ptr);
Felix Beck5314af62009-09-22 22:58:51 +020063static int ap_select_domain(void);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020064
Felix Beck1749a812008-04-17 07:46:28 +020065/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020066 * Module description.
67 */
68MODULE_AUTHOR("IBM Corporation");
69MODULE_DESCRIPTION("Adjunct Processor Bus driver, "
70 "Copyright 2006 IBM Corporation");
71MODULE_LICENSE("GPL");
72
Felix Beck1749a812008-04-17 07:46:28 +020073/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020074 * Module parameter
75 */
76int ap_domain_index = -1; /* Adjunct Processor Domain Index */
77module_param_named(domain, ap_domain_index, int, 0000);
78MODULE_PARM_DESC(domain, "domain index for ap devices");
79EXPORT_SYMBOL(ap_domain_index);
80
Felix Beckb90b34c2008-02-09 18:24:30 +010081static int ap_thread_flag = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +020082module_param_named(poll_thread, ap_thread_flag, int, 0000);
Felix Beckb90b34c2008-02-09 18:24:30 +010083MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off).");
Martin Schwidefsky1534c382006-09-20 15:58:25 +020084
85static struct device *ap_root_device = NULL;
Christian Maaser43c207e62008-12-25 13:38:42 +010086static DEFINE_SPINLOCK(ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +010087static LIST_HEAD(ap_device_list);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020088
Felix Beck1749a812008-04-17 07:46:28 +020089/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020090 * Workqueue & timer for bus rescan.
91 */
92static struct workqueue_struct *ap_work_queue;
93static struct timer_list ap_config_timer;
94static int ap_config_time = AP_CONFIG_TIME;
Al Viro4927b3f2006-12-06 19:18:20 +000095static DECLARE_WORK(ap_config_work, ap_scan_bus);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020096
Felix Beck1749a812008-04-17 07:46:28 +020097/*
Felix Beckcb17a632008-12-25 13:38:41 +010098 * Tasklet & timer for AP request polling and interrupts
Martin Schwidefsky1534c382006-09-20 15:58:25 +020099 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200100static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0);
101static atomic_t ap_poll_requests = ATOMIC_INIT(0);
102static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
103static struct task_struct *ap_poll_kthread = NULL;
104static DEFINE_MUTEX(ap_poll_thread_mutex);
Felix Beckcb17a632008-12-25 13:38:41 +0100105static void *ap_interrupt_indicator;
Felix Beckfe137232008-07-14 09:59:08 +0200106static struct hrtimer ap_poll_timer;
107/* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
108 * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
109static unsigned long long poll_timeout = 250000;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200110
Felix Beck772f5472009-06-22 12:08:16 +0200111/* Suspend flag */
112static int ap_suspend_flag;
Felix Beck5314af62009-09-22 22:58:51 +0200113/* Flag to check if domain was set through module parameter domain=. This is
114 * important when supsend and resume is done in a z/VM environment where the
115 * domain might change. */
116static int user_set_domain = 0;
Felix Beck772f5472009-06-22 12:08:16 +0200117static struct bus_type ap_bus_type;
118
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200119/**
Felix Beckcb17a632008-12-25 13:38:41 +0100120 * ap_using_interrupts() - Returns non-zero if interrupt support is
121 * available.
122 */
123static inline int ap_using_interrupts(void)
124{
125 return ap_interrupt_indicator != NULL;
126}
127
128/**
Felix Beck1749a812008-04-17 07:46:28 +0200129 * ap_intructions_available() - Test if AP instructions are available.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200130 *
Felix Beck1749a812008-04-17 07:46:28 +0200131 * Returns 0 if the AP instructions are installed.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200132 */
133static inline int ap_instructions_available(void)
134{
135 register unsigned long reg0 asm ("0") = AP_MKQID(0,0);
136 register unsigned long reg1 asm ("1") = -ENODEV;
137 register unsigned long reg2 asm ("2") = 0UL;
138
139 asm volatile(
140 " .long 0xb2af0000\n" /* PQAP(TAPQ) */
141 "0: la %1,0\n"
142 "1:\n"
143 EX_TABLE(0b, 1b)
144 : "+d" (reg0), "+d" (reg1), "+d" (reg2) : : "cc" );
145 return reg1;
146}
147
148/**
Felix Beckcb17a632008-12-25 13:38:41 +0100149 * ap_interrupts_available(): Test if AP interrupts are available.
150 *
151 * Returns 1 if AP interrupts are available.
152 */
153static int ap_interrupts_available(void)
154{
155 unsigned long long facility_bits[2];
156
157 if (stfle(facility_bits, 2) <= 1)
158 return 0;
159 if (!(facility_bits[0] & (1ULL << 61)) ||
160 !(facility_bits[1] & (1ULL << 62)))
161 return 0;
162 return 1;
163}
164
165/**
Felix Beck1749a812008-04-17 07:46:28 +0200166 * ap_test_queue(): Test adjunct processor queue.
167 * @qid: The AP queue number
168 * @queue_depth: Pointer to queue depth value
169 * @device_type: Pointer to device type value
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200170 *
Felix Beck1749a812008-04-17 07:46:28 +0200171 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200172 */
173static inline struct ap_queue_status
174ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
175{
176 register unsigned long reg0 asm ("0") = qid;
177 register struct ap_queue_status reg1 asm ("1");
178 register unsigned long reg2 asm ("2") = 0UL;
179
180 asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
181 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
182 *device_type = (int) (reg2 >> 24);
183 *queue_depth = (int) (reg2 & 0xff);
184 return reg1;
185}
186
187/**
Felix Beck1749a812008-04-17 07:46:28 +0200188 * ap_reset_queue(): Reset adjunct processor queue.
189 * @qid: The AP queue number
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200190 *
Felix Beck1749a812008-04-17 07:46:28 +0200191 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200192 */
193static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
194{
195 register unsigned long reg0 asm ("0") = qid | 0x01000000UL;
196 register struct ap_queue_status reg1 asm ("1");
197 register unsigned long reg2 asm ("2") = 0UL;
198
199 asm volatile(
200 ".long 0xb2af0000" /* PQAP(RAPQ) */
201 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
202 return reg1;
203}
204
Felix Beckcb17a632008-12-25 13:38:41 +0100205#ifdef CONFIG_64BIT
206/**
207 * ap_queue_interruption_control(): Enable interruption for a specific AP.
208 * @qid: The AP queue number
209 * @ind: The notification indicator byte
210 *
211 * Returns AP queue status.
212 */
213static inline struct ap_queue_status
214ap_queue_interruption_control(ap_qid_t qid, void *ind)
215{
216 register unsigned long reg0 asm ("0") = qid | 0x03000000UL;
217 register unsigned long reg1_in asm ("1") = 0x0000800000000000UL | AP_ISC;
218 register struct ap_queue_status reg1_out asm ("1");
219 register void *reg2 asm ("2") = ind;
220 asm volatile(
221 ".long 0xb2af0000" /* PQAP(RAPQ) */
222 : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
223 :
224 : "cc" );
225 return reg1_out;
226}
227#endif
228
229/**
230 * ap_queue_enable_interruption(): Enable interruption on an AP.
231 * @qid: The AP queue number
232 * @ind: the notification indicator byte
233 *
234 * Enables interruption on AP queue via ap_queue_interruption_control(). Based
235 * on the return value it waits a while and tests the AP queue if interrupts
236 * have been switched on using ap_test_queue().
237 */
238static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
239{
240#ifdef CONFIG_64BIT
241 struct ap_queue_status status;
242 int t_depth, t_device_type, rc, i;
243
244 rc = -EBUSY;
245 status = ap_queue_interruption_control(qid, ind);
246
247 for (i = 0; i < AP_MAX_RESET; i++) {
248 switch (status.response_code) {
249 case AP_RESPONSE_NORMAL:
250 if (status.int_enabled)
251 return 0;
252 break;
253 case AP_RESPONSE_RESET_IN_PROGRESS:
254 case AP_RESPONSE_BUSY:
255 break;
256 case AP_RESPONSE_Q_NOT_AVAIL:
257 case AP_RESPONSE_DECONFIGURED:
258 case AP_RESPONSE_CHECKSTOPPED:
259 case AP_RESPONSE_INVALID_ADDRESS:
260 return -ENODEV;
261 case AP_RESPONSE_OTHERWISE_CHANGED:
262 if (status.int_enabled)
263 return 0;
264 break;
265 default:
266 break;
267 }
268 if (i < AP_MAX_RESET - 1) {
269 udelay(5);
270 status = ap_test_queue(qid, &t_depth, &t_device_type);
271 }
272 }
273 return rc;
274#else
275 return -EINVAL;
276#endif
277}
278
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200279/**
Felix Beck1749a812008-04-17 07:46:28 +0200280 * __ap_send(): Send message to adjunct processor queue.
281 * @qid: The AP queue number
282 * @psmid: The program supplied message identifier
283 * @msg: The message text
284 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200285 *
Felix Beck1749a812008-04-17 07:46:28 +0200286 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200287 * Condition code 1 on NQAP can't happen because the L bit is 1.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200288 * Condition code 2 on NQAP also means the send is incomplete,
289 * because a segment boundary was reached. The NQAP is repeated.
290 */
291static inline struct ap_queue_status
292__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
293{
294 typedef struct { char _[length]; } msgblock;
295 register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
296 register struct ap_queue_status reg1 asm ("1");
297 register unsigned long reg2 asm ("2") = (unsigned long) msg;
298 register unsigned long reg3 asm ("3") = (unsigned long) length;
299 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
300 register unsigned long reg5 asm ("5") = (unsigned int) psmid;
301
302 asm volatile (
303 "0: .long 0xb2ad0042\n" /* DQAP */
304 " brc 2,0b"
305 : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
306 : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg)
307 : "cc" );
308 return reg1;
309}
310
311int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
312{
313 struct ap_queue_status status;
314
315 status = __ap_send(qid, psmid, msg, length);
316 switch (status.response_code) {
317 case AP_RESPONSE_NORMAL:
318 return 0;
319 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200320 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200321 return -EBUSY;
322 default: /* Device is gone. */
323 return -ENODEV;
324 }
325}
326EXPORT_SYMBOL(ap_send);
327
Felix Beck1749a812008-04-17 07:46:28 +0200328/**
329 * __ap_recv(): Receive message from adjunct processor queue.
330 * @qid: The AP queue number
331 * @psmid: Pointer to program supplied message identifier
332 * @msg: The message text
333 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200334 *
Felix Beck1749a812008-04-17 07:46:28 +0200335 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200336 * Condition code 1 on DQAP means the receive has taken place
337 * but only partially. The response is incomplete, hence the
338 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200339 * Condition code 2 on DQAP also means the receive is incomplete,
340 * this time because a segment boundary was reached. Again, the
341 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200342 * Note that gpr2 is used by the DQAP instruction to keep track of
343 * any 'residual' length, in case the instruction gets interrupted.
344 * Hence it gets zeroed before the instruction.
345 */
346static inline struct ap_queue_status
347__ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
348{
349 typedef struct { char _[length]; } msgblock;
350 register unsigned long reg0 asm("0") = qid | 0x80000000UL;
351 register struct ap_queue_status reg1 asm ("1");
352 register unsigned long reg2 asm("2") = 0UL;
353 register unsigned long reg4 asm("4") = (unsigned long) msg;
354 register unsigned long reg5 asm("5") = (unsigned long) length;
355 register unsigned long reg6 asm("6") = 0UL;
356 register unsigned long reg7 asm("7") = 0UL;
357
358
359 asm volatile(
360 "0: .long 0xb2ae0064\n"
361 " brc 6,0b\n"
362 : "+d" (reg0), "=d" (reg1), "+d" (reg2),
363 "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
364 "=m" (*(msgblock *) msg) : : "cc" );
365 *psmid = (((unsigned long long) reg6) << 32) + reg7;
366 return reg1;
367}
368
369int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
370{
371 struct ap_queue_status status;
372
373 status = __ap_recv(qid, psmid, msg, length);
374 switch (status.response_code) {
375 case AP_RESPONSE_NORMAL:
376 return 0;
377 case AP_RESPONSE_NO_PENDING_REPLY:
378 if (status.queue_empty)
379 return -ENOENT;
380 return -EBUSY;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200381 case AP_RESPONSE_RESET_IN_PROGRESS:
382 return -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200383 default:
384 return -ENODEV;
385 }
386}
387EXPORT_SYMBOL(ap_recv);
388
389/**
Felix Beck1749a812008-04-17 07:46:28 +0200390 * ap_query_queue(): Check if an AP queue is available.
391 * @qid: The AP queue number
392 * @queue_depth: Pointer to queue depth value
393 * @device_type: Pointer to device type value
394 *
395 * The test is repeated for AP_MAX_RESET times.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200396 */
397static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
398{
399 struct ap_queue_status status;
400 int t_depth, t_device_type, rc, i;
401
402 rc = -EBUSY;
403 for (i = 0; i < AP_MAX_RESET; i++) {
404 status = ap_test_queue(qid, &t_depth, &t_device_type);
405 switch (status.response_code) {
406 case AP_RESPONSE_NORMAL:
407 *queue_depth = t_depth + 1;
408 *device_type = t_device_type;
409 rc = 0;
410 break;
411 case AP_RESPONSE_Q_NOT_AVAIL:
412 rc = -ENODEV;
413 break;
414 case AP_RESPONSE_RESET_IN_PROGRESS:
415 break;
416 case AP_RESPONSE_DECONFIGURED:
417 rc = -ENODEV;
418 break;
419 case AP_RESPONSE_CHECKSTOPPED:
420 rc = -ENODEV;
421 break;
Felix Beckcb17a632008-12-25 13:38:41 +0100422 case AP_RESPONSE_INVALID_ADDRESS:
423 rc = -ENODEV;
424 break;
425 case AP_RESPONSE_OTHERWISE_CHANGED:
426 break;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200427 case AP_RESPONSE_BUSY:
428 break;
429 default:
430 BUG();
431 }
432 if (rc != -EBUSY)
433 break;
434 if (i < AP_MAX_RESET - 1)
435 udelay(5);
436 }
437 return rc;
438}
439
440/**
Felix Beck1749a812008-04-17 07:46:28 +0200441 * ap_init_queue(): Reset an AP queue.
442 * @qid: The AP queue number
443 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200444 * Reset an AP queue and wait for it to become available again.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200445 */
446static int ap_init_queue(ap_qid_t qid)
447{
448 struct ap_queue_status status;
449 int rc, dummy, i;
450
451 rc = -ENODEV;
452 status = ap_reset_queue(qid);
453 for (i = 0; i < AP_MAX_RESET; i++) {
454 switch (status.response_code) {
455 case AP_RESPONSE_NORMAL:
456 if (status.queue_empty)
457 rc = 0;
458 break;
459 case AP_RESPONSE_Q_NOT_AVAIL:
460 case AP_RESPONSE_DECONFIGURED:
461 case AP_RESPONSE_CHECKSTOPPED:
462 i = AP_MAX_RESET; /* return with -ENODEV */
463 break;
464 case AP_RESPONSE_RESET_IN_PROGRESS:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200465 rc = -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200466 case AP_RESPONSE_BUSY:
467 default:
468 break;
469 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200470 if (rc != -ENODEV && rc != -EBUSY)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200471 break;
472 if (i < AP_MAX_RESET - 1) {
473 udelay(5);
474 status = ap_test_queue(qid, &dummy, &dummy);
475 }
476 }
Felix Beckcb17a632008-12-25 13:38:41 +0100477 if (rc == 0 && ap_using_interrupts()) {
478 rc = ap_queue_enable_interruption(qid, ap_interrupt_indicator);
479 /* If interruption mode is supported by the machine,
480 * but an AP can not be enabled for interruption then
481 * the AP will be discarded. */
482 if (rc)
483 pr_err("Registering adapter interrupts for "
484 "AP %d failed\n", AP_QID_DEVICE(qid));
485 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200486 return rc;
487}
488
489/**
Felix Beck1749a812008-04-17 07:46:28 +0200490 * ap_increase_queue_count(): Arm request timeout.
491 * @ap_dev: Pointer to an AP device.
492 *
493 * Arm request timeout if an AP device was idle and a new request is submitted.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200494 */
495static void ap_increase_queue_count(struct ap_device *ap_dev)
496{
497 int timeout = ap_dev->drv->request_timeout;
498
499 ap_dev->queue_count++;
500 if (ap_dev->queue_count == 1) {
501 mod_timer(&ap_dev->timeout, jiffies + timeout);
502 ap_dev->reset = AP_RESET_ARMED;
503 }
504}
505
506/**
Felix Beck1749a812008-04-17 07:46:28 +0200507 * ap_decrease_queue_count(): Decrease queue count.
508 * @ap_dev: Pointer to an AP device.
509 *
510 * If AP device is still alive, re-schedule request timeout if there are still
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200511 * pending requests.
512 */
513static void ap_decrease_queue_count(struct ap_device *ap_dev)
514{
515 int timeout = ap_dev->drv->request_timeout;
516
517 ap_dev->queue_count--;
518 if (ap_dev->queue_count > 0)
519 mod_timer(&ap_dev->timeout, jiffies + timeout);
520 else
Felix Beck1749a812008-04-17 07:46:28 +0200521 /*
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200522 * The timeout timer should to be disabled now - since
523 * del_timer_sync() is very expensive, we just tell via the
524 * reset flag to ignore the pending timeout timer.
525 */
526 ap_dev->reset = AP_RESET_IGNORE;
527}
528
Felix Beck1749a812008-04-17 07:46:28 +0200529/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200530 * AP device related attributes.
531 */
532static ssize_t ap_hwtype_show(struct device *dev,
533 struct device_attribute *attr, char *buf)
534{
535 struct ap_device *ap_dev = to_ap_dev(dev);
536 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type);
537}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200538
Christian Maaser43c207e62008-12-25 13:38:42 +0100539static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200540static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr,
541 char *buf)
542{
543 struct ap_device *ap_dev = to_ap_dev(dev);
544 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth);
545}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200546
Christian Maaser43c207e62008-12-25 13:38:42 +0100547static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200548static ssize_t ap_request_count_show(struct device *dev,
549 struct device_attribute *attr,
550 char *buf)
551{
552 struct ap_device *ap_dev = to_ap_dev(dev);
553 int rc;
554
555 spin_lock_bh(&ap_dev->lock);
556 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->total_request_count);
557 spin_unlock_bh(&ap_dev->lock);
558 return rc;
559}
560
561static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL);
562
563static ssize_t ap_modalias_show(struct device *dev,
564 struct device_attribute *attr, char *buf)
565{
566 return sprintf(buf, "ap:t%02X", to_ap_dev(dev)->device_type);
567}
568
569static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL);
570
571static struct attribute *ap_dev_attrs[] = {
572 &dev_attr_hwtype.attr,
573 &dev_attr_depth.attr,
574 &dev_attr_request_count.attr,
575 &dev_attr_modalias.attr,
576 NULL
577};
578static struct attribute_group ap_dev_attr_group = {
579 .attrs = ap_dev_attrs
580};
581
582/**
Felix Beck1749a812008-04-17 07:46:28 +0200583 * ap_bus_match()
584 * @dev: Pointer to device
585 * @drv: Pointer to device_driver
586 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200587 * AP bus driver registration/unregistration.
588 */
589static int ap_bus_match(struct device *dev, struct device_driver *drv)
590{
591 struct ap_device *ap_dev = to_ap_dev(dev);
592 struct ap_driver *ap_drv = to_ap_drv(drv);
593 struct ap_device_id *id;
594
Felix Beck1749a812008-04-17 07:46:28 +0200595 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200596 * Compare device type of the device with the list of
597 * supported types of the device_driver.
598 */
599 for (id = ap_drv->ids; id->match_flags; id++) {
600 if ((id->match_flags & AP_DEVICE_ID_MATCH_DEVICE_TYPE) &&
601 (id->dev_type != ap_dev->device_type))
602 continue;
603 return 1;
604 }
605 return 0;
606}
607
608/**
Felix Beck1749a812008-04-17 07:46:28 +0200609 * ap_uevent(): Uevent function for AP devices.
610 * @dev: Pointer to device
611 * @env: Pointer to kobj_uevent_env
612 *
613 * It sets up a single environment variable DEV_TYPE which contains the
614 * hardware device type.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200615 */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200616static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200617{
618 struct ap_device *ap_dev = to_ap_dev(dev);
Kay Sievers7eff2e72007-08-14 15:15:12 +0200619 int retval = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200620
621 if (!ap_dev)
622 return -ENODEV;
623
624 /* Set up DEV_TYPE environment variable. */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200625 retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700626 if (retval)
627 return retval;
628
Cornelia Huck66a4263b2006-12-04 15:40:10 +0100629 /* Add MODALIAS= */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200630 retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700631
Eric Rannaudbf624562007-03-30 22:23:12 -0700632 return retval;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200633}
634
Felix Beck772f5472009-06-22 12:08:16 +0200635static int ap_bus_suspend(struct device *dev, pm_message_t state)
636{
637 struct ap_device *ap_dev = to_ap_dev(dev);
638 unsigned long flags;
639
640 if (!ap_suspend_flag) {
641 ap_suspend_flag = 1;
642
643 /* Disable scanning for devices, thus we do not want to scan
644 * for them after removing.
645 */
646 del_timer_sync(&ap_config_timer);
647 if (ap_work_queue != NULL) {
648 destroy_workqueue(ap_work_queue);
649 ap_work_queue = NULL;
650 }
Felix Beck5314af62009-09-22 22:58:51 +0200651
Felix Beck772f5472009-06-22 12:08:16 +0200652 tasklet_disable(&ap_tasklet);
653 }
654 /* Poll on the device until all requests are finished. */
655 do {
656 flags = 0;
Felix Beck95f15562009-09-11 10:28:51 +0200657 spin_lock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200658 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +0200659 spin_unlock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200660 } while ((flags & 1) || (flags & 2));
661
Felix Beck5314af62009-09-22 22:58:51 +0200662 spin_lock_bh(&ap_dev->lock);
663 ap_dev->unregistered = 1;
664 spin_unlock_bh(&ap_dev->lock);
665
Felix Beck772f5472009-06-22 12:08:16 +0200666 return 0;
667}
668
669static int ap_bus_resume(struct device *dev)
670{
671 int rc = 0;
672 struct ap_device *ap_dev = to_ap_dev(dev);
673
674 if (ap_suspend_flag) {
675 ap_suspend_flag = 0;
676 if (!ap_interrupts_available())
677 ap_interrupt_indicator = NULL;
Felix Beck5314af62009-09-22 22:58:51 +0200678 if (!user_set_domain) {
679 ap_domain_index = -1;
680 ap_select_domain();
681 }
Felix Beck772f5472009-06-22 12:08:16 +0200682 init_timer(&ap_config_timer);
683 ap_config_timer.function = ap_config_timeout;
684 ap_config_timer.data = 0;
685 ap_config_timer.expires = jiffies + ap_config_time * HZ;
686 add_timer(&ap_config_timer);
687 ap_work_queue = create_singlethread_workqueue("kapwork");
688 if (!ap_work_queue)
689 return -ENOMEM;
690 tasklet_enable(&ap_tasklet);
691 if (!ap_using_interrupts())
692 ap_schedule_poll_timer();
693 else
694 tasklet_schedule(&ap_tasklet);
695 if (ap_thread_flag)
696 rc = ap_poll_thread_start();
Felix Beck772f5472009-06-22 12:08:16 +0200697 }
Felix Beck5314af62009-09-22 22:58:51 +0200698 if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) {
699 spin_lock_bh(&ap_dev->lock);
700 ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid),
701 ap_domain_index);
702 spin_unlock_bh(&ap_dev->lock);
703 }
704 queue_work(ap_work_queue, &ap_config_work);
Felix Beck772f5472009-06-22 12:08:16 +0200705
706 return rc;
707}
708
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200709static struct bus_type ap_bus_type = {
710 .name = "ap",
711 .match = &ap_bus_match,
712 .uevent = &ap_uevent,
Felix Beck772f5472009-06-22 12:08:16 +0200713 .suspend = ap_bus_suspend,
714 .resume = ap_bus_resume
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200715};
716
717static int ap_device_probe(struct device *dev)
718{
719 struct ap_device *ap_dev = to_ap_dev(dev);
720 struct ap_driver *ap_drv = to_ap_drv(dev->driver);
721 int rc;
722
723 ap_dev->drv = ap_drv;
724 rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100725 if (!rc) {
Christian Maaser43c207e62008-12-25 13:38:42 +0100726 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100727 list_add(&ap_dev->list, &ap_device_list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100728 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100729 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200730 return rc;
731}
732
733/**
Felix Beck1749a812008-04-17 07:46:28 +0200734 * __ap_flush_queue(): Flush requests.
735 * @ap_dev: Pointer to the AP device
736 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200737 * Flush all requests from the request/pending queue of an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200738 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100739static void __ap_flush_queue(struct ap_device *ap_dev)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200740{
741 struct ap_message *ap_msg, *next;
742
743 list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
744 list_del_init(&ap_msg->list);
745 ap_dev->pendingq_count--;
746 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
747 }
748 list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
749 list_del_init(&ap_msg->list);
750 ap_dev->requestq_count--;
751 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
752 }
753}
754
755void ap_flush_queue(struct ap_device *ap_dev)
756{
757 spin_lock_bh(&ap_dev->lock);
758 __ap_flush_queue(ap_dev);
759 spin_unlock_bh(&ap_dev->lock);
760}
761EXPORT_SYMBOL(ap_flush_queue);
762
763static int ap_device_remove(struct device *dev)
764{
765 struct ap_device *ap_dev = to_ap_dev(dev);
766 struct ap_driver *ap_drv = ap_dev->drv;
767
Ralph Wuerthner4e562962006-10-04 20:02:05 +0200768 ap_flush_queue(ap_dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200769 del_timer_sync(&ap_dev->timeout);
Christian Maaser43c207e62008-12-25 13:38:42 +0100770 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +0100771 list_del_init(&ap_dev->list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100772 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100773 if (ap_drv->remove)
774 ap_drv->remove(ap_dev);
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +0200775 spin_lock_bh(&ap_dev->lock);
776 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
777 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200778 return 0;
779}
780
781int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
782 char *name)
783{
784 struct device_driver *drv = &ap_drv->driver;
785
786 drv->bus = &ap_bus_type;
787 drv->probe = ap_device_probe;
788 drv->remove = ap_device_remove;
789 drv->owner = owner;
790 drv->name = name;
791 return driver_register(drv);
792}
793EXPORT_SYMBOL(ap_driver_register);
794
795void ap_driver_unregister(struct ap_driver *ap_drv)
796{
797 driver_unregister(&ap_drv->driver);
798}
799EXPORT_SYMBOL(ap_driver_unregister);
800
Felix Beck1749a812008-04-17 07:46:28 +0200801/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200802 * AP bus attributes.
803 */
804static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
805{
806 return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
807}
808
809static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
810
811static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
812{
813 return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
814}
815
Felix Beckcb17a632008-12-25 13:38:41 +0100816static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
817{
818 return snprintf(buf, PAGE_SIZE, "%d\n",
819 ap_using_interrupts() ? 1 : 0);
820}
821
822static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL);
823
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200824static ssize_t ap_config_time_store(struct bus_type *bus,
825 const char *buf, size_t count)
826{
827 int time;
828
829 if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120)
830 return -EINVAL;
831 ap_config_time = time;
832 if (!timer_pending(&ap_config_timer) ||
833 !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) {
834 ap_config_timer.expires = jiffies + ap_config_time * HZ;
835 add_timer(&ap_config_timer);
836 }
837 return count;
838}
839
840static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store);
841
842static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf)
843{
844 return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
845}
846
847static ssize_t ap_poll_thread_store(struct bus_type *bus,
848 const char *buf, size_t count)
849{
850 int flag, rc;
851
852 if (sscanf(buf, "%d\n", &flag) != 1)
853 return -EINVAL;
854 if (flag) {
855 rc = ap_poll_thread_start();
856 if (rc)
857 return rc;
858 }
859 else
860 ap_poll_thread_stop();
861 return count;
862}
863
864static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
865
Felix Beckfe137232008-07-14 09:59:08 +0200866static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
867{
868 return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
869}
870
871static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
872 size_t count)
873{
874 unsigned long long time;
875 ktime_t hr_time;
876
877 /* 120 seconds = maximum poll interval */
Felix Beckcb17a632008-12-25 13:38:41 +0100878 if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 ||
879 time > 120000000000ULL)
Felix Beckfe137232008-07-14 09:59:08 +0200880 return -EINVAL;
881 poll_timeout = time;
882 hr_time = ktime_set(0, poll_timeout);
883
884 if (!hrtimer_is_queued(&ap_poll_timer) ||
Arjan van de Ven6c644ea2008-09-01 15:20:30 -0700885 !hrtimer_forward(&ap_poll_timer, hrtimer_get_expires(&ap_poll_timer), hr_time)) {
886 hrtimer_set_expires(&ap_poll_timer, hr_time);
887 hrtimer_start_expires(&ap_poll_timer, HRTIMER_MODE_ABS);
Felix Beckfe137232008-07-14 09:59:08 +0200888 }
889 return count;
890}
891
892static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
893
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200894static struct bus_attribute *const ap_bus_attrs[] = {
895 &bus_attr_ap_domain,
896 &bus_attr_config_time,
897 &bus_attr_poll_thread,
Felix Beckcb17a632008-12-25 13:38:41 +0100898 &bus_attr_ap_interrupts,
Felix Beckfe137232008-07-14 09:59:08 +0200899 &bus_attr_poll_timeout,
900 NULL,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200901};
902
903/**
Felix Beck1749a812008-04-17 07:46:28 +0200904 * ap_select_domain(): Select an AP domain.
905 *
906 * Pick one of the 16 AP domains.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200907 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100908static int ap_select_domain(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200909{
910 int queue_depth, device_type, count, max_count, best_domain;
911 int rc, i, j;
912
Felix Beck1749a812008-04-17 07:46:28 +0200913 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200914 * We want to use a single domain. Either the one specified with
915 * the "domain=" parameter or the domain with the maximum number
916 * of devices.
917 */
918 if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS)
919 /* Domain has already been selected. */
920 return 0;
921 best_domain = -1;
922 max_count = 0;
923 for (i = 0; i < AP_DOMAINS; i++) {
924 count = 0;
925 for (j = 0; j < AP_DEVICES; j++) {
926 ap_qid_t qid = AP_MKQID(j, i);
927 rc = ap_query_queue(qid, &queue_depth, &device_type);
928 if (rc)
929 continue;
930 count++;
931 }
932 if (count > max_count) {
933 max_count = count;
934 best_domain = i;
935 }
936 }
937 if (best_domain >= 0){
938 ap_domain_index = best_domain;
939 return 0;
940 }
941 return -ENODEV;
942}
943
944/**
Felix Beck1749a812008-04-17 07:46:28 +0200945 * ap_probe_device_type(): Find the device type of an AP.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200946 * @ap_dev: pointer to the AP device.
Felix Beck1749a812008-04-17 07:46:28 +0200947 *
948 * Find the device type if query queue returned a device type of 0.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200949 */
950static int ap_probe_device_type(struct ap_device *ap_dev)
951{
952 static unsigned char msg[] = {
953 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
954 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
955 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
956 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
957 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50,
958 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,
959 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00,
960 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,
961 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
962 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,
963 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
964 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,
965 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00,
966 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
967 0x00,0x00,0x00,0x00,0xb8,0x05,0x00,0x00,
968 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
969 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
970 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
971 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
972 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
973 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
974 0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,
975 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
976 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
977 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20,
978 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,
979 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22,
980 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
981 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
982 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,
983 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,
984 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,
985 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
986 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,
987 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00,
988 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,
989 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01,
990 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,
991 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68,
992 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,
993 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0,
994 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,
995 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04,
996 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,
997 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d,
998 };
999 struct ap_queue_status status;
1000 unsigned long long psmid;
1001 char *reply;
1002 int rc, i;
1003
1004 reply = (void *) get_zeroed_page(GFP_KERNEL);
1005 if (!reply) {
1006 rc = -ENOMEM;
1007 goto out;
1008 }
1009
1010 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
1011 msg, sizeof(msg));
1012 if (status.response_code != AP_RESPONSE_NORMAL) {
1013 rc = -ENODEV;
1014 goto out_free;
1015 }
1016
1017 /* Wait for the test message to complete. */
1018 for (i = 0; i < 6; i++) {
1019 mdelay(300);
1020 status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
1021 if (status.response_code == AP_RESPONSE_NORMAL &&
1022 psmid == 0x0102030405060708ULL)
1023 break;
1024 }
1025 if (i < 6) {
1026 /* Got an answer. */
1027 if (reply[0] == 0x00 && reply[1] == 0x86)
1028 ap_dev->device_type = AP_DEVICE_TYPE_PCICC;
1029 else
1030 ap_dev->device_type = AP_DEVICE_TYPE_PCICA;
1031 rc = 0;
1032 } else
1033 rc = -ENODEV;
1034
1035out_free:
1036 free_page((unsigned long) reply);
1037out:
1038 return rc;
1039}
1040
Felix Beckcb17a632008-12-25 13:38:41 +01001041static void ap_interrupt_handler(void *unused1, void *unused2)
1042{
1043 tasklet_schedule(&ap_tasklet);
1044}
1045
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001046/**
Felix Beck1749a812008-04-17 07:46:28 +02001047 * __ap_scan_bus(): Scan the AP bus.
1048 * @dev: Pointer to device
1049 * @data: Pointer to data
1050 *
1051 * Scan the AP bus for new devices.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001052 */
1053static int __ap_scan_bus(struct device *dev, void *data)
1054{
1055 return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data;
1056}
1057
1058static void ap_device_release(struct device *dev)
1059{
1060 struct ap_device *ap_dev = to_ap_dev(dev);
1061
1062 kfree(ap_dev);
1063}
1064
Al Viro4927b3f2006-12-06 19:18:20 +00001065static void ap_scan_bus(struct work_struct *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001066{
1067 struct ap_device *ap_dev;
1068 struct device *dev;
1069 ap_qid_t qid;
1070 int queue_depth, device_type;
1071 int rc, i;
1072
1073 if (ap_select_domain() != 0)
1074 return;
1075 for (i = 0; i < AP_DEVICES; i++) {
1076 qid = AP_MKQID(i, ap_domain_index);
1077 dev = bus_find_device(&ap_bus_type, NULL,
1078 (void *)(unsigned long)qid,
1079 __ap_scan_bus);
Ralph Wuerthnerf3b017d2006-10-27 12:39:26 +02001080 rc = ap_query_queue(qid, &queue_depth, &device_type);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001081 if (dev) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001082 if (rc == -EBUSY) {
1083 set_current_state(TASK_UNINTERRUPTIBLE);
1084 schedule_timeout(AP_RESET_TIMEOUT);
1085 rc = ap_query_queue(qid, &queue_depth,
1086 &device_type);
1087 }
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001088 ap_dev = to_ap_dev(dev);
1089 spin_lock_bh(&ap_dev->lock);
1090 if (rc || ap_dev->unregistered) {
1091 spin_unlock_bh(&ap_dev->lock);
Felix Beck5314af62009-09-22 22:58:51 +02001092 if (ap_dev->unregistered)
1093 i--;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001094 device_unregister(dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001095 put_device(dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001096 continue;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001097 }
1098 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001099 put_device(dev);
1100 continue;
1101 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001102 if (rc)
1103 continue;
1104 rc = ap_init_queue(qid);
1105 if (rc)
1106 continue;
1107 ap_dev = kzalloc(sizeof(*ap_dev), GFP_KERNEL);
1108 if (!ap_dev)
1109 break;
1110 ap_dev->qid = qid;
1111 ap_dev->queue_depth = queue_depth;
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001112 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001113 spin_lock_init(&ap_dev->lock);
1114 INIT_LIST_HEAD(&ap_dev->pendingq);
1115 INIT_LIST_HEAD(&ap_dev->requestq);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001116 INIT_LIST_HEAD(&ap_dev->list);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001117 setup_timer(&ap_dev->timeout, ap_request_timeout,
1118 (unsigned long) ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001119 if (device_type == 0)
1120 ap_probe_device_type(ap_dev);
1121 else
1122 ap_dev->device_type = device_type;
1123
1124 ap_dev->device.bus = &ap_bus_type;
1125 ap_dev->device.parent = ap_root_device;
Felix Beckedc44fa2009-09-11 10:28:52 +02001126 if (dev_set_name(&ap_dev->device, "card%02x",
1127 AP_QID_DEVICE(ap_dev->qid))) {
1128 kfree(ap_dev);
1129 continue;
1130 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001131 ap_dev->device.release = ap_device_release;
1132 rc = device_register(&ap_dev->device);
1133 if (rc) {
Sebastian Ottc6304932009-09-11 10:28:38 +02001134 put_device(&ap_dev->device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001135 continue;
1136 }
1137 /* Add device attributes. */
1138 rc = sysfs_create_group(&ap_dev->device.kobj,
1139 &ap_dev_attr_group);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001140 if (!rc) {
1141 spin_lock_bh(&ap_dev->lock);
1142 ap_dev->unregistered = 0;
1143 spin_unlock_bh(&ap_dev->lock);
1144 }
1145 else
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001146 device_unregister(&ap_dev->device);
1147 }
1148}
1149
1150static void
1151ap_config_timeout(unsigned long ptr)
1152{
1153 queue_work(ap_work_queue, &ap_config_work);
1154 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1155 add_timer(&ap_config_timer);
1156}
1157
1158/**
Felix Beck1749a812008-04-17 07:46:28 +02001159 * ap_schedule_poll_timer(): Schedule poll timer.
1160 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001161 * Set up the timer to run the poll tasklet
1162 */
1163static inline void ap_schedule_poll_timer(void)
1164{
Felix Beck8d406c62009-07-24 12:39:53 +02001165 ktime_t hr_time;
Felix Beck772f5472009-06-22 12:08:16 +02001166 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beckcb17a632008-12-25 13:38:41 +01001167 return;
Felix Beckfe137232008-07-14 09:59:08 +02001168 if (hrtimer_is_queued(&ap_poll_timer))
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001169 return;
Felix Beck8d406c62009-07-24 12:39:53 +02001170 if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
1171 hr_time = ktime_set(0, poll_timeout);
1172 hrtimer_forward_now(&ap_poll_timer, hr_time);
1173 hrtimer_restart(&ap_poll_timer);
1174 }
1175 return;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001176}
1177
1178/**
Felix Beck1749a812008-04-17 07:46:28 +02001179 * ap_poll_read(): Receive pending reply messages from an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001180 * @ap_dev: pointer to the AP device
1181 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1182 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001183 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001184 * Returns 0 if the device is still present, -ENODEV if not.
1185 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001186static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001187{
1188 struct ap_queue_status status;
1189 struct ap_message *ap_msg;
1190
1191 if (ap_dev->queue_count <= 0)
1192 return 0;
1193 status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
1194 ap_dev->reply->message, ap_dev->reply->length);
1195 switch (status.response_code) {
1196 case AP_RESPONSE_NORMAL:
1197 atomic_dec(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001198 ap_decrease_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001199 list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
1200 if (ap_msg->psmid != ap_dev->reply->psmid)
1201 continue;
1202 list_del_init(&ap_msg->list);
1203 ap_dev->pendingq_count--;
1204 ap_dev->drv->receive(ap_dev, ap_msg, ap_dev->reply);
1205 break;
1206 }
1207 if (ap_dev->queue_count > 0)
1208 *flags |= 1;
1209 break;
1210 case AP_RESPONSE_NO_PENDING_REPLY:
1211 if (status.queue_empty) {
1212 /* The card shouldn't forget requests but who knows. */
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +02001213 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001214 ap_dev->queue_count = 0;
1215 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1216 ap_dev->requestq_count += ap_dev->pendingq_count;
1217 ap_dev->pendingq_count = 0;
1218 } else
1219 *flags |= 2;
1220 break;
1221 default:
1222 return -ENODEV;
1223 }
1224 return 0;
1225}
1226
1227/**
Felix Beck1749a812008-04-17 07:46:28 +02001228 * ap_poll_write(): Send messages from the request queue to an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001229 * @ap_dev: pointer to the AP device
1230 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1231 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001232 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001233 * Returns 0 if the device is still present, -ENODEV if not.
1234 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001235static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001236{
1237 struct ap_queue_status status;
1238 struct ap_message *ap_msg;
1239
1240 if (ap_dev->requestq_count <= 0 ||
1241 ap_dev->queue_count >= ap_dev->queue_depth)
1242 return 0;
1243 /* Start the next request on the queue. */
1244 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
1245 status = __ap_send(ap_dev->qid, ap_msg->psmid,
1246 ap_msg->message, ap_msg->length);
1247 switch (status.response_code) {
1248 case AP_RESPONSE_NORMAL:
1249 atomic_inc(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001250 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001251 list_move_tail(&ap_msg->list, &ap_dev->pendingq);
1252 ap_dev->requestq_count--;
1253 ap_dev->pendingq_count++;
1254 if (ap_dev->queue_count < ap_dev->queue_depth &&
1255 ap_dev->requestq_count > 0)
1256 *flags |= 1;
1257 *flags |= 2;
1258 break;
1259 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001260 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001261 *flags |= 2;
1262 break;
1263 case AP_RESPONSE_MESSAGE_TOO_BIG:
1264 return -EINVAL;
1265 default:
1266 return -ENODEV;
1267 }
1268 return 0;
1269}
1270
1271/**
Felix Beck1749a812008-04-17 07:46:28 +02001272 * ap_poll_queue(): Poll AP device for pending replies and send new messages.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001273 * @ap_dev: pointer to the bus device
1274 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1275 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001276 *
1277 * Poll AP device for pending replies and send new messages. If either
1278 * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001279 * Returns 0.
1280 */
1281static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
1282{
1283 int rc;
1284
1285 rc = ap_poll_read(ap_dev, flags);
1286 if (rc)
1287 return rc;
1288 return ap_poll_write(ap_dev, flags);
1289}
1290
1291/**
Felix Beck1749a812008-04-17 07:46:28 +02001292 * __ap_queue_message(): Queue a message to a device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001293 * @ap_dev: pointer to the AP device
1294 * @ap_msg: the message to be queued
Felix Beck1749a812008-04-17 07:46:28 +02001295 *
1296 * Queue a message to a device. Returns 0 if successful.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001297 */
1298static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1299{
1300 struct ap_queue_status status;
1301
1302 if (list_empty(&ap_dev->requestq) &&
1303 ap_dev->queue_count < ap_dev->queue_depth) {
1304 status = __ap_send(ap_dev->qid, ap_msg->psmid,
1305 ap_msg->message, ap_msg->length);
1306 switch (status.response_code) {
1307 case AP_RESPONSE_NORMAL:
1308 list_add_tail(&ap_msg->list, &ap_dev->pendingq);
1309 atomic_inc(&ap_poll_requests);
1310 ap_dev->pendingq_count++;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001311 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001312 ap_dev->total_request_count++;
1313 break;
1314 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001315 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001316 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1317 ap_dev->requestq_count++;
1318 ap_dev->total_request_count++;
1319 return -EBUSY;
1320 case AP_RESPONSE_MESSAGE_TOO_BIG:
1321 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
1322 return -EINVAL;
1323 default: /* Device is gone. */
1324 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
1325 return -ENODEV;
1326 }
1327 } else {
1328 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1329 ap_dev->requestq_count++;
1330 ap_dev->total_request_count++;
1331 return -EBUSY;
1332 }
1333 ap_schedule_poll_timer();
1334 return 0;
1335}
1336
1337void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1338{
1339 unsigned long flags;
1340 int rc;
1341
1342 spin_lock_bh(&ap_dev->lock);
1343 if (!ap_dev->unregistered) {
1344 /* Make room on the queue by polling for finished requests. */
1345 rc = ap_poll_queue(ap_dev, &flags);
1346 if (!rc)
1347 rc = __ap_queue_message(ap_dev, ap_msg);
1348 if (!rc)
1349 wake_up(&ap_poll_wait);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001350 if (rc == -ENODEV)
1351 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001352 } else {
1353 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001354 rc = -ENODEV;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001355 }
1356 spin_unlock_bh(&ap_dev->lock);
1357 if (rc == -ENODEV)
1358 device_unregister(&ap_dev->device);
1359}
1360EXPORT_SYMBOL(ap_queue_message);
1361
1362/**
Felix Beck1749a812008-04-17 07:46:28 +02001363 * ap_cancel_message(): Cancel a crypto request.
1364 * @ap_dev: The AP device that has the message queued
1365 * @ap_msg: The message that is to be removed
1366 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001367 * Cancel a crypto request. This is done by removing the request
Felix Beck1749a812008-04-17 07:46:28 +02001368 * from the device pending or request queue. Note that the
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001369 * request stays on the AP queue. When it finishes the message
1370 * reply will be discarded because the psmid can't be found.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001371 */
1372void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1373{
1374 struct ap_message *tmp;
1375
1376 spin_lock_bh(&ap_dev->lock);
1377 if (!list_empty(&ap_msg->list)) {
1378 list_for_each_entry(tmp, &ap_dev->pendingq, list)
1379 if (tmp->psmid == ap_msg->psmid) {
1380 ap_dev->pendingq_count--;
1381 goto found;
1382 }
1383 ap_dev->requestq_count--;
1384 found:
1385 list_del_init(&ap_msg->list);
1386 }
1387 spin_unlock_bh(&ap_dev->lock);
1388}
1389EXPORT_SYMBOL(ap_cancel_message);
1390
1391/**
Felix Beck1749a812008-04-17 07:46:28 +02001392 * ap_poll_timeout(): AP receive polling for finished AP requests.
Felix Beckfe137232008-07-14 09:59:08 +02001393 * @unused: Unused pointer.
Felix Beck1749a812008-04-17 07:46:28 +02001394 *
Felix Beckfe137232008-07-14 09:59:08 +02001395 * Schedules the AP tasklet using a high resolution timer.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001396 */
Felix Beckfe137232008-07-14 09:59:08 +02001397static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001398{
1399 tasklet_schedule(&ap_tasklet);
Felix Beckfe137232008-07-14 09:59:08 +02001400 return HRTIMER_NORESTART;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001401}
1402
1403/**
Felix Beck1749a812008-04-17 07:46:28 +02001404 * ap_reset(): Reset a not responding AP device.
1405 * @ap_dev: Pointer to the AP device
1406 *
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001407 * Reset a not responding AP device and move all requests from the
1408 * pending queue to the request queue.
1409 */
1410static void ap_reset(struct ap_device *ap_dev)
1411{
1412 int rc;
1413
1414 ap_dev->reset = AP_RESET_IGNORE;
1415 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
1416 ap_dev->queue_count = 0;
1417 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1418 ap_dev->requestq_count += ap_dev->pendingq_count;
1419 ap_dev->pendingq_count = 0;
1420 rc = ap_init_queue(ap_dev->qid);
1421 if (rc == -ENODEV)
1422 ap_dev->unregistered = 1;
1423}
1424
Christian Maaser43c207e62008-12-25 13:38:42 +01001425static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001426{
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001427 if (!ap_dev->unregistered) {
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001428 if (ap_poll_queue(ap_dev, flags))
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001429 ap_dev->unregistered = 1;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001430 if (ap_dev->reset == AP_RESET_DO)
1431 ap_reset(ap_dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001432 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001433 return 0;
1434}
1435
Felix Beck1749a812008-04-17 07:46:28 +02001436/**
1437 * ap_poll_all(): Poll all AP devices.
1438 * @dummy: Unused variable
1439 *
1440 * Poll all AP devices on the bus in a round robin fashion. Continue
1441 * polling until bit 2^0 of the control flags is not set. If bit 2^1
1442 * of the control flags has been set arm the poll timer.
1443 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001444static void ap_poll_all(unsigned long dummy)
1445{
1446 unsigned long flags;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001447 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001448
Felix Beckcb17a632008-12-25 13:38:41 +01001449 /* Reset the indicator if interrupts are used. Thus new interrupts can
1450 * be received. Doing it in the beginning of the tasklet is therefor
1451 * important that no requests on any AP get lost.
1452 */
1453 if (ap_using_interrupts())
1454 xchg((u8 *)ap_interrupt_indicator, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001455 do {
1456 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001457 spin_lock(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001458 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001459 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001460 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001461 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001462 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001463 spin_unlock(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001464 } while (flags & 1);
1465 if (flags & 2)
1466 ap_schedule_poll_timer();
1467}
1468
1469/**
Felix Beck1749a812008-04-17 07:46:28 +02001470 * ap_poll_thread(): Thread that polls for finished requests.
1471 * @data: Unused pointer
1472 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001473 * AP bus poll thread. The purpose of this thread is to poll for
1474 * finished requests in a loop if there is a "free" cpu - that is
1475 * a cpu that doesn't have anything better to do. The polling stops
1476 * as soon as there is another task or if all messages have been
1477 * delivered.
1478 */
1479static int ap_poll_thread(void *data)
1480{
1481 DECLARE_WAITQUEUE(wait, current);
1482 unsigned long flags;
1483 int requests;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001484 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001485
Christian Borntraegerd83682b2006-10-06 16:38:22 +02001486 set_user_nice(current, 19);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001487 while (1) {
Felix Beck772f5472009-06-22 12:08:16 +02001488 if (ap_suspend_flag)
1489 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001490 if (need_resched()) {
1491 schedule();
1492 continue;
1493 }
1494 add_wait_queue(&ap_poll_wait, &wait);
1495 set_current_state(TASK_INTERRUPTIBLE);
1496 if (kthread_should_stop())
1497 break;
1498 requests = atomic_read(&ap_poll_requests);
1499 if (requests <= 0)
1500 schedule();
1501 set_current_state(TASK_RUNNING);
1502 remove_wait_queue(&ap_poll_wait, &wait);
1503
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001504 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001505 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001506 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001507 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001508 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001509 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001510 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001511 spin_unlock_bh(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001512 }
1513 set_current_state(TASK_RUNNING);
1514 remove_wait_queue(&ap_poll_wait, &wait);
1515 return 0;
1516}
1517
1518static int ap_poll_thread_start(void)
1519{
1520 int rc;
1521
Felix Beck772f5472009-06-22 12:08:16 +02001522 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beckcb17a632008-12-25 13:38:41 +01001523 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001524 mutex_lock(&ap_poll_thread_mutex);
1525 if (!ap_poll_kthread) {
1526 ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
1527 rc = IS_ERR(ap_poll_kthread) ? PTR_ERR(ap_poll_kthread) : 0;
1528 if (rc)
1529 ap_poll_kthread = NULL;
1530 }
1531 else
1532 rc = 0;
1533 mutex_unlock(&ap_poll_thread_mutex);
1534 return rc;
1535}
1536
1537static void ap_poll_thread_stop(void)
1538{
1539 mutex_lock(&ap_poll_thread_mutex);
1540 if (ap_poll_kthread) {
1541 kthread_stop(ap_poll_kthread);
1542 ap_poll_kthread = NULL;
1543 }
1544 mutex_unlock(&ap_poll_thread_mutex);
1545}
1546
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001547/**
Felix Beck1749a812008-04-17 07:46:28 +02001548 * ap_request_timeout(): Handling of request timeouts
1549 * @data: Holds the AP device.
1550 *
1551 * Handles request timeouts.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001552 */
1553static void ap_request_timeout(unsigned long data)
1554{
1555 struct ap_device *ap_dev = (struct ap_device *) data;
1556
Felix Beckcb17a632008-12-25 13:38:41 +01001557 if (ap_dev->reset == AP_RESET_ARMED) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001558 ap_dev->reset = AP_RESET_DO;
Felix Beckcb17a632008-12-25 13:38:41 +01001559
1560 if (ap_using_interrupts())
1561 tasklet_schedule(&ap_tasklet);
1562 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001563}
1564
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001565static void ap_reset_domain(void)
1566{
1567 int i;
1568
Ralph Wuerthner39aa7cf2007-10-12 16:11:29 +02001569 if (ap_domain_index != -1)
1570 for (i = 0; i < AP_DEVICES; i++)
1571 ap_reset_queue(AP_MKQID(i, ap_domain_index));
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001572}
1573
1574static void ap_reset_all(void)
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001575{
1576 int i, j;
1577
1578 for (i = 0; i < AP_DOMAINS; i++)
1579 for (j = 0; j < AP_DEVICES; j++)
1580 ap_reset_queue(AP_MKQID(j, i));
1581}
1582
1583static struct reset_call ap_reset_call = {
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001584 .fn = ap_reset_all,
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001585};
1586
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001587/**
Felix Beck1749a812008-04-17 07:46:28 +02001588 * ap_module_init(): The module initialization code.
1589 *
1590 * Initializes the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001591 */
1592int __init ap_module_init(void)
1593{
1594 int rc, i;
1595
1596 if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001597 pr_warning("%d is not a valid cryptographic domain\n",
1598 ap_domain_index);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001599 return -EINVAL;
1600 }
Felix Beck5314af62009-09-22 22:58:51 +02001601 /* In resume callback we need to know if the user had set the domain.
1602 * If so, we can not just reset it.
1603 */
1604 if (ap_domain_index >= 0)
1605 user_set_domain = 1;
1606
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001607 if (ap_instructions_available() != 0) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001608 pr_warning("The hardware system does not support "
1609 "AP instructions\n");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001610 return -ENODEV;
1611 }
Felix Beckcb17a632008-12-25 13:38:41 +01001612 if (ap_interrupts_available()) {
1613 isc_register(AP_ISC);
1614 ap_interrupt_indicator = s390_register_adapter_interrupt(
1615 &ap_interrupt_handler, NULL, AP_ISC);
1616 if (IS_ERR(ap_interrupt_indicator)) {
1617 ap_interrupt_indicator = NULL;
1618 isc_unregister(AP_ISC);
1619 }
1620 }
1621
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001622 register_reset_call(&ap_reset_call);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001623
1624 /* Create /sys/bus/ap. */
1625 rc = bus_register(&ap_bus_type);
1626 if (rc)
1627 goto out;
1628 for (i = 0; ap_bus_attrs[i]; i++) {
1629 rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]);
1630 if (rc)
1631 goto out_bus;
1632 }
1633
1634 /* Create /sys/devices/ap. */
Mark McLoughlin035da162008-12-15 12:58:29 +00001635 ap_root_device = root_device_register("ap");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001636 rc = IS_ERR(ap_root_device) ? PTR_ERR(ap_root_device) : 0;
1637 if (rc)
1638 goto out_bus;
1639
1640 ap_work_queue = create_singlethread_workqueue("kapwork");
1641 if (!ap_work_queue) {
1642 rc = -ENOMEM;
1643 goto out_root;
1644 }
1645
1646 if (ap_select_domain() == 0)
1647 ap_scan_bus(NULL);
1648
Felix Beck1749a812008-04-17 07:46:28 +02001649 /* Setup the AP bus rescan timer. */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001650 init_timer(&ap_config_timer);
1651 ap_config_timer.function = ap_config_timeout;
1652 ap_config_timer.data = 0;
1653 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1654 add_timer(&ap_config_timer);
1655
Felix Beckfe137232008-07-14 09:59:08 +02001656 /* Setup the high resultion poll timer.
1657 * If we are running under z/VM adjust polling to z/VM polling rate.
1658 */
1659 if (MACHINE_IS_VM)
1660 poll_timeout = 1500000;
1661 hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1662 ap_poll_timer.function = ap_poll_timeout;
1663
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001664 /* Start the low priority AP bus poll thread. */
1665 if (ap_thread_flag) {
1666 rc = ap_poll_thread_start();
1667 if (rc)
1668 goto out_work;
1669 }
1670
1671 return 0;
1672
1673out_work:
1674 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001675 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001676 destroy_workqueue(ap_work_queue);
1677out_root:
Mark McLoughlin035da162008-12-15 12:58:29 +00001678 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001679out_bus:
1680 while (i--)
1681 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1682 bus_unregister(&ap_bus_type);
1683out:
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001684 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001685 if (ap_using_interrupts()) {
1686 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1687 isc_unregister(AP_ISC);
1688 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001689 return rc;
1690}
1691
1692static int __ap_match_all(struct device *dev, void *data)
1693{
1694 return 1;
1695}
1696
1697/**
Felix Beck1749a812008-04-17 07:46:28 +02001698 * ap_modules_exit(): The module termination code
1699 *
1700 * Terminates the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001701 */
1702void ap_module_exit(void)
1703{
1704 int i;
1705 struct device *dev;
1706
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001707 ap_reset_domain();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001708 ap_poll_thread_stop();
1709 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001710 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001711 destroy_workqueue(ap_work_queue);
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001712 tasklet_kill(&ap_tasklet);
Mark McLoughlin035da162008-12-15 12:58:29 +00001713 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001714 while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
1715 __ap_match_all)))
1716 {
1717 device_unregister(dev);
1718 put_device(dev);
1719 }
1720 for (i = 0; ap_bus_attrs[i]; i++)
1721 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1722 bus_unregister(&ap_bus_type);
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001723 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001724 if (ap_using_interrupts()) {
1725 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1726 isc_unregister(AP_ISC);
1727 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001728}
1729
1730#ifndef CONFIG_ZCRYPT_MONOLITHIC
1731module_init(ap_module_init);
1732module_exit(ap_module_exit);
1733#endif