blob: 2335be5f9bf76aba0361a5c70699c119cfbef349 [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
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/delay.h>
30#include <linux/err.h>
31#include <linux/interrupt.h>
32#include <linux/workqueue.h>
33#include <linux/notifier.h>
34#include <linux/kthread.h>
35#include <linux/mutex.h>
36#include <asm/s390_rdev.h>
Ralph Wuerthner85eca852006-12-08 15:54:07 +010037#include <asm/reset.h>
Felix Beckcb17a632008-12-25 13:38:41 +010038#include <asm/airq.h>
39#include <asm/atomic.h>
40#include <asm/system.h>
41#include <asm/isc.h>
Felix Beckfe137232008-07-14 09:59:08 +020042#include <linux/hrtimer.h>
43#include <linux/ktime.h>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020044
45#include "ap_bus.h"
46
47/* Some prototypes. */
Al Viro4927b3f2006-12-06 19:18:20 +000048static void ap_scan_bus(struct work_struct *);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020049static void ap_poll_all(unsigned long);
Felix Beckfe137232008-07-14 09:59:08 +020050static enum hrtimer_restart ap_poll_timeout(struct hrtimer *);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020051static int ap_poll_thread_start(void);
52static void ap_poll_thread_stop(void);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +020053static void ap_request_timeout(unsigned long);
Felix Beckcb17a632008-12-25 13:38:41 +010054static inline void ap_schedule_poll_timer(void);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020055
Felix Beck1749a812008-04-17 07:46:28 +020056/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020057 * Module description.
58 */
59MODULE_AUTHOR("IBM Corporation");
60MODULE_DESCRIPTION("Adjunct Processor Bus driver, "
61 "Copyright 2006 IBM Corporation");
62MODULE_LICENSE("GPL");
63
Felix Beck1749a812008-04-17 07:46:28 +020064/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020065 * Module parameter
66 */
67int ap_domain_index = -1; /* Adjunct Processor Domain Index */
68module_param_named(domain, ap_domain_index, int, 0000);
69MODULE_PARM_DESC(domain, "domain index for ap devices");
70EXPORT_SYMBOL(ap_domain_index);
71
Felix Beckb90b34c2008-02-09 18:24:30 +010072static int ap_thread_flag = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +020073module_param_named(poll_thread, ap_thread_flag, int, 0000);
Felix Beckb90b34c2008-02-09 18:24:30 +010074MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off).");
Martin Schwidefsky1534c382006-09-20 15:58:25 +020075
76static struct device *ap_root_device = NULL;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +010077static DEFINE_SPINLOCK(ap_device_lock);
78static LIST_HEAD(ap_device_list);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020079
Felix Beck1749a812008-04-17 07:46:28 +020080/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020081 * Workqueue & timer for bus rescan.
82 */
83static struct workqueue_struct *ap_work_queue;
84static struct timer_list ap_config_timer;
85static int ap_config_time = AP_CONFIG_TIME;
Al Viro4927b3f2006-12-06 19:18:20 +000086static DECLARE_WORK(ap_config_work, ap_scan_bus);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020087
Felix Beck1749a812008-04-17 07:46:28 +020088/*
Felix Beckcb17a632008-12-25 13:38:41 +010089 * Tasklet & timer for AP request polling and interrupts
Martin Schwidefsky1534c382006-09-20 15:58:25 +020090 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +020091static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0);
92static atomic_t ap_poll_requests = ATOMIC_INIT(0);
93static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
94static struct task_struct *ap_poll_kthread = NULL;
95static DEFINE_MUTEX(ap_poll_thread_mutex);
Felix Beckcb17a632008-12-25 13:38:41 +010096static void *ap_interrupt_indicator;
Felix Beckfe137232008-07-14 09:59:08 +020097static struct hrtimer ap_poll_timer;
98/* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
99 * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
100static unsigned long long poll_timeout = 250000;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200101
102/**
Felix Beckcb17a632008-12-25 13:38:41 +0100103 * ap_using_interrupts() - Returns non-zero if interrupt support is
104 * available.
105 */
106static inline int ap_using_interrupts(void)
107{
108 return ap_interrupt_indicator != NULL;
109}
110
111/**
Felix Beck1749a812008-04-17 07:46:28 +0200112 * ap_intructions_available() - Test if AP instructions are available.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200113 *
Felix Beck1749a812008-04-17 07:46:28 +0200114 * Returns 0 if the AP instructions are installed.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200115 */
116static inline int ap_instructions_available(void)
117{
118 register unsigned long reg0 asm ("0") = AP_MKQID(0,0);
119 register unsigned long reg1 asm ("1") = -ENODEV;
120 register unsigned long reg2 asm ("2") = 0UL;
121
122 asm volatile(
123 " .long 0xb2af0000\n" /* PQAP(TAPQ) */
124 "0: la %1,0\n"
125 "1:\n"
126 EX_TABLE(0b, 1b)
127 : "+d" (reg0), "+d" (reg1), "+d" (reg2) : : "cc" );
128 return reg1;
129}
130
131/**
Felix Beckcb17a632008-12-25 13:38:41 +0100132 * ap_interrupts_available(): Test if AP interrupts are available.
133 *
134 * Returns 1 if AP interrupts are available.
135 */
136static int ap_interrupts_available(void)
137{
138 unsigned long long facility_bits[2];
139
140 if (stfle(facility_bits, 2) <= 1)
141 return 0;
142 if (!(facility_bits[0] & (1ULL << 61)) ||
143 !(facility_bits[1] & (1ULL << 62)))
144 return 0;
145 return 1;
146}
147
148/**
Felix Beck1749a812008-04-17 07:46:28 +0200149 * ap_test_queue(): Test adjunct processor queue.
150 * @qid: The AP queue number
151 * @queue_depth: Pointer to queue depth value
152 * @device_type: Pointer to device type value
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200153 *
Felix Beck1749a812008-04-17 07:46:28 +0200154 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200155 */
156static inline struct ap_queue_status
157ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
158{
159 register unsigned long reg0 asm ("0") = qid;
160 register struct ap_queue_status reg1 asm ("1");
161 register unsigned long reg2 asm ("2") = 0UL;
162
163 asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
164 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
165 *device_type = (int) (reg2 >> 24);
166 *queue_depth = (int) (reg2 & 0xff);
167 return reg1;
168}
169
170/**
Felix Beck1749a812008-04-17 07:46:28 +0200171 * ap_reset_queue(): Reset adjunct processor queue.
172 * @qid: The AP queue number
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200173 *
Felix Beck1749a812008-04-17 07:46:28 +0200174 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200175 */
176static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
177{
178 register unsigned long reg0 asm ("0") = qid | 0x01000000UL;
179 register struct ap_queue_status reg1 asm ("1");
180 register unsigned long reg2 asm ("2") = 0UL;
181
182 asm volatile(
183 ".long 0xb2af0000" /* PQAP(RAPQ) */
184 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
185 return reg1;
186}
187
Felix Beckcb17a632008-12-25 13:38:41 +0100188#ifdef CONFIG_64BIT
189/**
190 * ap_queue_interruption_control(): Enable interruption for a specific AP.
191 * @qid: The AP queue number
192 * @ind: The notification indicator byte
193 *
194 * Returns AP queue status.
195 */
196static inline struct ap_queue_status
197ap_queue_interruption_control(ap_qid_t qid, void *ind)
198{
199 register unsigned long reg0 asm ("0") = qid | 0x03000000UL;
200 register unsigned long reg1_in asm ("1") = 0x0000800000000000UL | AP_ISC;
201 register struct ap_queue_status reg1_out asm ("1");
202 register void *reg2 asm ("2") = ind;
203 asm volatile(
204 ".long 0xb2af0000" /* PQAP(RAPQ) */
205 : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
206 :
207 : "cc" );
208 return reg1_out;
209}
210#endif
211
212/**
213 * ap_queue_enable_interruption(): Enable interruption on an AP.
214 * @qid: The AP queue number
215 * @ind: the notification indicator byte
216 *
217 * Enables interruption on AP queue via ap_queue_interruption_control(). Based
218 * on the return value it waits a while and tests the AP queue if interrupts
219 * have been switched on using ap_test_queue().
220 */
221static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
222{
223#ifdef CONFIG_64BIT
224 struct ap_queue_status status;
225 int t_depth, t_device_type, rc, i;
226
227 rc = -EBUSY;
228 status = ap_queue_interruption_control(qid, ind);
229
230 for (i = 0; i < AP_MAX_RESET; i++) {
231 switch (status.response_code) {
232 case AP_RESPONSE_NORMAL:
233 if (status.int_enabled)
234 return 0;
235 break;
236 case AP_RESPONSE_RESET_IN_PROGRESS:
237 case AP_RESPONSE_BUSY:
238 break;
239 case AP_RESPONSE_Q_NOT_AVAIL:
240 case AP_RESPONSE_DECONFIGURED:
241 case AP_RESPONSE_CHECKSTOPPED:
242 case AP_RESPONSE_INVALID_ADDRESS:
243 return -ENODEV;
244 case AP_RESPONSE_OTHERWISE_CHANGED:
245 if (status.int_enabled)
246 return 0;
247 break;
248 default:
249 break;
250 }
251 if (i < AP_MAX_RESET - 1) {
252 udelay(5);
253 status = ap_test_queue(qid, &t_depth, &t_device_type);
254 }
255 }
256 return rc;
257#else
258 return -EINVAL;
259#endif
260}
261
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200262/**
Felix Beck1749a812008-04-17 07:46:28 +0200263 * __ap_send(): Send message to adjunct processor queue.
264 * @qid: The AP queue number
265 * @psmid: The program supplied message identifier
266 * @msg: The message text
267 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200268 *
Felix Beck1749a812008-04-17 07:46:28 +0200269 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200270 * Condition code 1 on NQAP can't happen because the L bit is 1.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200271 * Condition code 2 on NQAP also means the send is incomplete,
272 * because a segment boundary was reached. The NQAP is repeated.
273 */
274static inline struct ap_queue_status
275__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
276{
277 typedef struct { char _[length]; } msgblock;
278 register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
279 register struct ap_queue_status reg1 asm ("1");
280 register unsigned long reg2 asm ("2") = (unsigned long) msg;
281 register unsigned long reg3 asm ("3") = (unsigned long) length;
282 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
283 register unsigned long reg5 asm ("5") = (unsigned int) psmid;
284
285 asm volatile (
286 "0: .long 0xb2ad0042\n" /* DQAP */
287 " brc 2,0b"
288 : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
289 : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg)
290 : "cc" );
291 return reg1;
292}
293
294int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
295{
296 struct ap_queue_status status;
297
298 status = __ap_send(qid, psmid, msg, length);
299 switch (status.response_code) {
300 case AP_RESPONSE_NORMAL:
301 return 0;
302 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200303 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200304 return -EBUSY;
305 default: /* Device is gone. */
306 return -ENODEV;
307 }
308}
309EXPORT_SYMBOL(ap_send);
310
Felix Beck1749a812008-04-17 07:46:28 +0200311/**
312 * __ap_recv(): Receive message from adjunct processor queue.
313 * @qid: The AP queue number
314 * @psmid: Pointer to program supplied message identifier
315 * @msg: The message text
316 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200317 *
Felix Beck1749a812008-04-17 07:46:28 +0200318 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200319 * Condition code 1 on DQAP means the receive has taken place
320 * but only partially. The response is incomplete, hence the
321 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200322 * Condition code 2 on DQAP also means the receive is incomplete,
323 * this time because a segment boundary was reached. Again, the
324 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200325 * Note that gpr2 is used by the DQAP instruction to keep track of
326 * any 'residual' length, in case the instruction gets interrupted.
327 * Hence it gets zeroed before the instruction.
328 */
329static inline struct ap_queue_status
330__ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
331{
332 typedef struct { char _[length]; } msgblock;
333 register unsigned long reg0 asm("0") = qid | 0x80000000UL;
334 register struct ap_queue_status reg1 asm ("1");
335 register unsigned long reg2 asm("2") = 0UL;
336 register unsigned long reg4 asm("4") = (unsigned long) msg;
337 register unsigned long reg5 asm("5") = (unsigned long) length;
338 register unsigned long reg6 asm("6") = 0UL;
339 register unsigned long reg7 asm("7") = 0UL;
340
341
342 asm volatile(
343 "0: .long 0xb2ae0064\n"
344 " brc 6,0b\n"
345 : "+d" (reg0), "=d" (reg1), "+d" (reg2),
346 "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
347 "=m" (*(msgblock *) msg) : : "cc" );
348 *psmid = (((unsigned long long) reg6) << 32) + reg7;
349 return reg1;
350}
351
352int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
353{
354 struct ap_queue_status status;
355
356 status = __ap_recv(qid, psmid, msg, length);
357 switch (status.response_code) {
358 case AP_RESPONSE_NORMAL:
359 return 0;
360 case AP_RESPONSE_NO_PENDING_REPLY:
361 if (status.queue_empty)
362 return -ENOENT;
363 return -EBUSY;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200364 case AP_RESPONSE_RESET_IN_PROGRESS:
365 return -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200366 default:
367 return -ENODEV;
368 }
369}
370EXPORT_SYMBOL(ap_recv);
371
372/**
Felix Beck1749a812008-04-17 07:46:28 +0200373 * ap_query_queue(): Check if an AP queue is available.
374 * @qid: The AP queue number
375 * @queue_depth: Pointer to queue depth value
376 * @device_type: Pointer to device type value
377 *
378 * The test is repeated for AP_MAX_RESET times.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200379 */
380static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
381{
382 struct ap_queue_status status;
383 int t_depth, t_device_type, rc, i;
384
385 rc = -EBUSY;
386 for (i = 0; i < AP_MAX_RESET; i++) {
387 status = ap_test_queue(qid, &t_depth, &t_device_type);
388 switch (status.response_code) {
389 case AP_RESPONSE_NORMAL:
390 *queue_depth = t_depth + 1;
391 *device_type = t_device_type;
392 rc = 0;
393 break;
394 case AP_RESPONSE_Q_NOT_AVAIL:
395 rc = -ENODEV;
396 break;
397 case AP_RESPONSE_RESET_IN_PROGRESS:
398 break;
399 case AP_RESPONSE_DECONFIGURED:
400 rc = -ENODEV;
401 break;
402 case AP_RESPONSE_CHECKSTOPPED:
403 rc = -ENODEV;
404 break;
Felix Beckcb17a632008-12-25 13:38:41 +0100405 case AP_RESPONSE_INVALID_ADDRESS:
406 rc = -ENODEV;
407 break;
408 case AP_RESPONSE_OTHERWISE_CHANGED:
409 break;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200410 case AP_RESPONSE_BUSY:
411 break;
412 default:
413 BUG();
414 }
415 if (rc != -EBUSY)
416 break;
417 if (i < AP_MAX_RESET - 1)
418 udelay(5);
419 }
420 return rc;
421}
422
423/**
Felix Beck1749a812008-04-17 07:46:28 +0200424 * ap_init_queue(): Reset an AP queue.
425 * @qid: The AP queue number
426 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200427 * Reset an AP queue and wait for it to become available again.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200428 */
429static int ap_init_queue(ap_qid_t qid)
430{
431 struct ap_queue_status status;
432 int rc, dummy, i;
433
434 rc = -ENODEV;
435 status = ap_reset_queue(qid);
436 for (i = 0; i < AP_MAX_RESET; i++) {
437 switch (status.response_code) {
438 case AP_RESPONSE_NORMAL:
439 if (status.queue_empty)
440 rc = 0;
441 break;
442 case AP_RESPONSE_Q_NOT_AVAIL:
443 case AP_RESPONSE_DECONFIGURED:
444 case AP_RESPONSE_CHECKSTOPPED:
445 i = AP_MAX_RESET; /* return with -ENODEV */
446 break;
447 case AP_RESPONSE_RESET_IN_PROGRESS:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200448 rc = -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200449 case AP_RESPONSE_BUSY:
450 default:
451 break;
452 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200453 if (rc != -ENODEV && rc != -EBUSY)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200454 break;
455 if (i < AP_MAX_RESET - 1) {
456 udelay(5);
457 status = ap_test_queue(qid, &dummy, &dummy);
458 }
459 }
Felix Beckcb17a632008-12-25 13:38:41 +0100460 if (rc == 0 && ap_using_interrupts()) {
461 rc = ap_queue_enable_interruption(qid, ap_interrupt_indicator);
462 /* If interruption mode is supported by the machine,
463 * but an AP can not be enabled for interruption then
464 * the AP will be discarded. */
465 if (rc)
466 pr_err("Registering adapter interrupts for "
467 "AP %d failed\n", AP_QID_DEVICE(qid));
468 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200469 return rc;
470}
471
472/**
Felix Beck1749a812008-04-17 07:46:28 +0200473 * ap_increase_queue_count(): Arm request timeout.
474 * @ap_dev: Pointer to an AP device.
475 *
476 * Arm request timeout if an AP device was idle and a new request is submitted.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200477 */
478static void ap_increase_queue_count(struct ap_device *ap_dev)
479{
480 int timeout = ap_dev->drv->request_timeout;
481
482 ap_dev->queue_count++;
483 if (ap_dev->queue_count == 1) {
484 mod_timer(&ap_dev->timeout, jiffies + timeout);
485 ap_dev->reset = AP_RESET_ARMED;
486 }
487}
488
489/**
Felix Beck1749a812008-04-17 07:46:28 +0200490 * ap_decrease_queue_count(): Decrease queue count.
491 * @ap_dev: Pointer to an AP device.
492 *
493 * If AP device is still alive, re-schedule request timeout if there are still
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200494 * pending requests.
495 */
496static void ap_decrease_queue_count(struct ap_device *ap_dev)
497{
498 int timeout = ap_dev->drv->request_timeout;
499
500 ap_dev->queue_count--;
501 if (ap_dev->queue_count > 0)
502 mod_timer(&ap_dev->timeout, jiffies + timeout);
503 else
Felix Beck1749a812008-04-17 07:46:28 +0200504 /*
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200505 * The timeout timer should to be disabled now - since
506 * del_timer_sync() is very expensive, we just tell via the
507 * reset flag to ignore the pending timeout timer.
508 */
509 ap_dev->reset = AP_RESET_IGNORE;
510}
511
Felix Beck1749a812008-04-17 07:46:28 +0200512/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200513 * AP device related attributes.
514 */
515static ssize_t ap_hwtype_show(struct device *dev,
516 struct device_attribute *attr, char *buf)
517{
518 struct ap_device *ap_dev = to_ap_dev(dev);
519 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type);
520}
521static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL);
522
523static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr,
524 char *buf)
525{
526 struct ap_device *ap_dev = to_ap_dev(dev);
527 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth);
528}
529static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL);
530
531static ssize_t ap_request_count_show(struct device *dev,
532 struct device_attribute *attr,
533 char *buf)
534{
535 struct ap_device *ap_dev = to_ap_dev(dev);
536 int rc;
537
538 spin_lock_bh(&ap_dev->lock);
539 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->total_request_count);
540 spin_unlock_bh(&ap_dev->lock);
541 return rc;
542}
543
544static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL);
545
546static ssize_t ap_modalias_show(struct device *dev,
547 struct device_attribute *attr, char *buf)
548{
549 return sprintf(buf, "ap:t%02X", to_ap_dev(dev)->device_type);
550}
551
552static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL);
553
554static struct attribute *ap_dev_attrs[] = {
555 &dev_attr_hwtype.attr,
556 &dev_attr_depth.attr,
557 &dev_attr_request_count.attr,
558 &dev_attr_modalias.attr,
559 NULL
560};
561static struct attribute_group ap_dev_attr_group = {
562 .attrs = ap_dev_attrs
563};
564
565/**
Felix Beck1749a812008-04-17 07:46:28 +0200566 * ap_bus_match()
567 * @dev: Pointer to device
568 * @drv: Pointer to device_driver
569 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200570 * AP bus driver registration/unregistration.
571 */
572static int ap_bus_match(struct device *dev, struct device_driver *drv)
573{
574 struct ap_device *ap_dev = to_ap_dev(dev);
575 struct ap_driver *ap_drv = to_ap_drv(drv);
576 struct ap_device_id *id;
577
Felix Beck1749a812008-04-17 07:46:28 +0200578 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200579 * Compare device type of the device with the list of
580 * supported types of the device_driver.
581 */
582 for (id = ap_drv->ids; id->match_flags; id++) {
583 if ((id->match_flags & AP_DEVICE_ID_MATCH_DEVICE_TYPE) &&
584 (id->dev_type != ap_dev->device_type))
585 continue;
586 return 1;
587 }
588 return 0;
589}
590
591/**
Felix Beck1749a812008-04-17 07:46:28 +0200592 * ap_uevent(): Uevent function for AP devices.
593 * @dev: Pointer to device
594 * @env: Pointer to kobj_uevent_env
595 *
596 * It sets up a single environment variable DEV_TYPE which contains the
597 * hardware device type.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200598 */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200599static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200600{
601 struct ap_device *ap_dev = to_ap_dev(dev);
Kay Sievers7eff2e72007-08-14 15:15:12 +0200602 int retval = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200603
604 if (!ap_dev)
605 return -ENODEV;
606
607 /* Set up DEV_TYPE environment variable. */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200608 retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700609 if (retval)
610 return retval;
611
Cornelia Huck66a4263b2006-12-04 15:40:10 +0100612 /* Add MODALIAS= */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200613 retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700614
Eric Rannaudbf624562007-03-30 22:23:12 -0700615 return retval;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200616}
617
618static struct bus_type ap_bus_type = {
619 .name = "ap",
620 .match = &ap_bus_match,
621 .uevent = &ap_uevent,
622};
623
624static int ap_device_probe(struct device *dev)
625{
626 struct ap_device *ap_dev = to_ap_dev(dev);
627 struct ap_driver *ap_drv = to_ap_drv(dev->driver);
628 int rc;
629
630 ap_dev->drv = ap_drv;
631 rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100632 if (!rc) {
633 spin_lock_bh(&ap_device_lock);
634 list_add(&ap_dev->list, &ap_device_list);
635 spin_unlock_bh(&ap_device_lock);
636 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200637 return rc;
638}
639
640/**
Felix Beck1749a812008-04-17 07:46:28 +0200641 * __ap_flush_queue(): Flush requests.
642 * @ap_dev: Pointer to the AP device
643 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200644 * Flush all requests from the request/pending queue of an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200645 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100646static void __ap_flush_queue(struct ap_device *ap_dev)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200647{
648 struct ap_message *ap_msg, *next;
649
650 list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
651 list_del_init(&ap_msg->list);
652 ap_dev->pendingq_count--;
653 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
654 }
655 list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
656 list_del_init(&ap_msg->list);
657 ap_dev->requestq_count--;
658 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
659 }
660}
661
662void ap_flush_queue(struct ap_device *ap_dev)
663{
664 spin_lock_bh(&ap_dev->lock);
665 __ap_flush_queue(ap_dev);
666 spin_unlock_bh(&ap_dev->lock);
667}
668EXPORT_SYMBOL(ap_flush_queue);
669
670static int ap_device_remove(struct device *dev)
671{
672 struct ap_device *ap_dev = to_ap_dev(dev);
673 struct ap_driver *ap_drv = ap_dev->drv;
674
Ralph Wuerthner4e562962006-10-04 20:02:05 +0200675 ap_flush_queue(ap_dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200676 del_timer_sync(&ap_dev->timeout);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +0100677 spin_lock_bh(&ap_device_lock);
678 list_del_init(&ap_dev->list);
679 spin_unlock_bh(&ap_device_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100680 if (ap_drv->remove)
681 ap_drv->remove(ap_dev);
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +0200682 spin_lock_bh(&ap_dev->lock);
683 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
684 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200685 return 0;
686}
687
688int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
689 char *name)
690{
691 struct device_driver *drv = &ap_drv->driver;
692
693 drv->bus = &ap_bus_type;
694 drv->probe = ap_device_probe;
695 drv->remove = ap_device_remove;
696 drv->owner = owner;
697 drv->name = name;
698 return driver_register(drv);
699}
700EXPORT_SYMBOL(ap_driver_register);
701
702void ap_driver_unregister(struct ap_driver *ap_drv)
703{
704 driver_unregister(&ap_drv->driver);
705}
706EXPORT_SYMBOL(ap_driver_unregister);
707
Felix Beck1749a812008-04-17 07:46:28 +0200708/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200709 * AP bus attributes.
710 */
711static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
712{
713 return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
714}
715
716static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
717
718static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
719{
720 return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
721}
722
Felix Beckcb17a632008-12-25 13:38:41 +0100723static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
724{
725 return snprintf(buf, PAGE_SIZE, "%d\n",
726 ap_using_interrupts() ? 1 : 0);
727}
728
729static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL);
730
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200731static ssize_t ap_config_time_store(struct bus_type *bus,
732 const char *buf, size_t count)
733{
734 int time;
735
736 if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120)
737 return -EINVAL;
738 ap_config_time = time;
739 if (!timer_pending(&ap_config_timer) ||
740 !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) {
741 ap_config_timer.expires = jiffies + ap_config_time * HZ;
742 add_timer(&ap_config_timer);
743 }
744 return count;
745}
746
747static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store);
748
749static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf)
750{
751 return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
752}
753
754static ssize_t ap_poll_thread_store(struct bus_type *bus,
755 const char *buf, size_t count)
756{
757 int flag, rc;
758
759 if (sscanf(buf, "%d\n", &flag) != 1)
760 return -EINVAL;
761 if (flag) {
762 rc = ap_poll_thread_start();
763 if (rc)
764 return rc;
765 }
766 else
767 ap_poll_thread_stop();
768 return count;
769}
770
771static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
772
Felix Beckfe137232008-07-14 09:59:08 +0200773static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
774{
775 return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
776}
777
778static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
779 size_t count)
780{
781 unsigned long long time;
782 ktime_t hr_time;
783
784 /* 120 seconds = maximum poll interval */
Felix Beckcb17a632008-12-25 13:38:41 +0100785 if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 ||
786 time > 120000000000ULL)
Felix Beckfe137232008-07-14 09:59:08 +0200787 return -EINVAL;
788 poll_timeout = time;
789 hr_time = ktime_set(0, poll_timeout);
790
791 if (!hrtimer_is_queued(&ap_poll_timer) ||
Arjan van de Ven6c644ea2008-09-01 15:20:30 -0700792 !hrtimer_forward(&ap_poll_timer, hrtimer_get_expires(&ap_poll_timer), hr_time)) {
793 hrtimer_set_expires(&ap_poll_timer, hr_time);
794 hrtimer_start_expires(&ap_poll_timer, HRTIMER_MODE_ABS);
Felix Beckfe137232008-07-14 09:59:08 +0200795 }
796 return count;
797}
798
799static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
800
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200801static struct bus_attribute *const ap_bus_attrs[] = {
802 &bus_attr_ap_domain,
803 &bus_attr_config_time,
804 &bus_attr_poll_thread,
Felix Beckcb17a632008-12-25 13:38:41 +0100805 &bus_attr_ap_interrupts,
Felix Beckfe137232008-07-14 09:59:08 +0200806 &bus_attr_poll_timeout,
807 NULL,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200808};
809
810/**
Felix Beck1749a812008-04-17 07:46:28 +0200811 * ap_select_domain(): Select an AP domain.
812 *
813 * Pick one of the 16 AP domains.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200814 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100815static int ap_select_domain(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200816{
817 int queue_depth, device_type, count, max_count, best_domain;
818 int rc, i, j;
819
Felix Beck1749a812008-04-17 07:46:28 +0200820 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200821 * We want to use a single domain. Either the one specified with
822 * the "domain=" parameter or the domain with the maximum number
823 * of devices.
824 */
825 if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS)
826 /* Domain has already been selected. */
827 return 0;
828 best_domain = -1;
829 max_count = 0;
830 for (i = 0; i < AP_DOMAINS; i++) {
831 count = 0;
832 for (j = 0; j < AP_DEVICES; j++) {
833 ap_qid_t qid = AP_MKQID(j, i);
834 rc = ap_query_queue(qid, &queue_depth, &device_type);
835 if (rc)
836 continue;
837 count++;
838 }
839 if (count > max_count) {
840 max_count = count;
841 best_domain = i;
842 }
843 }
844 if (best_domain >= 0){
845 ap_domain_index = best_domain;
846 return 0;
847 }
848 return -ENODEV;
849}
850
851/**
Felix Beck1749a812008-04-17 07:46:28 +0200852 * ap_probe_device_type(): Find the device type of an AP.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200853 * @ap_dev: pointer to the AP device.
Felix Beck1749a812008-04-17 07:46:28 +0200854 *
855 * Find the device type if query queue returned a device type of 0.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200856 */
857static int ap_probe_device_type(struct ap_device *ap_dev)
858{
859 static unsigned char msg[] = {
860 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
861 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
862 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
863 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
864 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50,
865 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,
866 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00,
867 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,
868 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
869 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,
870 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
871 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,
872 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00,
873 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
874 0x00,0x00,0x00,0x00,0xb8,0x05,0x00,0x00,
875 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
876 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
877 0x00,0x00,0x00,0x00,0x00,0x00,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,0x0a,0x00,0x00,0x00,0x00,0x00,
882 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
883 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
884 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20,
885 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,
886 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22,
887 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
888 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
889 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,
890 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,
891 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,
892 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
893 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,
894 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00,
895 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,
896 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01,
897 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,
898 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68,
899 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,
900 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0,
901 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,
902 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04,
903 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,
904 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d,
905 };
906 struct ap_queue_status status;
907 unsigned long long psmid;
908 char *reply;
909 int rc, i;
910
911 reply = (void *) get_zeroed_page(GFP_KERNEL);
912 if (!reply) {
913 rc = -ENOMEM;
914 goto out;
915 }
916
917 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
918 msg, sizeof(msg));
919 if (status.response_code != AP_RESPONSE_NORMAL) {
920 rc = -ENODEV;
921 goto out_free;
922 }
923
924 /* Wait for the test message to complete. */
925 for (i = 0; i < 6; i++) {
926 mdelay(300);
927 status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
928 if (status.response_code == AP_RESPONSE_NORMAL &&
929 psmid == 0x0102030405060708ULL)
930 break;
931 }
932 if (i < 6) {
933 /* Got an answer. */
934 if (reply[0] == 0x00 && reply[1] == 0x86)
935 ap_dev->device_type = AP_DEVICE_TYPE_PCICC;
936 else
937 ap_dev->device_type = AP_DEVICE_TYPE_PCICA;
938 rc = 0;
939 } else
940 rc = -ENODEV;
941
942out_free:
943 free_page((unsigned long) reply);
944out:
945 return rc;
946}
947
Felix Beckcb17a632008-12-25 13:38:41 +0100948static void ap_interrupt_handler(void *unused1, void *unused2)
949{
950 tasklet_schedule(&ap_tasklet);
951}
952
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200953/**
Felix Beck1749a812008-04-17 07:46:28 +0200954 * __ap_scan_bus(): Scan the AP bus.
955 * @dev: Pointer to device
956 * @data: Pointer to data
957 *
958 * Scan the AP bus for new devices.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200959 */
960static int __ap_scan_bus(struct device *dev, void *data)
961{
962 return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data;
963}
964
965static void ap_device_release(struct device *dev)
966{
967 struct ap_device *ap_dev = to_ap_dev(dev);
968
969 kfree(ap_dev);
970}
971
Al Viro4927b3f2006-12-06 19:18:20 +0000972static void ap_scan_bus(struct work_struct *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200973{
974 struct ap_device *ap_dev;
975 struct device *dev;
976 ap_qid_t qid;
977 int queue_depth, device_type;
978 int rc, i;
979
980 if (ap_select_domain() != 0)
981 return;
982 for (i = 0; i < AP_DEVICES; i++) {
983 qid = AP_MKQID(i, ap_domain_index);
984 dev = bus_find_device(&ap_bus_type, NULL,
985 (void *)(unsigned long)qid,
986 __ap_scan_bus);
Ralph Wuerthnerf3b017d2006-10-27 12:39:26 +0200987 rc = ap_query_queue(qid, &queue_depth, &device_type);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +0200988 if (dev) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200989 if (rc == -EBUSY) {
990 set_current_state(TASK_UNINTERRUPTIBLE);
991 schedule_timeout(AP_RESET_TIMEOUT);
992 rc = ap_query_queue(qid, &queue_depth,
993 &device_type);
994 }
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +0200995 ap_dev = to_ap_dev(dev);
996 spin_lock_bh(&ap_dev->lock);
997 if (rc || ap_dev->unregistered) {
998 spin_unlock_bh(&ap_dev->lock);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +0200999 device_unregister(dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001000 put_device(dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001001 continue;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001002 }
1003 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001004 put_device(dev);
1005 continue;
1006 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001007 if (rc)
1008 continue;
1009 rc = ap_init_queue(qid);
1010 if (rc)
1011 continue;
1012 ap_dev = kzalloc(sizeof(*ap_dev), GFP_KERNEL);
1013 if (!ap_dev)
1014 break;
1015 ap_dev->qid = qid;
1016 ap_dev->queue_depth = queue_depth;
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001017 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001018 spin_lock_init(&ap_dev->lock);
1019 INIT_LIST_HEAD(&ap_dev->pendingq);
1020 INIT_LIST_HEAD(&ap_dev->requestq);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001021 INIT_LIST_HEAD(&ap_dev->list);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001022 setup_timer(&ap_dev->timeout, ap_request_timeout,
1023 (unsigned long) ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001024 if (device_type == 0)
1025 ap_probe_device_type(ap_dev);
1026 else
1027 ap_dev->device_type = device_type;
1028
1029 ap_dev->device.bus = &ap_bus_type;
1030 ap_dev->device.parent = ap_root_device;
Cornelia Huck1bf5b282008-10-10 21:33:10 +02001031 dev_set_name(&ap_dev->device, "card%02x",
1032 AP_QID_DEVICE(ap_dev->qid));
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001033 ap_dev->device.release = ap_device_release;
1034 rc = device_register(&ap_dev->device);
1035 if (rc) {
1036 kfree(ap_dev);
1037 continue;
1038 }
1039 /* Add device attributes. */
1040 rc = sysfs_create_group(&ap_dev->device.kobj,
1041 &ap_dev_attr_group);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001042 if (!rc) {
1043 spin_lock_bh(&ap_dev->lock);
1044 ap_dev->unregistered = 0;
1045 spin_unlock_bh(&ap_dev->lock);
1046 }
1047 else
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001048 device_unregister(&ap_dev->device);
1049 }
1050}
1051
1052static void
1053ap_config_timeout(unsigned long ptr)
1054{
1055 queue_work(ap_work_queue, &ap_config_work);
1056 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1057 add_timer(&ap_config_timer);
1058}
1059
1060/**
Felix Beck1749a812008-04-17 07:46:28 +02001061 * ap_schedule_poll_timer(): Schedule poll timer.
1062 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001063 * Set up the timer to run the poll tasklet
1064 */
1065static inline void ap_schedule_poll_timer(void)
1066{
Felix Beckcb17a632008-12-25 13:38:41 +01001067 if (ap_using_interrupts())
1068 return;
Felix Beckfe137232008-07-14 09:59:08 +02001069 if (hrtimer_is_queued(&ap_poll_timer))
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001070 return;
Felix Beckfe137232008-07-14 09:59:08 +02001071 hrtimer_start(&ap_poll_timer, ktime_set(0, poll_timeout),
1072 HRTIMER_MODE_ABS);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001073}
1074
1075/**
Felix Beck1749a812008-04-17 07:46:28 +02001076 * ap_poll_read(): Receive pending reply messages from an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001077 * @ap_dev: pointer to the AP device
1078 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1079 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001080 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001081 * Returns 0 if the device is still present, -ENODEV if not.
1082 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001083static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001084{
1085 struct ap_queue_status status;
1086 struct ap_message *ap_msg;
1087
1088 if (ap_dev->queue_count <= 0)
1089 return 0;
1090 status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
1091 ap_dev->reply->message, ap_dev->reply->length);
1092 switch (status.response_code) {
1093 case AP_RESPONSE_NORMAL:
1094 atomic_dec(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001095 ap_decrease_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001096 list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
1097 if (ap_msg->psmid != ap_dev->reply->psmid)
1098 continue;
1099 list_del_init(&ap_msg->list);
1100 ap_dev->pendingq_count--;
1101 ap_dev->drv->receive(ap_dev, ap_msg, ap_dev->reply);
1102 break;
1103 }
1104 if (ap_dev->queue_count > 0)
1105 *flags |= 1;
1106 break;
1107 case AP_RESPONSE_NO_PENDING_REPLY:
1108 if (status.queue_empty) {
1109 /* The card shouldn't forget requests but who knows. */
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +02001110 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001111 ap_dev->queue_count = 0;
1112 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1113 ap_dev->requestq_count += ap_dev->pendingq_count;
1114 ap_dev->pendingq_count = 0;
1115 } else
1116 *flags |= 2;
1117 break;
1118 default:
1119 return -ENODEV;
1120 }
1121 return 0;
1122}
1123
1124/**
Felix Beck1749a812008-04-17 07:46:28 +02001125 * ap_poll_write(): Send messages from the request queue to an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001126 * @ap_dev: pointer to the AP device
1127 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1128 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001129 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001130 * Returns 0 if the device is still present, -ENODEV if not.
1131 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001132static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001133{
1134 struct ap_queue_status status;
1135 struct ap_message *ap_msg;
1136
1137 if (ap_dev->requestq_count <= 0 ||
1138 ap_dev->queue_count >= ap_dev->queue_depth)
1139 return 0;
1140 /* Start the next request on the queue. */
1141 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
1142 status = __ap_send(ap_dev->qid, ap_msg->psmid,
1143 ap_msg->message, ap_msg->length);
1144 switch (status.response_code) {
1145 case AP_RESPONSE_NORMAL:
1146 atomic_inc(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001147 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001148 list_move_tail(&ap_msg->list, &ap_dev->pendingq);
1149 ap_dev->requestq_count--;
1150 ap_dev->pendingq_count++;
1151 if (ap_dev->queue_count < ap_dev->queue_depth &&
1152 ap_dev->requestq_count > 0)
1153 *flags |= 1;
1154 *flags |= 2;
1155 break;
1156 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001157 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001158 *flags |= 2;
1159 break;
1160 case AP_RESPONSE_MESSAGE_TOO_BIG:
1161 return -EINVAL;
1162 default:
1163 return -ENODEV;
1164 }
1165 return 0;
1166}
1167
1168/**
Felix Beck1749a812008-04-17 07:46:28 +02001169 * ap_poll_queue(): Poll AP device for pending replies and send new messages.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001170 * @ap_dev: pointer to the bus device
1171 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1172 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001173 *
1174 * Poll AP device for pending replies and send new messages. If either
1175 * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001176 * Returns 0.
1177 */
1178static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
1179{
1180 int rc;
1181
1182 rc = ap_poll_read(ap_dev, flags);
1183 if (rc)
1184 return rc;
1185 return ap_poll_write(ap_dev, flags);
1186}
1187
1188/**
Felix Beck1749a812008-04-17 07:46:28 +02001189 * __ap_queue_message(): Queue a message to a device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001190 * @ap_dev: pointer to the AP device
1191 * @ap_msg: the message to be queued
Felix Beck1749a812008-04-17 07:46:28 +02001192 *
1193 * Queue a message to a device. Returns 0 if successful.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001194 */
1195static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1196{
1197 struct ap_queue_status status;
1198
1199 if (list_empty(&ap_dev->requestq) &&
1200 ap_dev->queue_count < ap_dev->queue_depth) {
1201 status = __ap_send(ap_dev->qid, ap_msg->psmid,
1202 ap_msg->message, ap_msg->length);
1203 switch (status.response_code) {
1204 case AP_RESPONSE_NORMAL:
1205 list_add_tail(&ap_msg->list, &ap_dev->pendingq);
1206 atomic_inc(&ap_poll_requests);
1207 ap_dev->pendingq_count++;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001208 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001209 ap_dev->total_request_count++;
1210 break;
1211 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001212 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001213 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1214 ap_dev->requestq_count++;
1215 ap_dev->total_request_count++;
1216 return -EBUSY;
1217 case AP_RESPONSE_MESSAGE_TOO_BIG:
1218 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
1219 return -EINVAL;
1220 default: /* Device is gone. */
1221 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
1222 return -ENODEV;
1223 }
1224 } else {
1225 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1226 ap_dev->requestq_count++;
1227 ap_dev->total_request_count++;
1228 return -EBUSY;
1229 }
1230 ap_schedule_poll_timer();
1231 return 0;
1232}
1233
1234void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1235{
1236 unsigned long flags;
1237 int rc;
1238
1239 spin_lock_bh(&ap_dev->lock);
1240 if (!ap_dev->unregistered) {
1241 /* Make room on the queue by polling for finished requests. */
1242 rc = ap_poll_queue(ap_dev, &flags);
1243 if (!rc)
1244 rc = __ap_queue_message(ap_dev, ap_msg);
1245 if (!rc)
1246 wake_up(&ap_poll_wait);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001247 if (rc == -ENODEV)
1248 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001249 } else {
1250 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001251 rc = -ENODEV;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001252 }
1253 spin_unlock_bh(&ap_dev->lock);
1254 if (rc == -ENODEV)
1255 device_unregister(&ap_dev->device);
1256}
1257EXPORT_SYMBOL(ap_queue_message);
1258
1259/**
Felix Beck1749a812008-04-17 07:46:28 +02001260 * ap_cancel_message(): Cancel a crypto request.
1261 * @ap_dev: The AP device that has the message queued
1262 * @ap_msg: The message that is to be removed
1263 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001264 * Cancel a crypto request. This is done by removing the request
Felix Beck1749a812008-04-17 07:46:28 +02001265 * from the device pending or request queue. Note that the
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001266 * request stays on the AP queue. When it finishes the message
1267 * reply will be discarded because the psmid can't be found.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001268 */
1269void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1270{
1271 struct ap_message *tmp;
1272
1273 spin_lock_bh(&ap_dev->lock);
1274 if (!list_empty(&ap_msg->list)) {
1275 list_for_each_entry(tmp, &ap_dev->pendingq, list)
1276 if (tmp->psmid == ap_msg->psmid) {
1277 ap_dev->pendingq_count--;
1278 goto found;
1279 }
1280 ap_dev->requestq_count--;
1281 found:
1282 list_del_init(&ap_msg->list);
1283 }
1284 spin_unlock_bh(&ap_dev->lock);
1285}
1286EXPORT_SYMBOL(ap_cancel_message);
1287
1288/**
Felix Beck1749a812008-04-17 07:46:28 +02001289 * ap_poll_timeout(): AP receive polling for finished AP requests.
Felix Beckfe137232008-07-14 09:59:08 +02001290 * @unused: Unused pointer.
Felix Beck1749a812008-04-17 07:46:28 +02001291 *
Felix Beckfe137232008-07-14 09:59:08 +02001292 * Schedules the AP tasklet using a high resolution timer.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001293 */
Felix Beckfe137232008-07-14 09:59:08 +02001294static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001295{
1296 tasklet_schedule(&ap_tasklet);
Felix Beckfe137232008-07-14 09:59:08 +02001297 return HRTIMER_NORESTART;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001298}
1299
1300/**
Felix Beck1749a812008-04-17 07:46:28 +02001301 * ap_reset(): Reset a not responding AP device.
1302 * @ap_dev: Pointer to the AP device
1303 *
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001304 * Reset a not responding AP device and move all requests from the
1305 * pending queue to the request queue.
1306 */
1307static void ap_reset(struct ap_device *ap_dev)
1308{
1309 int rc;
1310
1311 ap_dev->reset = AP_RESET_IGNORE;
1312 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
1313 ap_dev->queue_count = 0;
1314 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1315 ap_dev->requestq_count += ap_dev->pendingq_count;
1316 ap_dev->pendingq_count = 0;
1317 rc = ap_init_queue(ap_dev->qid);
1318 if (rc == -ENODEV)
1319 ap_dev->unregistered = 1;
1320}
1321
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001322static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001323{
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001324 spin_lock(&ap_dev->lock);
1325 if (!ap_dev->unregistered) {
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001326 if (ap_poll_queue(ap_dev, flags))
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001327 ap_dev->unregistered = 1;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001328 if (ap_dev->reset == AP_RESET_DO)
1329 ap_reset(ap_dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001330 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001331 spin_unlock(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001332 return 0;
1333}
1334
Felix Beck1749a812008-04-17 07:46:28 +02001335/**
1336 * ap_poll_all(): Poll all AP devices.
1337 * @dummy: Unused variable
1338 *
1339 * Poll all AP devices on the bus in a round robin fashion. Continue
1340 * polling until bit 2^0 of the control flags is not set. If bit 2^1
1341 * of the control flags has been set arm the poll timer.
1342 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001343static void ap_poll_all(unsigned long dummy)
1344{
1345 unsigned long flags;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001346 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001347
Felix Beckcb17a632008-12-25 13:38:41 +01001348 /* Reset the indicator if interrupts are used. Thus new interrupts can
1349 * be received. Doing it in the beginning of the tasklet is therefor
1350 * important that no requests on any AP get lost.
1351 */
1352 if (ap_using_interrupts())
1353 xchg((u8 *)ap_interrupt_indicator, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001354 do {
1355 flags = 0;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001356 spin_lock(&ap_device_lock);
1357 list_for_each_entry(ap_dev, &ap_device_list, list) {
1358 __ap_poll_all(ap_dev, &flags);
1359 }
1360 spin_unlock(&ap_device_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001361 } while (flags & 1);
1362 if (flags & 2)
1363 ap_schedule_poll_timer();
1364}
1365
1366/**
Felix Beck1749a812008-04-17 07:46:28 +02001367 * ap_poll_thread(): Thread that polls for finished requests.
1368 * @data: Unused pointer
1369 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001370 * AP bus poll thread. The purpose of this thread is to poll for
1371 * finished requests in a loop if there is a "free" cpu - that is
1372 * a cpu that doesn't have anything better to do. The polling stops
1373 * as soon as there is another task or if all messages have been
1374 * delivered.
1375 */
1376static int ap_poll_thread(void *data)
1377{
1378 DECLARE_WAITQUEUE(wait, current);
1379 unsigned long flags;
1380 int requests;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001381 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001382
Christian Borntraegerd83682b2006-10-06 16:38:22 +02001383 set_user_nice(current, 19);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001384 while (1) {
1385 if (need_resched()) {
1386 schedule();
1387 continue;
1388 }
1389 add_wait_queue(&ap_poll_wait, &wait);
1390 set_current_state(TASK_INTERRUPTIBLE);
1391 if (kthread_should_stop())
1392 break;
1393 requests = atomic_read(&ap_poll_requests);
1394 if (requests <= 0)
1395 schedule();
1396 set_current_state(TASK_RUNNING);
1397 remove_wait_queue(&ap_poll_wait, &wait);
1398
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001399 flags = 0;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001400 spin_lock_bh(&ap_device_lock);
1401 list_for_each_entry(ap_dev, &ap_device_list, list) {
1402 __ap_poll_all(ap_dev, &flags);
1403 }
1404 spin_unlock_bh(&ap_device_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001405 }
1406 set_current_state(TASK_RUNNING);
1407 remove_wait_queue(&ap_poll_wait, &wait);
1408 return 0;
1409}
1410
1411static int ap_poll_thread_start(void)
1412{
1413 int rc;
1414
Felix Beckcb17a632008-12-25 13:38:41 +01001415 if (ap_using_interrupts())
1416 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001417 mutex_lock(&ap_poll_thread_mutex);
1418 if (!ap_poll_kthread) {
1419 ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
1420 rc = IS_ERR(ap_poll_kthread) ? PTR_ERR(ap_poll_kthread) : 0;
1421 if (rc)
1422 ap_poll_kthread = NULL;
1423 }
1424 else
1425 rc = 0;
1426 mutex_unlock(&ap_poll_thread_mutex);
1427 return rc;
1428}
1429
1430static void ap_poll_thread_stop(void)
1431{
1432 mutex_lock(&ap_poll_thread_mutex);
1433 if (ap_poll_kthread) {
1434 kthread_stop(ap_poll_kthread);
1435 ap_poll_kthread = NULL;
1436 }
1437 mutex_unlock(&ap_poll_thread_mutex);
1438}
1439
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001440/**
Felix Beck1749a812008-04-17 07:46:28 +02001441 * ap_request_timeout(): Handling of request timeouts
1442 * @data: Holds the AP device.
1443 *
1444 * Handles request timeouts.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001445 */
1446static void ap_request_timeout(unsigned long data)
1447{
1448 struct ap_device *ap_dev = (struct ap_device *) data;
1449
Felix Beckcb17a632008-12-25 13:38:41 +01001450 if (ap_dev->reset == AP_RESET_ARMED) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001451 ap_dev->reset = AP_RESET_DO;
Felix Beckcb17a632008-12-25 13:38:41 +01001452
1453 if (ap_using_interrupts())
1454 tasklet_schedule(&ap_tasklet);
1455 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001456}
1457
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001458static void ap_reset_domain(void)
1459{
1460 int i;
1461
Ralph Wuerthner39aa7cf2007-10-12 16:11:29 +02001462 if (ap_domain_index != -1)
1463 for (i = 0; i < AP_DEVICES; i++)
1464 ap_reset_queue(AP_MKQID(i, ap_domain_index));
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001465}
1466
1467static void ap_reset_all(void)
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001468{
1469 int i, j;
1470
1471 for (i = 0; i < AP_DOMAINS; i++)
1472 for (j = 0; j < AP_DEVICES; j++)
1473 ap_reset_queue(AP_MKQID(j, i));
1474}
1475
1476static struct reset_call ap_reset_call = {
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001477 .fn = ap_reset_all,
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001478};
1479
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001480/**
Felix Beck1749a812008-04-17 07:46:28 +02001481 * ap_module_init(): The module initialization code.
1482 *
1483 * Initializes the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001484 */
1485int __init ap_module_init(void)
1486{
1487 int rc, i;
1488
1489 if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) {
1490 printk(KERN_WARNING "Invalid param: domain = %d. "
1491 " Not loading.\n", ap_domain_index);
1492 return -EINVAL;
1493 }
1494 if (ap_instructions_available() != 0) {
1495 printk(KERN_WARNING "AP instructions not installed.\n");
1496 return -ENODEV;
1497 }
Felix Beckcb17a632008-12-25 13:38:41 +01001498 if (ap_interrupts_available()) {
1499 isc_register(AP_ISC);
1500 ap_interrupt_indicator = s390_register_adapter_interrupt(
1501 &ap_interrupt_handler, NULL, AP_ISC);
1502 if (IS_ERR(ap_interrupt_indicator)) {
1503 ap_interrupt_indicator = NULL;
1504 isc_unregister(AP_ISC);
1505 }
1506 }
1507
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001508 register_reset_call(&ap_reset_call);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001509
1510 /* Create /sys/bus/ap. */
1511 rc = bus_register(&ap_bus_type);
1512 if (rc)
1513 goto out;
1514 for (i = 0; ap_bus_attrs[i]; i++) {
1515 rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]);
1516 if (rc)
1517 goto out_bus;
1518 }
1519
1520 /* Create /sys/devices/ap. */
1521 ap_root_device = s390_root_dev_register("ap");
1522 rc = IS_ERR(ap_root_device) ? PTR_ERR(ap_root_device) : 0;
1523 if (rc)
1524 goto out_bus;
1525
1526 ap_work_queue = create_singlethread_workqueue("kapwork");
1527 if (!ap_work_queue) {
1528 rc = -ENOMEM;
1529 goto out_root;
1530 }
1531
1532 if (ap_select_domain() == 0)
1533 ap_scan_bus(NULL);
1534
Felix Beck1749a812008-04-17 07:46:28 +02001535 /* Setup the AP bus rescan timer. */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001536 init_timer(&ap_config_timer);
1537 ap_config_timer.function = ap_config_timeout;
1538 ap_config_timer.data = 0;
1539 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1540 add_timer(&ap_config_timer);
1541
Felix Beckfe137232008-07-14 09:59:08 +02001542 /* Setup the high resultion poll timer.
1543 * If we are running under z/VM adjust polling to z/VM polling rate.
1544 */
1545 if (MACHINE_IS_VM)
1546 poll_timeout = 1500000;
1547 hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1548 ap_poll_timer.function = ap_poll_timeout;
1549
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001550 /* Start the low priority AP bus poll thread. */
1551 if (ap_thread_flag) {
1552 rc = ap_poll_thread_start();
1553 if (rc)
1554 goto out_work;
1555 }
1556
1557 return 0;
1558
1559out_work:
1560 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001561 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001562 destroy_workqueue(ap_work_queue);
1563out_root:
1564 s390_root_dev_unregister(ap_root_device);
1565out_bus:
1566 while (i--)
1567 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1568 bus_unregister(&ap_bus_type);
1569out:
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001570 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001571 if (ap_using_interrupts()) {
1572 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1573 isc_unregister(AP_ISC);
1574 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001575 return rc;
1576}
1577
1578static int __ap_match_all(struct device *dev, void *data)
1579{
1580 return 1;
1581}
1582
1583/**
Felix Beck1749a812008-04-17 07:46:28 +02001584 * ap_modules_exit(): The module termination code
1585 *
1586 * Terminates the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001587 */
1588void ap_module_exit(void)
1589{
1590 int i;
1591 struct device *dev;
1592
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001593 ap_reset_domain();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001594 ap_poll_thread_stop();
1595 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001596 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001597 destroy_workqueue(ap_work_queue);
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001598 tasklet_kill(&ap_tasklet);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001599 s390_root_dev_unregister(ap_root_device);
1600 while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
1601 __ap_match_all)))
1602 {
1603 device_unregister(dev);
1604 put_device(dev);
1605 }
1606 for (i = 0; ap_bus_attrs[i]; i++)
1607 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1608 bus_unregister(&ap_bus_type);
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001609 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001610 if (ap_using_interrupts()) {
1611 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1612 isc_unregister(AP_ISC);
1613 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001614}
1615
1616#ifndef CONFIG_ZCRYPT_MONOLITHIC
1617module_init(ap_module_init);
1618module_exit(ap_module_exit);
1619#endif