blob: 1f5f5d2d87d94b8fb3123f5c1d9855492b22b122 [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>
39#include <asm/s390_rdev.h>
Ralph Wuerthner85eca852006-12-08 15:54:07 +010040#include <asm/reset.h>
Felix Beckcb17a632008-12-25 13:38:41 +010041#include <asm/airq.h>
42#include <asm/atomic.h>
43#include <asm/system.h>
44#include <asm/isc.h>
Felix Beckfe137232008-07-14 09:59:08 +020045#include <linux/hrtimer.h>
46#include <linux/ktime.h>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020047
48#include "ap_bus.h"
49
50/* Some prototypes. */
Al Viro4927b3f2006-12-06 19:18:20 +000051static void ap_scan_bus(struct work_struct *);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020052static void ap_poll_all(unsigned long);
Felix Beckfe137232008-07-14 09:59:08 +020053static enum hrtimer_restart ap_poll_timeout(struct hrtimer *);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020054static int ap_poll_thread_start(void);
55static void ap_poll_thread_stop(void);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +020056static void ap_request_timeout(unsigned long);
Felix Beckcb17a632008-12-25 13:38:41 +010057static inline void ap_schedule_poll_timer(void);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020058
Felix Beck1749a812008-04-17 07:46:28 +020059/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020060 * Module description.
61 */
62MODULE_AUTHOR("IBM Corporation");
63MODULE_DESCRIPTION("Adjunct Processor Bus driver, "
64 "Copyright 2006 IBM Corporation");
65MODULE_LICENSE("GPL");
66
Felix Beck1749a812008-04-17 07:46:28 +020067/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020068 * Module parameter
69 */
70int ap_domain_index = -1; /* Adjunct Processor Domain Index */
71module_param_named(domain, ap_domain_index, int, 0000);
72MODULE_PARM_DESC(domain, "domain index for ap devices");
73EXPORT_SYMBOL(ap_domain_index);
74
Felix Beckb90b34c2008-02-09 18:24:30 +010075static int ap_thread_flag = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +020076module_param_named(poll_thread, ap_thread_flag, int, 0000);
Felix Beckb90b34c2008-02-09 18:24:30 +010077MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off).");
Martin Schwidefsky1534c382006-09-20 15:58:25 +020078
79static struct device *ap_root_device = NULL;
Christian Maaser43c207e62008-12-25 13:38:42 +010080static DEFINE_SPINLOCK(ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +010081static LIST_HEAD(ap_device_list);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020082
Felix Beck1749a812008-04-17 07:46:28 +020083/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020084 * Workqueue & timer for bus rescan.
85 */
86static struct workqueue_struct *ap_work_queue;
87static struct timer_list ap_config_timer;
88static int ap_config_time = AP_CONFIG_TIME;
Al Viro4927b3f2006-12-06 19:18:20 +000089static DECLARE_WORK(ap_config_work, ap_scan_bus);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020090
Felix Beck1749a812008-04-17 07:46:28 +020091/*
Felix Beckcb17a632008-12-25 13:38:41 +010092 * Tasklet & timer for AP request polling and interrupts
Martin Schwidefsky1534c382006-09-20 15:58:25 +020093 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +020094static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0);
95static atomic_t ap_poll_requests = ATOMIC_INIT(0);
96static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
97static struct task_struct *ap_poll_kthread = NULL;
98static DEFINE_MUTEX(ap_poll_thread_mutex);
Felix Beckcb17a632008-12-25 13:38:41 +010099static void *ap_interrupt_indicator;
Felix Beckfe137232008-07-14 09:59:08 +0200100static struct hrtimer ap_poll_timer;
101/* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
102 * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
103static unsigned long long poll_timeout = 250000;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200104
105/**
Felix Beckcb17a632008-12-25 13:38:41 +0100106 * ap_using_interrupts() - Returns non-zero if interrupt support is
107 * available.
108 */
109static inline int ap_using_interrupts(void)
110{
111 return ap_interrupt_indicator != NULL;
112}
113
114/**
Felix Beck1749a812008-04-17 07:46:28 +0200115 * ap_intructions_available() - Test if AP instructions are available.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200116 *
Felix Beck1749a812008-04-17 07:46:28 +0200117 * Returns 0 if the AP instructions are installed.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200118 */
119static inline int ap_instructions_available(void)
120{
121 register unsigned long reg0 asm ("0") = AP_MKQID(0,0);
122 register unsigned long reg1 asm ("1") = -ENODEV;
123 register unsigned long reg2 asm ("2") = 0UL;
124
125 asm volatile(
126 " .long 0xb2af0000\n" /* PQAP(TAPQ) */
127 "0: la %1,0\n"
128 "1:\n"
129 EX_TABLE(0b, 1b)
130 : "+d" (reg0), "+d" (reg1), "+d" (reg2) : : "cc" );
131 return reg1;
132}
133
134/**
Felix Beckcb17a632008-12-25 13:38:41 +0100135 * ap_interrupts_available(): Test if AP interrupts are available.
136 *
137 * Returns 1 if AP interrupts are available.
138 */
139static int ap_interrupts_available(void)
140{
141 unsigned long long facility_bits[2];
142
143 if (stfle(facility_bits, 2) <= 1)
144 return 0;
145 if (!(facility_bits[0] & (1ULL << 61)) ||
146 !(facility_bits[1] & (1ULL << 62)))
147 return 0;
148 return 1;
149}
150
151/**
Felix Beck1749a812008-04-17 07:46:28 +0200152 * ap_test_queue(): Test adjunct processor queue.
153 * @qid: The AP queue number
154 * @queue_depth: Pointer to queue depth value
155 * @device_type: Pointer to device type value
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200156 *
Felix Beck1749a812008-04-17 07:46:28 +0200157 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200158 */
159static inline struct ap_queue_status
160ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
161{
162 register unsigned long reg0 asm ("0") = qid;
163 register struct ap_queue_status reg1 asm ("1");
164 register unsigned long reg2 asm ("2") = 0UL;
165
166 asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
167 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
168 *device_type = (int) (reg2 >> 24);
169 *queue_depth = (int) (reg2 & 0xff);
170 return reg1;
171}
172
173/**
Felix Beck1749a812008-04-17 07:46:28 +0200174 * ap_reset_queue(): Reset adjunct processor queue.
175 * @qid: The AP queue number
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200176 *
Felix Beck1749a812008-04-17 07:46:28 +0200177 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200178 */
179static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
180{
181 register unsigned long reg0 asm ("0") = qid | 0x01000000UL;
182 register struct ap_queue_status reg1 asm ("1");
183 register unsigned long reg2 asm ("2") = 0UL;
184
185 asm volatile(
186 ".long 0xb2af0000" /* PQAP(RAPQ) */
187 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
188 return reg1;
189}
190
Felix Beckcb17a632008-12-25 13:38:41 +0100191#ifdef CONFIG_64BIT
192/**
193 * ap_queue_interruption_control(): Enable interruption for a specific AP.
194 * @qid: The AP queue number
195 * @ind: The notification indicator byte
196 *
197 * Returns AP queue status.
198 */
199static inline struct ap_queue_status
200ap_queue_interruption_control(ap_qid_t qid, void *ind)
201{
202 register unsigned long reg0 asm ("0") = qid | 0x03000000UL;
203 register unsigned long reg1_in asm ("1") = 0x0000800000000000UL | AP_ISC;
204 register struct ap_queue_status reg1_out asm ("1");
205 register void *reg2 asm ("2") = ind;
206 asm volatile(
207 ".long 0xb2af0000" /* PQAP(RAPQ) */
208 : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
209 :
210 : "cc" );
211 return reg1_out;
212}
213#endif
214
215/**
216 * ap_queue_enable_interruption(): Enable interruption on an AP.
217 * @qid: The AP queue number
218 * @ind: the notification indicator byte
219 *
220 * Enables interruption on AP queue via ap_queue_interruption_control(). Based
221 * on the return value it waits a while and tests the AP queue if interrupts
222 * have been switched on using ap_test_queue().
223 */
224static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
225{
226#ifdef CONFIG_64BIT
227 struct ap_queue_status status;
228 int t_depth, t_device_type, rc, i;
229
230 rc = -EBUSY;
231 status = ap_queue_interruption_control(qid, ind);
232
233 for (i = 0; i < AP_MAX_RESET; i++) {
234 switch (status.response_code) {
235 case AP_RESPONSE_NORMAL:
236 if (status.int_enabled)
237 return 0;
238 break;
239 case AP_RESPONSE_RESET_IN_PROGRESS:
240 case AP_RESPONSE_BUSY:
241 break;
242 case AP_RESPONSE_Q_NOT_AVAIL:
243 case AP_RESPONSE_DECONFIGURED:
244 case AP_RESPONSE_CHECKSTOPPED:
245 case AP_RESPONSE_INVALID_ADDRESS:
246 return -ENODEV;
247 case AP_RESPONSE_OTHERWISE_CHANGED:
248 if (status.int_enabled)
249 return 0;
250 break;
251 default:
252 break;
253 }
254 if (i < AP_MAX_RESET - 1) {
255 udelay(5);
256 status = ap_test_queue(qid, &t_depth, &t_device_type);
257 }
258 }
259 return rc;
260#else
261 return -EINVAL;
262#endif
263}
264
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200265/**
Felix Beck1749a812008-04-17 07:46:28 +0200266 * __ap_send(): Send message to adjunct processor queue.
267 * @qid: The AP queue number
268 * @psmid: The program supplied message identifier
269 * @msg: The message text
270 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200271 *
Felix Beck1749a812008-04-17 07:46:28 +0200272 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200273 * Condition code 1 on NQAP can't happen because the L bit is 1.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200274 * Condition code 2 on NQAP also means the send is incomplete,
275 * because a segment boundary was reached. The NQAP is repeated.
276 */
277static inline struct ap_queue_status
278__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
279{
280 typedef struct { char _[length]; } msgblock;
281 register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
282 register struct ap_queue_status reg1 asm ("1");
283 register unsigned long reg2 asm ("2") = (unsigned long) msg;
284 register unsigned long reg3 asm ("3") = (unsigned long) length;
285 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
286 register unsigned long reg5 asm ("5") = (unsigned int) psmid;
287
288 asm volatile (
289 "0: .long 0xb2ad0042\n" /* DQAP */
290 " brc 2,0b"
291 : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
292 : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg)
293 : "cc" );
294 return reg1;
295}
296
297int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
298{
299 struct ap_queue_status status;
300
301 status = __ap_send(qid, psmid, msg, length);
302 switch (status.response_code) {
303 case AP_RESPONSE_NORMAL:
304 return 0;
305 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200306 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200307 return -EBUSY;
308 default: /* Device is gone. */
309 return -ENODEV;
310 }
311}
312EXPORT_SYMBOL(ap_send);
313
Felix Beck1749a812008-04-17 07:46:28 +0200314/**
315 * __ap_recv(): Receive message from adjunct processor queue.
316 * @qid: The AP queue number
317 * @psmid: Pointer to program supplied message identifier
318 * @msg: The message text
319 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200320 *
Felix Beck1749a812008-04-17 07:46:28 +0200321 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200322 * Condition code 1 on DQAP means the receive has taken place
323 * but only partially. The response is incomplete, hence the
324 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200325 * Condition code 2 on DQAP also means the receive is incomplete,
326 * this time because a segment boundary was reached. Again, the
327 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200328 * Note that gpr2 is used by the DQAP instruction to keep track of
329 * any 'residual' length, in case the instruction gets interrupted.
330 * Hence it gets zeroed before the instruction.
331 */
332static inline struct ap_queue_status
333__ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
334{
335 typedef struct { char _[length]; } msgblock;
336 register unsigned long reg0 asm("0") = qid | 0x80000000UL;
337 register struct ap_queue_status reg1 asm ("1");
338 register unsigned long reg2 asm("2") = 0UL;
339 register unsigned long reg4 asm("4") = (unsigned long) msg;
340 register unsigned long reg5 asm("5") = (unsigned long) length;
341 register unsigned long reg6 asm("6") = 0UL;
342 register unsigned long reg7 asm("7") = 0UL;
343
344
345 asm volatile(
346 "0: .long 0xb2ae0064\n"
347 " brc 6,0b\n"
348 : "+d" (reg0), "=d" (reg1), "+d" (reg2),
349 "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
350 "=m" (*(msgblock *) msg) : : "cc" );
351 *psmid = (((unsigned long long) reg6) << 32) + reg7;
352 return reg1;
353}
354
355int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
356{
357 struct ap_queue_status status;
358
359 status = __ap_recv(qid, psmid, msg, length);
360 switch (status.response_code) {
361 case AP_RESPONSE_NORMAL:
362 return 0;
363 case AP_RESPONSE_NO_PENDING_REPLY:
364 if (status.queue_empty)
365 return -ENOENT;
366 return -EBUSY;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200367 case AP_RESPONSE_RESET_IN_PROGRESS:
368 return -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200369 default:
370 return -ENODEV;
371 }
372}
373EXPORT_SYMBOL(ap_recv);
374
375/**
Felix Beck1749a812008-04-17 07:46:28 +0200376 * ap_query_queue(): Check if an AP queue is available.
377 * @qid: The AP queue number
378 * @queue_depth: Pointer to queue depth value
379 * @device_type: Pointer to device type value
380 *
381 * The test is repeated for AP_MAX_RESET times.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200382 */
383static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
384{
385 struct ap_queue_status status;
386 int t_depth, t_device_type, rc, i;
387
388 rc = -EBUSY;
389 for (i = 0; i < AP_MAX_RESET; i++) {
390 status = ap_test_queue(qid, &t_depth, &t_device_type);
391 switch (status.response_code) {
392 case AP_RESPONSE_NORMAL:
393 *queue_depth = t_depth + 1;
394 *device_type = t_device_type;
395 rc = 0;
396 break;
397 case AP_RESPONSE_Q_NOT_AVAIL:
398 rc = -ENODEV;
399 break;
400 case AP_RESPONSE_RESET_IN_PROGRESS:
401 break;
402 case AP_RESPONSE_DECONFIGURED:
403 rc = -ENODEV;
404 break;
405 case AP_RESPONSE_CHECKSTOPPED:
406 rc = -ENODEV;
407 break;
Felix Beckcb17a632008-12-25 13:38:41 +0100408 case AP_RESPONSE_INVALID_ADDRESS:
409 rc = -ENODEV;
410 break;
411 case AP_RESPONSE_OTHERWISE_CHANGED:
412 break;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200413 case AP_RESPONSE_BUSY:
414 break;
415 default:
416 BUG();
417 }
418 if (rc != -EBUSY)
419 break;
420 if (i < AP_MAX_RESET - 1)
421 udelay(5);
422 }
423 return rc;
424}
425
426/**
Felix Beck1749a812008-04-17 07:46:28 +0200427 * ap_init_queue(): Reset an AP queue.
428 * @qid: The AP queue number
429 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200430 * Reset an AP queue and wait for it to become available again.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200431 */
432static int ap_init_queue(ap_qid_t qid)
433{
434 struct ap_queue_status status;
435 int rc, dummy, i;
436
437 rc = -ENODEV;
438 status = ap_reset_queue(qid);
439 for (i = 0; i < AP_MAX_RESET; i++) {
440 switch (status.response_code) {
441 case AP_RESPONSE_NORMAL:
442 if (status.queue_empty)
443 rc = 0;
444 break;
445 case AP_RESPONSE_Q_NOT_AVAIL:
446 case AP_RESPONSE_DECONFIGURED:
447 case AP_RESPONSE_CHECKSTOPPED:
448 i = AP_MAX_RESET; /* return with -ENODEV */
449 break;
450 case AP_RESPONSE_RESET_IN_PROGRESS:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200451 rc = -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200452 case AP_RESPONSE_BUSY:
453 default:
454 break;
455 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200456 if (rc != -ENODEV && rc != -EBUSY)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200457 break;
458 if (i < AP_MAX_RESET - 1) {
459 udelay(5);
460 status = ap_test_queue(qid, &dummy, &dummy);
461 }
462 }
Felix Beckcb17a632008-12-25 13:38:41 +0100463 if (rc == 0 && ap_using_interrupts()) {
464 rc = ap_queue_enable_interruption(qid, ap_interrupt_indicator);
465 /* If interruption mode is supported by the machine,
466 * but an AP can not be enabled for interruption then
467 * the AP will be discarded. */
468 if (rc)
469 pr_err("Registering adapter interrupts for "
470 "AP %d failed\n", AP_QID_DEVICE(qid));
471 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200472 return rc;
473}
474
475/**
Felix Beck1749a812008-04-17 07:46:28 +0200476 * ap_increase_queue_count(): Arm request timeout.
477 * @ap_dev: Pointer to an AP device.
478 *
479 * Arm request timeout if an AP device was idle and a new request is submitted.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200480 */
481static void ap_increase_queue_count(struct ap_device *ap_dev)
482{
483 int timeout = ap_dev->drv->request_timeout;
484
485 ap_dev->queue_count++;
486 if (ap_dev->queue_count == 1) {
487 mod_timer(&ap_dev->timeout, jiffies + timeout);
488 ap_dev->reset = AP_RESET_ARMED;
489 }
490}
491
492/**
Felix Beck1749a812008-04-17 07:46:28 +0200493 * ap_decrease_queue_count(): Decrease queue count.
494 * @ap_dev: Pointer to an AP device.
495 *
496 * If AP device is still alive, re-schedule request timeout if there are still
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200497 * pending requests.
498 */
499static void ap_decrease_queue_count(struct ap_device *ap_dev)
500{
501 int timeout = ap_dev->drv->request_timeout;
502
503 ap_dev->queue_count--;
504 if (ap_dev->queue_count > 0)
505 mod_timer(&ap_dev->timeout, jiffies + timeout);
506 else
Felix Beck1749a812008-04-17 07:46:28 +0200507 /*
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200508 * The timeout timer should to be disabled now - since
509 * del_timer_sync() is very expensive, we just tell via the
510 * reset flag to ignore the pending timeout timer.
511 */
512 ap_dev->reset = AP_RESET_IGNORE;
513}
514
Felix Beck1749a812008-04-17 07:46:28 +0200515/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200516 * AP device related attributes.
517 */
518static ssize_t ap_hwtype_show(struct device *dev,
519 struct device_attribute *attr, char *buf)
520{
521 struct ap_device *ap_dev = to_ap_dev(dev);
522 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type);
523}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200524
Christian Maaser43c207e62008-12-25 13:38:42 +0100525static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200526static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr,
527 char *buf)
528{
529 struct ap_device *ap_dev = to_ap_dev(dev);
530 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth);
531}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200532
Christian Maaser43c207e62008-12-25 13:38:42 +0100533static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200534static ssize_t ap_request_count_show(struct device *dev,
535 struct device_attribute *attr,
536 char *buf)
537{
538 struct ap_device *ap_dev = to_ap_dev(dev);
539 int rc;
540
541 spin_lock_bh(&ap_dev->lock);
542 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->total_request_count);
543 spin_unlock_bh(&ap_dev->lock);
544 return rc;
545}
546
547static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL);
548
549static ssize_t ap_modalias_show(struct device *dev,
550 struct device_attribute *attr, char *buf)
551{
552 return sprintf(buf, "ap:t%02X", to_ap_dev(dev)->device_type);
553}
554
555static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL);
556
557static struct attribute *ap_dev_attrs[] = {
558 &dev_attr_hwtype.attr,
559 &dev_attr_depth.attr,
560 &dev_attr_request_count.attr,
561 &dev_attr_modalias.attr,
562 NULL
563};
564static struct attribute_group ap_dev_attr_group = {
565 .attrs = ap_dev_attrs
566};
567
568/**
Felix Beck1749a812008-04-17 07:46:28 +0200569 * ap_bus_match()
570 * @dev: Pointer to device
571 * @drv: Pointer to device_driver
572 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200573 * AP bus driver registration/unregistration.
574 */
575static int ap_bus_match(struct device *dev, struct device_driver *drv)
576{
577 struct ap_device *ap_dev = to_ap_dev(dev);
578 struct ap_driver *ap_drv = to_ap_drv(drv);
579 struct ap_device_id *id;
580
Felix Beck1749a812008-04-17 07:46:28 +0200581 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200582 * Compare device type of the device with the list of
583 * supported types of the device_driver.
584 */
585 for (id = ap_drv->ids; id->match_flags; id++) {
586 if ((id->match_flags & AP_DEVICE_ID_MATCH_DEVICE_TYPE) &&
587 (id->dev_type != ap_dev->device_type))
588 continue;
589 return 1;
590 }
591 return 0;
592}
593
594/**
Felix Beck1749a812008-04-17 07:46:28 +0200595 * ap_uevent(): Uevent function for AP devices.
596 * @dev: Pointer to device
597 * @env: Pointer to kobj_uevent_env
598 *
599 * It sets up a single environment variable DEV_TYPE which contains the
600 * hardware device type.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200601 */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200602static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200603{
604 struct ap_device *ap_dev = to_ap_dev(dev);
Kay Sievers7eff2e72007-08-14 15:15:12 +0200605 int retval = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200606
607 if (!ap_dev)
608 return -ENODEV;
609
610 /* Set up DEV_TYPE environment variable. */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200611 retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700612 if (retval)
613 return retval;
614
Cornelia Huck66a42632006-12-04 15:40:10 +0100615 /* Add MODALIAS= */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200616 retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700617
Eric Rannaudbf624562007-03-30 22:23:12 -0700618 return retval;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200619}
620
621static struct bus_type ap_bus_type = {
622 .name = "ap",
623 .match = &ap_bus_match,
624 .uevent = &ap_uevent,
625};
626
627static int ap_device_probe(struct device *dev)
628{
629 struct ap_device *ap_dev = to_ap_dev(dev);
630 struct ap_driver *ap_drv = to_ap_drv(dev->driver);
631 int rc;
632
633 ap_dev->drv = ap_drv;
634 rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100635 if (!rc) {
Christian Maaser43c207e62008-12-25 13:38:42 +0100636 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100637 list_add(&ap_dev->list, &ap_device_list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100638 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100639 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200640 return rc;
641}
642
643/**
Felix Beck1749a812008-04-17 07:46:28 +0200644 * __ap_flush_queue(): Flush requests.
645 * @ap_dev: Pointer to the AP device
646 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200647 * Flush all requests from the request/pending queue of an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200648 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100649static void __ap_flush_queue(struct ap_device *ap_dev)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200650{
651 struct ap_message *ap_msg, *next;
652
653 list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
654 list_del_init(&ap_msg->list);
655 ap_dev->pendingq_count--;
656 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
657 }
658 list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
659 list_del_init(&ap_msg->list);
660 ap_dev->requestq_count--;
661 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
662 }
663}
664
665void ap_flush_queue(struct ap_device *ap_dev)
666{
667 spin_lock_bh(&ap_dev->lock);
668 __ap_flush_queue(ap_dev);
669 spin_unlock_bh(&ap_dev->lock);
670}
671EXPORT_SYMBOL(ap_flush_queue);
672
673static int ap_device_remove(struct device *dev)
674{
675 struct ap_device *ap_dev = to_ap_dev(dev);
676 struct ap_driver *ap_drv = ap_dev->drv;
677
Ralph Wuerthner4e562962006-10-04 20:02:05 +0200678 ap_flush_queue(ap_dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200679 del_timer_sync(&ap_dev->timeout);
Christian Maaser43c207e62008-12-25 13:38:42 +0100680 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +0100681 list_del_init(&ap_dev->list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100682 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100683 if (ap_drv->remove)
684 ap_drv->remove(ap_dev);
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +0200685 spin_lock_bh(&ap_dev->lock);
686 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
687 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200688 return 0;
689}
690
691int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
692 char *name)
693{
694 struct device_driver *drv = &ap_drv->driver;
695
696 drv->bus = &ap_bus_type;
697 drv->probe = ap_device_probe;
698 drv->remove = ap_device_remove;
699 drv->owner = owner;
700 drv->name = name;
701 return driver_register(drv);
702}
703EXPORT_SYMBOL(ap_driver_register);
704
705void ap_driver_unregister(struct ap_driver *ap_drv)
706{
707 driver_unregister(&ap_drv->driver);
708}
709EXPORT_SYMBOL(ap_driver_unregister);
710
Felix Beck1749a812008-04-17 07:46:28 +0200711/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200712 * AP bus attributes.
713 */
714static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
715{
716 return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
717}
718
719static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
720
721static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
722{
723 return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
724}
725
Felix Beckcb17a632008-12-25 13:38:41 +0100726static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
727{
728 return snprintf(buf, PAGE_SIZE, "%d\n",
729 ap_using_interrupts() ? 1 : 0);
730}
731
732static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL);
733
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200734static ssize_t ap_config_time_store(struct bus_type *bus,
735 const char *buf, size_t count)
736{
737 int time;
738
739 if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120)
740 return -EINVAL;
741 ap_config_time = time;
742 if (!timer_pending(&ap_config_timer) ||
743 !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) {
744 ap_config_timer.expires = jiffies + ap_config_time * HZ;
745 add_timer(&ap_config_timer);
746 }
747 return count;
748}
749
750static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store);
751
752static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf)
753{
754 return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
755}
756
757static ssize_t ap_poll_thread_store(struct bus_type *bus,
758 const char *buf, size_t count)
759{
760 int flag, rc;
761
762 if (sscanf(buf, "%d\n", &flag) != 1)
763 return -EINVAL;
764 if (flag) {
765 rc = ap_poll_thread_start();
766 if (rc)
767 return rc;
768 }
769 else
770 ap_poll_thread_stop();
771 return count;
772}
773
774static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
775
Felix Beckfe137232008-07-14 09:59:08 +0200776static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
777{
778 return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
779}
780
781static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
782 size_t count)
783{
784 unsigned long long time;
785 ktime_t hr_time;
786
787 /* 120 seconds = maximum poll interval */
Felix Beckcb17a632008-12-25 13:38:41 +0100788 if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 ||
789 time > 120000000000ULL)
Felix Beckfe137232008-07-14 09:59:08 +0200790 return -EINVAL;
791 poll_timeout = time;
792 hr_time = ktime_set(0, poll_timeout);
793
794 if (!hrtimer_is_queued(&ap_poll_timer) ||
Arjan van de Ven6c644ea2008-09-01 15:20:30 -0700795 !hrtimer_forward(&ap_poll_timer, hrtimer_get_expires(&ap_poll_timer), hr_time)) {
796 hrtimer_set_expires(&ap_poll_timer, hr_time);
797 hrtimer_start_expires(&ap_poll_timer, HRTIMER_MODE_ABS);
Felix Beckfe137232008-07-14 09:59:08 +0200798 }
799 return count;
800}
801
802static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
803
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200804static struct bus_attribute *const ap_bus_attrs[] = {
805 &bus_attr_ap_domain,
806 &bus_attr_config_time,
807 &bus_attr_poll_thread,
Felix Beckcb17a632008-12-25 13:38:41 +0100808 &bus_attr_ap_interrupts,
Felix Beckfe137232008-07-14 09:59:08 +0200809 &bus_attr_poll_timeout,
810 NULL,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200811};
812
813/**
Felix Beck1749a812008-04-17 07:46:28 +0200814 * ap_select_domain(): Select an AP domain.
815 *
816 * Pick one of the 16 AP domains.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200817 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100818static int ap_select_domain(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200819{
820 int queue_depth, device_type, count, max_count, best_domain;
821 int rc, i, j;
822
Felix Beck1749a812008-04-17 07:46:28 +0200823 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200824 * We want to use a single domain. Either the one specified with
825 * the "domain=" parameter or the domain with the maximum number
826 * of devices.
827 */
828 if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS)
829 /* Domain has already been selected. */
830 return 0;
831 best_domain = -1;
832 max_count = 0;
833 for (i = 0; i < AP_DOMAINS; i++) {
834 count = 0;
835 for (j = 0; j < AP_DEVICES; j++) {
836 ap_qid_t qid = AP_MKQID(j, i);
837 rc = ap_query_queue(qid, &queue_depth, &device_type);
838 if (rc)
839 continue;
840 count++;
841 }
842 if (count > max_count) {
843 max_count = count;
844 best_domain = i;
845 }
846 }
847 if (best_domain >= 0){
848 ap_domain_index = best_domain;
849 return 0;
850 }
851 return -ENODEV;
852}
853
854/**
Felix Beck1749a812008-04-17 07:46:28 +0200855 * ap_probe_device_type(): Find the device type of an AP.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200856 * @ap_dev: pointer to the AP device.
Felix Beck1749a812008-04-17 07:46:28 +0200857 *
858 * Find the device type if query queue returned a device type of 0.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200859 */
860static int ap_probe_device_type(struct ap_device *ap_dev)
861{
862 static unsigned char msg[] = {
863 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
864 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
865 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
866 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
867 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50,
868 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,
869 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00,
870 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,
871 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
872 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,
873 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
874 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,
875 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00,
876 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
877 0x00,0x00,0x00,0x00,0xb8,0x05,0x00,0x00,
878 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
879 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
880 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
881 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
882 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
883 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
884 0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,
885 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
886 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
887 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20,
888 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,
889 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22,
890 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
891 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
892 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,
893 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,
894 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,
895 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
896 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,
897 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00,
898 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,
899 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01,
900 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,
901 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68,
902 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,
903 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0,
904 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,
905 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04,
906 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,
907 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d,
908 };
909 struct ap_queue_status status;
910 unsigned long long psmid;
911 char *reply;
912 int rc, i;
913
914 reply = (void *) get_zeroed_page(GFP_KERNEL);
915 if (!reply) {
916 rc = -ENOMEM;
917 goto out;
918 }
919
920 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
921 msg, sizeof(msg));
922 if (status.response_code != AP_RESPONSE_NORMAL) {
923 rc = -ENODEV;
924 goto out_free;
925 }
926
927 /* Wait for the test message to complete. */
928 for (i = 0; i < 6; i++) {
929 mdelay(300);
930 status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
931 if (status.response_code == AP_RESPONSE_NORMAL &&
932 psmid == 0x0102030405060708ULL)
933 break;
934 }
935 if (i < 6) {
936 /* Got an answer. */
937 if (reply[0] == 0x00 && reply[1] == 0x86)
938 ap_dev->device_type = AP_DEVICE_TYPE_PCICC;
939 else
940 ap_dev->device_type = AP_DEVICE_TYPE_PCICA;
941 rc = 0;
942 } else
943 rc = -ENODEV;
944
945out_free:
946 free_page((unsigned long) reply);
947out:
948 return rc;
949}
950
Felix Beckcb17a632008-12-25 13:38:41 +0100951static void ap_interrupt_handler(void *unused1, void *unused2)
952{
953 tasklet_schedule(&ap_tasklet);
954}
955
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200956/**
Felix Beck1749a812008-04-17 07:46:28 +0200957 * __ap_scan_bus(): Scan the AP bus.
958 * @dev: Pointer to device
959 * @data: Pointer to data
960 *
961 * Scan the AP bus for new devices.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200962 */
963static int __ap_scan_bus(struct device *dev, void *data)
964{
965 return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data;
966}
967
968static void ap_device_release(struct device *dev)
969{
970 struct ap_device *ap_dev = to_ap_dev(dev);
971
972 kfree(ap_dev);
973}
974
Al Viro4927b3f2006-12-06 19:18:20 +0000975static void ap_scan_bus(struct work_struct *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200976{
977 struct ap_device *ap_dev;
978 struct device *dev;
979 ap_qid_t qid;
980 int queue_depth, device_type;
981 int rc, i;
982
983 if (ap_select_domain() != 0)
984 return;
985 for (i = 0; i < AP_DEVICES; i++) {
986 qid = AP_MKQID(i, ap_domain_index);
987 dev = bus_find_device(&ap_bus_type, NULL,
988 (void *)(unsigned long)qid,
989 __ap_scan_bus);
Ralph Wuerthnerf3b017d2006-10-27 12:39:26 +0200990 rc = ap_query_queue(qid, &queue_depth, &device_type);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +0200991 if (dev) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200992 if (rc == -EBUSY) {
993 set_current_state(TASK_UNINTERRUPTIBLE);
994 schedule_timeout(AP_RESET_TIMEOUT);
995 rc = ap_query_queue(qid, &queue_depth,
996 &device_type);
997 }
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +0200998 ap_dev = to_ap_dev(dev);
999 spin_lock_bh(&ap_dev->lock);
1000 if (rc || ap_dev->unregistered) {
1001 spin_unlock_bh(&ap_dev->lock);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001002 device_unregister(dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001003 put_device(dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001004 continue;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001005 }
1006 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001007 put_device(dev);
1008 continue;
1009 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001010 if (rc)
1011 continue;
1012 rc = ap_init_queue(qid);
1013 if (rc)
1014 continue;
1015 ap_dev = kzalloc(sizeof(*ap_dev), GFP_KERNEL);
1016 if (!ap_dev)
1017 break;
1018 ap_dev->qid = qid;
1019 ap_dev->queue_depth = queue_depth;
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001020 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001021 spin_lock_init(&ap_dev->lock);
1022 INIT_LIST_HEAD(&ap_dev->pendingq);
1023 INIT_LIST_HEAD(&ap_dev->requestq);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001024 INIT_LIST_HEAD(&ap_dev->list);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001025 setup_timer(&ap_dev->timeout, ap_request_timeout,
1026 (unsigned long) ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001027 if (device_type == 0)
1028 ap_probe_device_type(ap_dev);
1029 else
1030 ap_dev->device_type = device_type;
1031
1032 ap_dev->device.bus = &ap_bus_type;
1033 ap_dev->device.parent = ap_root_device;
Cornelia Huck1bf5b282008-10-10 21:33:10 +02001034 dev_set_name(&ap_dev->device, "card%02x",
1035 AP_QID_DEVICE(ap_dev->qid));
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001036 ap_dev->device.release = ap_device_release;
1037 rc = device_register(&ap_dev->device);
1038 if (rc) {
1039 kfree(ap_dev);
1040 continue;
1041 }
1042 /* Add device attributes. */
1043 rc = sysfs_create_group(&ap_dev->device.kobj,
1044 &ap_dev_attr_group);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001045 if (!rc) {
1046 spin_lock_bh(&ap_dev->lock);
1047 ap_dev->unregistered = 0;
1048 spin_unlock_bh(&ap_dev->lock);
1049 }
1050 else
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001051 device_unregister(&ap_dev->device);
1052 }
1053}
1054
1055static void
1056ap_config_timeout(unsigned long ptr)
1057{
1058 queue_work(ap_work_queue, &ap_config_work);
1059 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1060 add_timer(&ap_config_timer);
1061}
1062
1063/**
Felix Beck1749a812008-04-17 07:46:28 +02001064 * ap_schedule_poll_timer(): Schedule poll timer.
1065 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001066 * Set up the timer to run the poll tasklet
1067 */
1068static inline void ap_schedule_poll_timer(void)
1069{
Felix Beckcb17a632008-12-25 13:38:41 +01001070 if (ap_using_interrupts())
1071 return;
Felix Beckfe137232008-07-14 09:59:08 +02001072 if (hrtimer_is_queued(&ap_poll_timer))
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001073 return;
Felix Beckfe137232008-07-14 09:59:08 +02001074 hrtimer_start(&ap_poll_timer, ktime_set(0, poll_timeout),
1075 HRTIMER_MODE_ABS);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001076}
1077
1078/**
Felix Beck1749a812008-04-17 07:46:28 +02001079 * ap_poll_read(): Receive pending reply messages from an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001080 * @ap_dev: pointer to the AP device
1081 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1082 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001083 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001084 * Returns 0 if the device is still present, -ENODEV if not.
1085 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001086static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001087{
1088 struct ap_queue_status status;
1089 struct ap_message *ap_msg;
1090
1091 if (ap_dev->queue_count <= 0)
1092 return 0;
1093 status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
1094 ap_dev->reply->message, ap_dev->reply->length);
1095 switch (status.response_code) {
1096 case AP_RESPONSE_NORMAL:
1097 atomic_dec(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001098 ap_decrease_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001099 list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
1100 if (ap_msg->psmid != ap_dev->reply->psmid)
1101 continue;
1102 list_del_init(&ap_msg->list);
1103 ap_dev->pendingq_count--;
1104 ap_dev->drv->receive(ap_dev, ap_msg, ap_dev->reply);
1105 break;
1106 }
1107 if (ap_dev->queue_count > 0)
1108 *flags |= 1;
1109 break;
1110 case AP_RESPONSE_NO_PENDING_REPLY:
1111 if (status.queue_empty) {
1112 /* The card shouldn't forget requests but who knows. */
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +02001113 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001114 ap_dev->queue_count = 0;
1115 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1116 ap_dev->requestq_count += ap_dev->pendingq_count;
1117 ap_dev->pendingq_count = 0;
1118 } else
1119 *flags |= 2;
1120 break;
1121 default:
1122 return -ENODEV;
1123 }
1124 return 0;
1125}
1126
1127/**
Felix Beck1749a812008-04-17 07:46:28 +02001128 * ap_poll_write(): Send messages from the request queue to an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001129 * @ap_dev: pointer to the AP device
1130 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1131 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001132 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001133 * Returns 0 if the device is still present, -ENODEV if not.
1134 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001135static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001136{
1137 struct ap_queue_status status;
1138 struct ap_message *ap_msg;
1139
1140 if (ap_dev->requestq_count <= 0 ||
1141 ap_dev->queue_count >= ap_dev->queue_depth)
1142 return 0;
1143 /* Start the next request on the queue. */
1144 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
1145 status = __ap_send(ap_dev->qid, ap_msg->psmid,
1146 ap_msg->message, ap_msg->length);
1147 switch (status.response_code) {
1148 case AP_RESPONSE_NORMAL:
1149 atomic_inc(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001150 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001151 list_move_tail(&ap_msg->list, &ap_dev->pendingq);
1152 ap_dev->requestq_count--;
1153 ap_dev->pendingq_count++;
1154 if (ap_dev->queue_count < ap_dev->queue_depth &&
1155 ap_dev->requestq_count > 0)
1156 *flags |= 1;
1157 *flags |= 2;
1158 break;
1159 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001160 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001161 *flags |= 2;
1162 break;
1163 case AP_RESPONSE_MESSAGE_TOO_BIG:
1164 return -EINVAL;
1165 default:
1166 return -ENODEV;
1167 }
1168 return 0;
1169}
1170
1171/**
Felix Beck1749a812008-04-17 07:46:28 +02001172 * ap_poll_queue(): Poll AP device for pending replies and send new messages.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001173 * @ap_dev: pointer to the bus device
1174 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1175 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001176 *
1177 * Poll AP device for pending replies and send new messages. If either
1178 * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001179 * Returns 0.
1180 */
1181static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
1182{
1183 int rc;
1184
1185 rc = ap_poll_read(ap_dev, flags);
1186 if (rc)
1187 return rc;
1188 return ap_poll_write(ap_dev, flags);
1189}
1190
1191/**
Felix Beck1749a812008-04-17 07:46:28 +02001192 * __ap_queue_message(): Queue a message to a device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001193 * @ap_dev: pointer to the AP device
1194 * @ap_msg: the message to be queued
Felix Beck1749a812008-04-17 07:46:28 +02001195 *
1196 * Queue a message to a device. Returns 0 if successful.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001197 */
1198static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1199{
1200 struct ap_queue_status status;
1201
1202 if (list_empty(&ap_dev->requestq) &&
1203 ap_dev->queue_count < ap_dev->queue_depth) {
1204 status = __ap_send(ap_dev->qid, ap_msg->psmid,
1205 ap_msg->message, ap_msg->length);
1206 switch (status.response_code) {
1207 case AP_RESPONSE_NORMAL:
1208 list_add_tail(&ap_msg->list, &ap_dev->pendingq);
1209 atomic_inc(&ap_poll_requests);
1210 ap_dev->pendingq_count++;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001211 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001212 ap_dev->total_request_count++;
1213 break;
1214 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001215 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001216 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1217 ap_dev->requestq_count++;
1218 ap_dev->total_request_count++;
1219 return -EBUSY;
1220 case AP_RESPONSE_MESSAGE_TOO_BIG:
1221 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
1222 return -EINVAL;
1223 default: /* Device is gone. */
1224 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
1225 return -ENODEV;
1226 }
1227 } else {
1228 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1229 ap_dev->requestq_count++;
1230 ap_dev->total_request_count++;
1231 return -EBUSY;
1232 }
1233 ap_schedule_poll_timer();
1234 return 0;
1235}
1236
1237void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1238{
1239 unsigned long flags;
1240 int rc;
1241
1242 spin_lock_bh(&ap_dev->lock);
1243 if (!ap_dev->unregistered) {
1244 /* Make room on the queue by polling for finished requests. */
1245 rc = ap_poll_queue(ap_dev, &flags);
1246 if (!rc)
1247 rc = __ap_queue_message(ap_dev, ap_msg);
1248 if (!rc)
1249 wake_up(&ap_poll_wait);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001250 if (rc == -ENODEV)
1251 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001252 } else {
1253 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001254 rc = -ENODEV;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001255 }
1256 spin_unlock_bh(&ap_dev->lock);
1257 if (rc == -ENODEV)
1258 device_unregister(&ap_dev->device);
1259}
1260EXPORT_SYMBOL(ap_queue_message);
1261
1262/**
Felix Beck1749a812008-04-17 07:46:28 +02001263 * ap_cancel_message(): Cancel a crypto request.
1264 * @ap_dev: The AP device that has the message queued
1265 * @ap_msg: The message that is to be removed
1266 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001267 * Cancel a crypto request. This is done by removing the request
Felix Beck1749a812008-04-17 07:46:28 +02001268 * from the device pending or request queue. Note that the
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001269 * request stays on the AP queue. When it finishes the message
1270 * reply will be discarded because the psmid can't be found.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001271 */
1272void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1273{
1274 struct ap_message *tmp;
1275
1276 spin_lock_bh(&ap_dev->lock);
1277 if (!list_empty(&ap_msg->list)) {
1278 list_for_each_entry(tmp, &ap_dev->pendingq, list)
1279 if (tmp->psmid == ap_msg->psmid) {
1280 ap_dev->pendingq_count--;
1281 goto found;
1282 }
1283 ap_dev->requestq_count--;
1284 found:
1285 list_del_init(&ap_msg->list);
1286 }
1287 spin_unlock_bh(&ap_dev->lock);
1288}
1289EXPORT_SYMBOL(ap_cancel_message);
1290
1291/**
Felix Beck1749a812008-04-17 07:46:28 +02001292 * ap_poll_timeout(): AP receive polling for finished AP requests.
Felix Beckfe137232008-07-14 09:59:08 +02001293 * @unused: Unused pointer.
Felix Beck1749a812008-04-17 07:46:28 +02001294 *
Felix Beckfe137232008-07-14 09:59:08 +02001295 * Schedules the AP tasklet using a high resolution timer.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001296 */
Felix Beckfe137232008-07-14 09:59:08 +02001297static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001298{
1299 tasklet_schedule(&ap_tasklet);
Felix Beckfe137232008-07-14 09:59:08 +02001300 return HRTIMER_NORESTART;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001301}
1302
1303/**
Felix Beck1749a812008-04-17 07:46:28 +02001304 * ap_reset(): Reset a not responding AP device.
1305 * @ap_dev: Pointer to the AP device
1306 *
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001307 * Reset a not responding AP device and move all requests from the
1308 * pending queue to the request queue.
1309 */
1310static void ap_reset(struct ap_device *ap_dev)
1311{
1312 int rc;
1313
1314 ap_dev->reset = AP_RESET_IGNORE;
1315 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
1316 ap_dev->queue_count = 0;
1317 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1318 ap_dev->requestq_count += ap_dev->pendingq_count;
1319 ap_dev->pendingq_count = 0;
1320 rc = ap_init_queue(ap_dev->qid);
1321 if (rc == -ENODEV)
1322 ap_dev->unregistered = 1;
1323}
1324
Christian Maaser43c207e62008-12-25 13:38:42 +01001325static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001326{
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001327 spin_lock(&ap_dev->lock);
1328 if (!ap_dev->unregistered) {
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001329 if (ap_poll_queue(ap_dev, flags))
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001330 ap_dev->unregistered = 1;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001331 if (ap_dev->reset == AP_RESET_DO)
1332 ap_reset(ap_dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001333 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001334 spin_unlock(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001335 return 0;
1336}
1337
Felix Beck1749a812008-04-17 07:46:28 +02001338/**
1339 * ap_poll_all(): Poll all AP devices.
1340 * @dummy: Unused variable
1341 *
1342 * Poll all AP devices on the bus in a round robin fashion. Continue
1343 * polling until bit 2^0 of the control flags is not set. If bit 2^1
1344 * of the control flags has been set arm the poll timer.
1345 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001346static void ap_poll_all(unsigned long dummy)
1347{
1348 unsigned long flags;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001349 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001350
Felix Beckcb17a632008-12-25 13:38:41 +01001351 /* Reset the indicator if interrupts are used. Thus new interrupts can
1352 * be received. Doing it in the beginning of the tasklet is therefor
1353 * important that no requests on any AP get lost.
1354 */
1355 if (ap_using_interrupts())
1356 xchg((u8 *)ap_interrupt_indicator, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001357 do {
1358 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001359 spin_lock(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001360 list_for_each_entry(ap_dev, &ap_device_list, list) {
Christian Maaser43c207e62008-12-25 13:38:42 +01001361 __ap_poll_device(ap_dev, &flags);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001362 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001363 spin_unlock(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001364 } while (flags & 1);
1365 if (flags & 2)
1366 ap_schedule_poll_timer();
1367}
1368
1369/**
Felix Beck1749a812008-04-17 07:46:28 +02001370 * ap_poll_thread(): Thread that polls for finished requests.
1371 * @data: Unused pointer
1372 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001373 * AP bus poll thread. The purpose of this thread is to poll for
1374 * finished requests in a loop if there is a "free" cpu - that is
1375 * a cpu that doesn't have anything better to do. The polling stops
1376 * as soon as there is another task or if all messages have been
1377 * delivered.
1378 */
1379static int ap_poll_thread(void *data)
1380{
1381 DECLARE_WAITQUEUE(wait, current);
1382 unsigned long flags;
1383 int requests;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001384 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001385
Christian Borntraegerd83682b2006-10-06 16:38:22 +02001386 set_user_nice(current, 19);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001387 while (1) {
1388 if (need_resched()) {
1389 schedule();
1390 continue;
1391 }
1392 add_wait_queue(&ap_poll_wait, &wait);
1393 set_current_state(TASK_INTERRUPTIBLE);
1394 if (kthread_should_stop())
1395 break;
1396 requests = atomic_read(&ap_poll_requests);
1397 if (requests <= 0)
1398 schedule();
1399 set_current_state(TASK_RUNNING);
1400 remove_wait_queue(&ap_poll_wait, &wait);
1401
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001402 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001403 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001404 list_for_each_entry(ap_dev, &ap_device_list, list) {
Christian Maaser43c207e62008-12-25 13:38:42 +01001405 __ap_poll_device(ap_dev, &flags);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001406 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001407 spin_unlock_bh(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001408 }
1409 set_current_state(TASK_RUNNING);
1410 remove_wait_queue(&ap_poll_wait, &wait);
1411 return 0;
1412}
1413
1414static int ap_poll_thread_start(void)
1415{
1416 int rc;
1417
Felix Beckcb17a632008-12-25 13:38:41 +01001418 if (ap_using_interrupts())
1419 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001420 mutex_lock(&ap_poll_thread_mutex);
1421 if (!ap_poll_kthread) {
1422 ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
1423 rc = IS_ERR(ap_poll_kthread) ? PTR_ERR(ap_poll_kthread) : 0;
1424 if (rc)
1425 ap_poll_kthread = NULL;
1426 }
1427 else
1428 rc = 0;
1429 mutex_unlock(&ap_poll_thread_mutex);
1430 return rc;
1431}
1432
1433static void ap_poll_thread_stop(void)
1434{
1435 mutex_lock(&ap_poll_thread_mutex);
1436 if (ap_poll_kthread) {
1437 kthread_stop(ap_poll_kthread);
1438 ap_poll_kthread = NULL;
1439 }
1440 mutex_unlock(&ap_poll_thread_mutex);
1441}
1442
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001443/**
Felix Beck1749a812008-04-17 07:46:28 +02001444 * ap_request_timeout(): Handling of request timeouts
1445 * @data: Holds the AP device.
1446 *
1447 * Handles request timeouts.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001448 */
1449static void ap_request_timeout(unsigned long data)
1450{
1451 struct ap_device *ap_dev = (struct ap_device *) data;
1452
Felix Beckcb17a632008-12-25 13:38:41 +01001453 if (ap_dev->reset == AP_RESET_ARMED) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001454 ap_dev->reset = AP_RESET_DO;
Felix Beckcb17a632008-12-25 13:38:41 +01001455
1456 if (ap_using_interrupts())
1457 tasklet_schedule(&ap_tasklet);
1458 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001459}
1460
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001461static void ap_reset_domain(void)
1462{
1463 int i;
1464
Ralph Wuerthner39aa7cf2007-10-12 16:11:29 +02001465 if (ap_domain_index != -1)
1466 for (i = 0; i < AP_DEVICES; i++)
1467 ap_reset_queue(AP_MKQID(i, ap_domain_index));
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001468}
1469
1470static void ap_reset_all(void)
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001471{
1472 int i, j;
1473
1474 for (i = 0; i < AP_DOMAINS; i++)
1475 for (j = 0; j < AP_DEVICES; j++)
1476 ap_reset_queue(AP_MKQID(j, i));
1477}
1478
1479static struct reset_call ap_reset_call = {
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001480 .fn = ap_reset_all,
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001481};
1482
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001483/**
Felix Beck1749a812008-04-17 07:46:28 +02001484 * ap_module_init(): The module initialization code.
1485 *
1486 * Initializes the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001487 */
1488int __init ap_module_init(void)
1489{
1490 int rc, i;
1491
1492 if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001493 pr_warning("%d is not a valid cryptographic domain\n",
1494 ap_domain_index);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001495 return -EINVAL;
1496 }
1497 if (ap_instructions_available() != 0) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001498 pr_warning("The hardware system does not support "
1499 "AP instructions\n");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001500 return -ENODEV;
1501 }
Felix Beckcb17a632008-12-25 13:38:41 +01001502 if (ap_interrupts_available()) {
1503 isc_register(AP_ISC);
1504 ap_interrupt_indicator = s390_register_adapter_interrupt(
1505 &ap_interrupt_handler, NULL, AP_ISC);
1506 if (IS_ERR(ap_interrupt_indicator)) {
1507 ap_interrupt_indicator = NULL;
1508 isc_unregister(AP_ISC);
1509 }
1510 }
1511
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001512 register_reset_call(&ap_reset_call);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001513
1514 /* Create /sys/bus/ap. */
1515 rc = bus_register(&ap_bus_type);
1516 if (rc)
1517 goto out;
1518 for (i = 0; ap_bus_attrs[i]; i++) {
1519 rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]);
1520 if (rc)
1521 goto out_bus;
1522 }
1523
1524 /* Create /sys/devices/ap. */
1525 ap_root_device = s390_root_dev_register("ap");
1526 rc = IS_ERR(ap_root_device) ? PTR_ERR(ap_root_device) : 0;
1527 if (rc)
1528 goto out_bus;
1529
1530 ap_work_queue = create_singlethread_workqueue("kapwork");
1531 if (!ap_work_queue) {
1532 rc = -ENOMEM;
1533 goto out_root;
1534 }
1535
1536 if (ap_select_domain() == 0)
1537 ap_scan_bus(NULL);
1538
Felix Beck1749a812008-04-17 07:46:28 +02001539 /* Setup the AP bus rescan timer. */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001540 init_timer(&ap_config_timer);
1541 ap_config_timer.function = ap_config_timeout;
1542 ap_config_timer.data = 0;
1543 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1544 add_timer(&ap_config_timer);
1545
Felix Beckfe137232008-07-14 09:59:08 +02001546 /* Setup the high resultion poll timer.
1547 * If we are running under z/VM adjust polling to z/VM polling rate.
1548 */
1549 if (MACHINE_IS_VM)
1550 poll_timeout = 1500000;
1551 hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1552 ap_poll_timer.function = ap_poll_timeout;
1553
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001554 /* Start the low priority AP bus poll thread. */
1555 if (ap_thread_flag) {
1556 rc = ap_poll_thread_start();
1557 if (rc)
1558 goto out_work;
1559 }
1560
1561 return 0;
1562
1563out_work:
1564 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001565 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001566 destroy_workqueue(ap_work_queue);
1567out_root:
1568 s390_root_dev_unregister(ap_root_device);
1569out_bus:
1570 while (i--)
1571 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1572 bus_unregister(&ap_bus_type);
1573out:
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001574 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001575 if (ap_using_interrupts()) {
1576 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1577 isc_unregister(AP_ISC);
1578 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001579 return rc;
1580}
1581
1582static int __ap_match_all(struct device *dev, void *data)
1583{
1584 return 1;
1585}
1586
1587/**
Felix Beck1749a812008-04-17 07:46:28 +02001588 * ap_modules_exit(): The module termination code
1589 *
1590 * Terminates the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001591 */
1592void ap_module_exit(void)
1593{
1594 int i;
1595 struct device *dev;
1596
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001597 ap_reset_domain();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001598 ap_poll_thread_stop();
1599 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001600 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001601 destroy_workqueue(ap_work_queue);
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001602 tasklet_kill(&ap_tasklet);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001603 s390_root_dev_unregister(ap_root_device);
1604 while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
1605 __ap_match_all)))
1606 {
1607 device_unregister(dev);
1608 put_device(dev);
1609 }
1610 for (i = 0; ap_bus_attrs[i]; i++)
1611 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1612 bus_unregister(&ap_bus_type);
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001613 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001614 if (ap_using_interrupts()) {
1615 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1616 isc_unregister(AP_ISC);
1617 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001618}
1619
1620#ifndef CONFIG_ZCRYPT_MONOLITHIC
1621module_init(ap_module_init);
1622module_exit(ap_module_exit);
1623#endif