blob: a1ba52a09602cc06355624ef671a7fdd9655133a [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>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090036#include <linux/slab.h>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020037#include <linux/notifier.h>
38#include <linux/kthread.h>
39#include <linux/mutex.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);
Felix Beck772f5472009-06-22 12:08:16 +020058static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags);
59static int ap_device_remove(struct device *dev);
60static int ap_device_probe(struct device *dev);
61static void ap_interrupt_handler(void *unused1, void *unused2);
62static void ap_reset(struct ap_device *ap_dev);
63static void ap_config_timeout(unsigned long ptr);
Felix Beck5314af62009-09-22 22:58:51 +020064static int ap_select_domain(void);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020065
Felix Beck1749a812008-04-17 07:46:28 +020066/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020067 * Module description.
68 */
69MODULE_AUTHOR("IBM Corporation");
70MODULE_DESCRIPTION("Adjunct Processor Bus driver, "
71 "Copyright 2006 IBM Corporation");
72MODULE_LICENSE("GPL");
73
Felix Beck1749a812008-04-17 07:46:28 +020074/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020075 * Module parameter
76 */
77int ap_domain_index = -1; /* Adjunct Processor Domain Index */
78module_param_named(domain, ap_domain_index, int, 0000);
79MODULE_PARM_DESC(domain, "domain index for ap devices");
80EXPORT_SYMBOL(ap_domain_index);
81
Felix Beckb90b34c2008-02-09 18:24:30 +010082static int ap_thread_flag = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +020083module_param_named(poll_thread, ap_thread_flag, int, 0000);
Felix Beckb90b34c2008-02-09 18:24:30 +010084MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off).");
Martin Schwidefsky1534c382006-09-20 15:58:25 +020085
86static struct device *ap_root_device = NULL;
Christian Maaser43c207e62008-12-25 13:38:42 +010087static DEFINE_SPINLOCK(ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +010088static LIST_HEAD(ap_device_list);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020089
Felix Beck1749a812008-04-17 07:46:28 +020090/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020091 * Workqueue & timer for bus rescan.
92 */
93static struct workqueue_struct *ap_work_queue;
94static struct timer_list ap_config_timer;
95static int ap_config_time = AP_CONFIG_TIME;
Al Viro4927b3f2006-12-06 19:18:20 +000096static DECLARE_WORK(ap_config_work, ap_scan_bus);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020097
Felix Beck1749a812008-04-17 07:46:28 +020098/*
Felix Beckcb17a632008-12-25 13:38:41 +010099 * Tasklet & timer for AP request polling and interrupts
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200100 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200101static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0);
102static atomic_t ap_poll_requests = ATOMIC_INIT(0);
103static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
104static struct task_struct *ap_poll_kthread = NULL;
105static DEFINE_MUTEX(ap_poll_thread_mutex);
Felix Beck93521312009-12-07 12:52:00 +0100106static DEFINE_SPINLOCK(ap_poll_timer_lock);
Felix Beckcb17a632008-12-25 13:38:41 +0100107static void *ap_interrupt_indicator;
Felix Beckfe137232008-07-14 09:59:08 +0200108static struct hrtimer ap_poll_timer;
109/* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
110 * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
111static unsigned long long poll_timeout = 250000;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200112
Felix Beck772f5472009-06-22 12:08:16 +0200113/* Suspend flag */
114static int ap_suspend_flag;
Felix Beck5314af62009-09-22 22:58:51 +0200115/* Flag to check if domain was set through module parameter domain=. This is
116 * important when supsend and resume is done in a z/VM environment where the
117 * domain might change. */
118static int user_set_domain = 0;
Felix Beck772f5472009-06-22 12:08:16 +0200119static struct bus_type ap_bus_type;
120
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200121/**
Felix Beckcb17a632008-12-25 13:38:41 +0100122 * ap_using_interrupts() - Returns non-zero if interrupt support is
123 * available.
124 */
125static inline int ap_using_interrupts(void)
126{
127 return ap_interrupt_indicator != NULL;
128}
129
130/**
Felix Beck1749a812008-04-17 07:46:28 +0200131 * ap_intructions_available() - Test if AP instructions are available.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200132 *
Felix Beck1749a812008-04-17 07:46:28 +0200133 * Returns 0 if the AP instructions are installed.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200134 */
135static inline int ap_instructions_available(void)
136{
137 register unsigned long reg0 asm ("0") = AP_MKQID(0,0);
138 register unsigned long reg1 asm ("1") = -ENODEV;
139 register unsigned long reg2 asm ("2") = 0UL;
140
141 asm volatile(
142 " .long 0xb2af0000\n" /* PQAP(TAPQ) */
143 "0: la %1,0\n"
144 "1:\n"
145 EX_TABLE(0b, 1b)
146 : "+d" (reg0), "+d" (reg1), "+d" (reg2) : : "cc" );
147 return reg1;
148}
149
150/**
Felix Beckcb17a632008-12-25 13:38:41 +0100151 * ap_interrupts_available(): Test if AP interrupts are available.
152 *
153 * Returns 1 if AP interrupts are available.
154 */
155static int ap_interrupts_available(void)
156{
Felix Beck53ec24b12011-01-05 12:46:44 +0100157 return test_facility(2) && test_facility(65);
Felix Beckcb17a632008-12-25 13:38:41 +0100158}
159
160/**
Felix Beck1749a812008-04-17 07:46:28 +0200161 * ap_test_queue(): Test adjunct processor queue.
162 * @qid: The AP queue number
163 * @queue_depth: Pointer to queue depth value
164 * @device_type: Pointer to device type value
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200165 *
Felix Beck1749a812008-04-17 07:46:28 +0200166 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200167 */
168static inline struct ap_queue_status
169ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
170{
171 register unsigned long reg0 asm ("0") = qid;
172 register struct ap_queue_status reg1 asm ("1");
173 register unsigned long reg2 asm ("2") = 0UL;
174
175 asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
176 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
177 *device_type = (int) (reg2 >> 24);
178 *queue_depth = (int) (reg2 & 0xff);
179 return reg1;
180}
181
182/**
Felix Beck1749a812008-04-17 07:46:28 +0200183 * ap_reset_queue(): Reset adjunct processor queue.
184 * @qid: The AP queue number
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200185 *
Felix Beck1749a812008-04-17 07:46:28 +0200186 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200187 */
188static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
189{
190 register unsigned long reg0 asm ("0") = qid | 0x01000000UL;
191 register struct ap_queue_status reg1 asm ("1");
192 register unsigned long reg2 asm ("2") = 0UL;
193
194 asm volatile(
195 ".long 0xb2af0000" /* PQAP(RAPQ) */
196 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
197 return reg1;
198}
199
Felix Beckcb17a632008-12-25 13:38:41 +0100200#ifdef CONFIG_64BIT
201/**
202 * ap_queue_interruption_control(): Enable interruption for a specific AP.
203 * @qid: The AP queue number
204 * @ind: The notification indicator byte
205 *
206 * Returns AP queue status.
207 */
208static inline struct ap_queue_status
209ap_queue_interruption_control(ap_qid_t qid, void *ind)
210{
211 register unsigned long reg0 asm ("0") = qid | 0x03000000UL;
212 register unsigned long reg1_in asm ("1") = 0x0000800000000000UL | AP_ISC;
213 register struct ap_queue_status reg1_out asm ("1");
214 register void *reg2 asm ("2") = ind;
215 asm volatile(
216 ".long 0xb2af0000" /* PQAP(RAPQ) */
217 : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
218 :
219 : "cc" );
220 return reg1_out;
221}
222#endif
223
224/**
225 * ap_queue_enable_interruption(): Enable interruption on an AP.
226 * @qid: The AP queue number
227 * @ind: the notification indicator byte
228 *
229 * Enables interruption on AP queue via ap_queue_interruption_control(). Based
230 * on the return value it waits a while and tests the AP queue if interrupts
231 * have been switched on using ap_test_queue().
232 */
233static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
234{
235#ifdef CONFIG_64BIT
236 struct ap_queue_status status;
237 int t_depth, t_device_type, rc, i;
238
239 rc = -EBUSY;
240 status = ap_queue_interruption_control(qid, ind);
241
242 for (i = 0; i < AP_MAX_RESET; i++) {
243 switch (status.response_code) {
244 case AP_RESPONSE_NORMAL:
245 if (status.int_enabled)
246 return 0;
247 break;
248 case AP_RESPONSE_RESET_IN_PROGRESS:
249 case AP_RESPONSE_BUSY:
250 break;
251 case AP_RESPONSE_Q_NOT_AVAIL:
252 case AP_RESPONSE_DECONFIGURED:
253 case AP_RESPONSE_CHECKSTOPPED:
254 case AP_RESPONSE_INVALID_ADDRESS:
255 return -ENODEV;
256 case AP_RESPONSE_OTHERWISE_CHANGED:
257 if (status.int_enabled)
258 return 0;
259 break;
260 default:
261 break;
262 }
263 if (i < AP_MAX_RESET - 1) {
264 udelay(5);
265 status = ap_test_queue(qid, &t_depth, &t_device_type);
266 }
267 }
268 return rc;
269#else
270 return -EINVAL;
271#endif
272}
273
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200274/**
Felix Beck1749a812008-04-17 07:46:28 +0200275 * __ap_send(): Send message to adjunct processor queue.
276 * @qid: The AP queue number
277 * @psmid: The program supplied message identifier
278 * @msg: The message text
279 * @length: The message length
Felix Becka6a5d732009-12-07 12:51:55 +0100280 * @special: Special Bit
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200281 *
Felix Beck1749a812008-04-17 07:46:28 +0200282 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200283 * Condition code 1 on NQAP can't happen because the L bit is 1.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200284 * Condition code 2 on NQAP also means the send is incomplete,
285 * because a segment boundary was reached. The NQAP is repeated.
286 */
287static inline struct ap_queue_status
Felix Becka6a5d732009-12-07 12:51:55 +0100288__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length,
289 unsigned int special)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200290{
291 typedef struct { char _[length]; } msgblock;
292 register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
293 register struct ap_queue_status reg1 asm ("1");
294 register unsigned long reg2 asm ("2") = (unsigned long) msg;
295 register unsigned long reg3 asm ("3") = (unsigned long) length;
296 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
297 register unsigned long reg5 asm ("5") = (unsigned int) psmid;
298
Felix Becka6a5d732009-12-07 12:51:55 +0100299 if (special == 1)
300 reg0 |= 0x400000UL;
301
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200302 asm volatile (
303 "0: .long 0xb2ad0042\n" /* DQAP */
304 " brc 2,0b"
305 : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
306 : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg)
307 : "cc" );
308 return reg1;
309}
310
311int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
312{
313 struct ap_queue_status status;
314
Felix Becka6a5d732009-12-07 12:51:55 +0100315 status = __ap_send(qid, psmid, msg, length, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200316 switch (status.response_code) {
317 case AP_RESPONSE_NORMAL:
318 return 0;
319 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200320 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200321 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +0100322 case AP_RESPONSE_REQ_FAC_NOT_INST:
323 return -EINVAL;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200324 default: /* Device is gone. */
325 return -ENODEV;
326 }
327}
328EXPORT_SYMBOL(ap_send);
329
Felix Beck1749a812008-04-17 07:46:28 +0200330/**
331 * __ap_recv(): Receive message from adjunct processor queue.
332 * @qid: The AP queue number
333 * @psmid: Pointer to program supplied message identifier
334 * @msg: The message text
335 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200336 *
Felix Beck1749a812008-04-17 07:46:28 +0200337 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200338 * Condition code 1 on DQAP means the receive has taken place
339 * but only partially. The response is incomplete, hence the
340 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200341 * Condition code 2 on DQAP also means the receive is incomplete,
342 * this time because a segment boundary was reached. Again, the
343 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200344 * Note that gpr2 is used by the DQAP instruction to keep track of
345 * any 'residual' length, in case the instruction gets interrupted.
346 * Hence it gets zeroed before the instruction.
347 */
348static inline struct ap_queue_status
349__ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
350{
351 typedef struct { char _[length]; } msgblock;
352 register unsigned long reg0 asm("0") = qid | 0x80000000UL;
353 register struct ap_queue_status reg1 asm ("1");
354 register unsigned long reg2 asm("2") = 0UL;
355 register unsigned long reg4 asm("4") = (unsigned long) msg;
356 register unsigned long reg5 asm("5") = (unsigned long) length;
357 register unsigned long reg6 asm("6") = 0UL;
358 register unsigned long reg7 asm("7") = 0UL;
359
360
361 asm volatile(
362 "0: .long 0xb2ae0064\n"
363 " brc 6,0b\n"
364 : "+d" (reg0), "=d" (reg1), "+d" (reg2),
365 "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
366 "=m" (*(msgblock *) msg) : : "cc" );
367 *psmid = (((unsigned long long) reg6) << 32) + reg7;
368 return reg1;
369}
370
371int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
372{
373 struct ap_queue_status status;
374
375 status = __ap_recv(qid, psmid, msg, length);
376 switch (status.response_code) {
377 case AP_RESPONSE_NORMAL:
378 return 0;
379 case AP_RESPONSE_NO_PENDING_REPLY:
380 if (status.queue_empty)
381 return -ENOENT;
382 return -EBUSY;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200383 case AP_RESPONSE_RESET_IN_PROGRESS:
384 return -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200385 default:
386 return -ENODEV;
387 }
388}
389EXPORT_SYMBOL(ap_recv);
390
391/**
Felix Beck1749a812008-04-17 07:46:28 +0200392 * ap_query_queue(): Check if an AP queue is available.
393 * @qid: The AP queue number
394 * @queue_depth: Pointer to queue depth value
395 * @device_type: Pointer to device type value
396 *
397 * The test is repeated for AP_MAX_RESET times.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200398 */
399static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
400{
401 struct ap_queue_status status;
402 int t_depth, t_device_type, rc, i;
403
404 rc = -EBUSY;
405 for (i = 0; i < AP_MAX_RESET; i++) {
406 status = ap_test_queue(qid, &t_depth, &t_device_type);
407 switch (status.response_code) {
408 case AP_RESPONSE_NORMAL:
409 *queue_depth = t_depth + 1;
410 *device_type = t_device_type;
411 rc = 0;
412 break;
413 case AP_RESPONSE_Q_NOT_AVAIL:
414 rc = -ENODEV;
415 break;
416 case AP_RESPONSE_RESET_IN_PROGRESS:
417 break;
418 case AP_RESPONSE_DECONFIGURED:
419 rc = -ENODEV;
420 break;
421 case AP_RESPONSE_CHECKSTOPPED:
422 rc = -ENODEV;
423 break;
Felix Beckcb17a632008-12-25 13:38:41 +0100424 case AP_RESPONSE_INVALID_ADDRESS:
425 rc = -ENODEV;
426 break;
427 case AP_RESPONSE_OTHERWISE_CHANGED:
428 break;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200429 case AP_RESPONSE_BUSY:
430 break;
431 default:
432 BUG();
433 }
434 if (rc != -EBUSY)
435 break;
436 if (i < AP_MAX_RESET - 1)
437 udelay(5);
438 }
439 return rc;
440}
441
442/**
Felix Beck1749a812008-04-17 07:46:28 +0200443 * ap_init_queue(): Reset an AP queue.
444 * @qid: The AP queue number
445 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200446 * Reset an AP queue and wait for it to become available again.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200447 */
448static int ap_init_queue(ap_qid_t qid)
449{
450 struct ap_queue_status status;
451 int rc, dummy, i;
452
453 rc = -ENODEV;
454 status = ap_reset_queue(qid);
455 for (i = 0; i < AP_MAX_RESET; i++) {
456 switch (status.response_code) {
457 case AP_RESPONSE_NORMAL:
458 if (status.queue_empty)
459 rc = 0;
460 break;
461 case AP_RESPONSE_Q_NOT_AVAIL:
462 case AP_RESPONSE_DECONFIGURED:
463 case AP_RESPONSE_CHECKSTOPPED:
464 i = AP_MAX_RESET; /* return with -ENODEV */
465 break;
466 case AP_RESPONSE_RESET_IN_PROGRESS:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200467 rc = -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200468 case AP_RESPONSE_BUSY:
469 default:
470 break;
471 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200472 if (rc != -ENODEV && rc != -EBUSY)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200473 break;
474 if (i < AP_MAX_RESET - 1) {
475 udelay(5);
476 status = ap_test_queue(qid, &dummy, &dummy);
477 }
478 }
Felix Beckcb17a632008-12-25 13:38:41 +0100479 if (rc == 0 && ap_using_interrupts()) {
480 rc = ap_queue_enable_interruption(qid, ap_interrupt_indicator);
481 /* If interruption mode is supported by the machine,
482 * but an AP can not be enabled for interruption then
483 * the AP will be discarded. */
484 if (rc)
485 pr_err("Registering adapter interrupts for "
486 "AP %d failed\n", AP_QID_DEVICE(qid));
487 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200488 return rc;
489}
490
491/**
Felix Beck1749a812008-04-17 07:46:28 +0200492 * ap_increase_queue_count(): Arm request timeout.
493 * @ap_dev: Pointer to an AP device.
494 *
495 * Arm request timeout if an AP device was idle and a new request is submitted.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200496 */
497static void ap_increase_queue_count(struct ap_device *ap_dev)
498{
499 int timeout = ap_dev->drv->request_timeout;
500
501 ap_dev->queue_count++;
502 if (ap_dev->queue_count == 1) {
503 mod_timer(&ap_dev->timeout, jiffies + timeout);
504 ap_dev->reset = AP_RESET_ARMED;
505 }
506}
507
508/**
Felix Beck1749a812008-04-17 07:46:28 +0200509 * ap_decrease_queue_count(): Decrease queue count.
510 * @ap_dev: Pointer to an AP device.
511 *
512 * If AP device is still alive, re-schedule request timeout if there are still
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200513 * pending requests.
514 */
515static void ap_decrease_queue_count(struct ap_device *ap_dev)
516{
517 int timeout = ap_dev->drv->request_timeout;
518
519 ap_dev->queue_count--;
520 if (ap_dev->queue_count > 0)
521 mod_timer(&ap_dev->timeout, jiffies + timeout);
522 else
Felix Beck1749a812008-04-17 07:46:28 +0200523 /*
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200524 * The timeout timer should to be disabled now - since
525 * del_timer_sync() is very expensive, we just tell via the
526 * reset flag to ignore the pending timeout timer.
527 */
528 ap_dev->reset = AP_RESET_IGNORE;
529}
530
Felix Beck1749a812008-04-17 07:46:28 +0200531/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200532 * AP device related attributes.
533 */
534static ssize_t ap_hwtype_show(struct device *dev,
535 struct device_attribute *attr, char *buf)
536{
537 struct ap_device *ap_dev = to_ap_dev(dev);
538 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type);
539}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200540
Christian Maaser43c207e62008-12-25 13:38:42 +0100541static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200542static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr,
543 char *buf)
544{
545 struct ap_device *ap_dev = to_ap_dev(dev);
546 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth);
547}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200548
Christian Maaser43c207e62008-12-25 13:38:42 +0100549static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200550static ssize_t ap_request_count_show(struct device *dev,
551 struct device_attribute *attr,
552 char *buf)
553{
554 struct ap_device *ap_dev = to_ap_dev(dev);
555 int rc;
556
557 spin_lock_bh(&ap_dev->lock);
558 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->total_request_count);
559 spin_unlock_bh(&ap_dev->lock);
560 return rc;
561}
562
563static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL);
564
565static ssize_t ap_modalias_show(struct device *dev,
566 struct device_attribute *attr, char *buf)
567{
568 return sprintf(buf, "ap:t%02X", to_ap_dev(dev)->device_type);
569}
570
571static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL);
572
573static struct attribute *ap_dev_attrs[] = {
574 &dev_attr_hwtype.attr,
575 &dev_attr_depth.attr,
576 &dev_attr_request_count.attr,
577 &dev_attr_modalias.attr,
578 NULL
579};
580static struct attribute_group ap_dev_attr_group = {
581 .attrs = ap_dev_attrs
582};
583
584/**
Felix Beck1749a812008-04-17 07:46:28 +0200585 * ap_bus_match()
586 * @dev: Pointer to device
587 * @drv: Pointer to device_driver
588 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200589 * AP bus driver registration/unregistration.
590 */
591static int ap_bus_match(struct device *dev, struct device_driver *drv)
592{
593 struct ap_device *ap_dev = to_ap_dev(dev);
594 struct ap_driver *ap_drv = to_ap_drv(drv);
595 struct ap_device_id *id;
596
Felix Beck1749a812008-04-17 07:46:28 +0200597 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200598 * Compare device type of the device with the list of
599 * supported types of the device_driver.
600 */
601 for (id = ap_drv->ids; id->match_flags; id++) {
602 if ((id->match_flags & AP_DEVICE_ID_MATCH_DEVICE_TYPE) &&
603 (id->dev_type != ap_dev->device_type))
604 continue;
605 return 1;
606 }
607 return 0;
608}
609
610/**
Felix Beck1749a812008-04-17 07:46:28 +0200611 * ap_uevent(): Uevent function for AP devices.
612 * @dev: Pointer to device
613 * @env: Pointer to kobj_uevent_env
614 *
615 * It sets up a single environment variable DEV_TYPE which contains the
616 * hardware device type.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200617 */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200618static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200619{
620 struct ap_device *ap_dev = to_ap_dev(dev);
Kay Sievers7eff2e72007-08-14 15:15:12 +0200621 int retval = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200622
623 if (!ap_dev)
624 return -ENODEV;
625
626 /* Set up DEV_TYPE environment variable. */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200627 retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700628 if (retval)
629 return retval;
630
Cornelia Huck66a4263b2006-12-04 15:40:10 +0100631 /* Add MODALIAS= */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200632 retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700633
Eric Rannaudbf624562007-03-30 22:23:12 -0700634 return retval;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200635}
636
Felix Beck772f5472009-06-22 12:08:16 +0200637static int ap_bus_suspend(struct device *dev, pm_message_t state)
638{
639 struct ap_device *ap_dev = to_ap_dev(dev);
640 unsigned long flags;
641
642 if (!ap_suspend_flag) {
643 ap_suspend_flag = 1;
644
645 /* Disable scanning for devices, thus we do not want to scan
646 * for them after removing.
647 */
648 del_timer_sync(&ap_config_timer);
649 if (ap_work_queue != NULL) {
650 destroy_workqueue(ap_work_queue);
651 ap_work_queue = NULL;
652 }
Felix Beck5314af62009-09-22 22:58:51 +0200653
Felix Beck772f5472009-06-22 12:08:16 +0200654 tasklet_disable(&ap_tasklet);
655 }
656 /* Poll on the device until all requests are finished. */
657 do {
658 flags = 0;
Felix Beck95f15562009-09-11 10:28:51 +0200659 spin_lock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200660 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +0200661 spin_unlock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200662 } while ((flags & 1) || (flags & 2));
663
Felix Beck5314af62009-09-22 22:58:51 +0200664 spin_lock_bh(&ap_dev->lock);
665 ap_dev->unregistered = 1;
666 spin_unlock_bh(&ap_dev->lock);
667
Felix Beck772f5472009-06-22 12:08:16 +0200668 return 0;
669}
670
671static int ap_bus_resume(struct device *dev)
672{
673 int rc = 0;
674 struct ap_device *ap_dev = to_ap_dev(dev);
675
676 if (ap_suspend_flag) {
677 ap_suspend_flag = 0;
678 if (!ap_interrupts_available())
679 ap_interrupt_indicator = NULL;
Felix Beck5314af62009-09-22 22:58:51 +0200680 if (!user_set_domain) {
681 ap_domain_index = -1;
682 ap_select_domain();
683 }
Felix Beck772f5472009-06-22 12:08:16 +0200684 init_timer(&ap_config_timer);
685 ap_config_timer.function = ap_config_timeout;
686 ap_config_timer.data = 0;
687 ap_config_timer.expires = jiffies + ap_config_time * HZ;
688 add_timer(&ap_config_timer);
689 ap_work_queue = create_singlethread_workqueue("kapwork");
690 if (!ap_work_queue)
691 return -ENOMEM;
692 tasklet_enable(&ap_tasklet);
693 if (!ap_using_interrupts())
694 ap_schedule_poll_timer();
695 else
696 tasklet_schedule(&ap_tasklet);
697 if (ap_thread_flag)
698 rc = ap_poll_thread_start();
Felix Beck772f5472009-06-22 12:08:16 +0200699 }
Felix Beck5314af62009-09-22 22:58:51 +0200700 if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) {
701 spin_lock_bh(&ap_dev->lock);
702 ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid),
703 ap_domain_index);
704 spin_unlock_bh(&ap_dev->lock);
705 }
706 queue_work(ap_work_queue, &ap_config_work);
Felix Beck772f5472009-06-22 12:08:16 +0200707
708 return rc;
709}
710
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200711static struct bus_type ap_bus_type = {
712 .name = "ap",
713 .match = &ap_bus_match,
714 .uevent = &ap_uevent,
Felix Beck772f5472009-06-22 12:08:16 +0200715 .suspend = ap_bus_suspend,
716 .resume = ap_bus_resume
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200717};
718
719static int ap_device_probe(struct device *dev)
720{
721 struct ap_device *ap_dev = to_ap_dev(dev);
722 struct ap_driver *ap_drv = to_ap_drv(dev->driver);
723 int rc;
724
725 ap_dev->drv = ap_drv;
726 rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100727 if (!rc) {
Christian Maaser43c207e62008-12-25 13:38:42 +0100728 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100729 list_add(&ap_dev->list, &ap_device_list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100730 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100731 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200732 return rc;
733}
734
735/**
Felix Beck1749a812008-04-17 07:46:28 +0200736 * __ap_flush_queue(): Flush requests.
737 * @ap_dev: Pointer to the AP device
738 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200739 * Flush all requests from the request/pending queue of an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200740 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100741static void __ap_flush_queue(struct ap_device *ap_dev)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200742{
743 struct ap_message *ap_msg, *next;
744
745 list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
746 list_del_init(&ap_msg->list);
747 ap_dev->pendingq_count--;
748 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
749 }
750 list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
751 list_del_init(&ap_msg->list);
752 ap_dev->requestq_count--;
753 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
754 }
755}
756
757void ap_flush_queue(struct ap_device *ap_dev)
758{
759 spin_lock_bh(&ap_dev->lock);
760 __ap_flush_queue(ap_dev);
761 spin_unlock_bh(&ap_dev->lock);
762}
763EXPORT_SYMBOL(ap_flush_queue);
764
765static int ap_device_remove(struct device *dev)
766{
767 struct ap_device *ap_dev = to_ap_dev(dev);
768 struct ap_driver *ap_drv = ap_dev->drv;
769
Ralph Wuerthner4e562962006-10-04 20:02:05 +0200770 ap_flush_queue(ap_dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200771 del_timer_sync(&ap_dev->timeout);
Christian Maaser43c207e62008-12-25 13:38:42 +0100772 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +0100773 list_del_init(&ap_dev->list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100774 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100775 if (ap_drv->remove)
776 ap_drv->remove(ap_dev);
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +0200777 spin_lock_bh(&ap_dev->lock);
778 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
779 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200780 return 0;
781}
782
783int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
784 char *name)
785{
786 struct device_driver *drv = &ap_drv->driver;
787
788 drv->bus = &ap_bus_type;
789 drv->probe = ap_device_probe;
790 drv->remove = ap_device_remove;
791 drv->owner = owner;
792 drv->name = name;
793 return driver_register(drv);
794}
795EXPORT_SYMBOL(ap_driver_register);
796
797void ap_driver_unregister(struct ap_driver *ap_drv)
798{
799 driver_unregister(&ap_drv->driver);
800}
801EXPORT_SYMBOL(ap_driver_unregister);
802
Felix Beck1749a812008-04-17 07:46:28 +0200803/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200804 * AP bus attributes.
805 */
806static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
807{
808 return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
809}
810
811static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
812
813static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
814{
815 return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
816}
817
Felix Beckcb17a632008-12-25 13:38:41 +0100818static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
819{
820 return snprintf(buf, PAGE_SIZE, "%d\n",
821 ap_using_interrupts() ? 1 : 0);
822}
823
824static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL);
825
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200826static ssize_t ap_config_time_store(struct bus_type *bus,
827 const char *buf, size_t count)
828{
829 int time;
830
831 if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120)
832 return -EINVAL;
833 ap_config_time = time;
834 if (!timer_pending(&ap_config_timer) ||
835 !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) {
836 ap_config_timer.expires = jiffies + ap_config_time * HZ;
837 add_timer(&ap_config_timer);
838 }
839 return count;
840}
841
842static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store);
843
844static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf)
845{
846 return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
847}
848
849static ssize_t ap_poll_thread_store(struct bus_type *bus,
850 const char *buf, size_t count)
851{
852 int flag, rc;
853
854 if (sscanf(buf, "%d\n", &flag) != 1)
855 return -EINVAL;
856 if (flag) {
857 rc = ap_poll_thread_start();
858 if (rc)
859 return rc;
860 }
861 else
862 ap_poll_thread_stop();
863 return count;
864}
865
866static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
867
Felix Beckfe137232008-07-14 09:59:08 +0200868static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
869{
870 return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
871}
872
873static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
874 size_t count)
875{
876 unsigned long long time;
877 ktime_t hr_time;
878
879 /* 120 seconds = maximum poll interval */
Felix Beckcb17a632008-12-25 13:38:41 +0100880 if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 ||
881 time > 120000000000ULL)
Felix Beckfe137232008-07-14 09:59:08 +0200882 return -EINVAL;
883 poll_timeout = time;
884 hr_time = ktime_set(0, poll_timeout);
885
886 if (!hrtimer_is_queued(&ap_poll_timer) ||
Arjan van de Ven6c644ea2008-09-01 15:20:30 -0700887 !hrtimer_forward(&ap_poll_timer, hrtimer_get_expires(&ap_poll_timer), hr_time)) {
888 hrtimer_set_expires(&ap_poll_timer, hr_time);
889 hrtimer_start_expires(&ap_poll_timer, HRTIMER_MODE_ABS);
Felix Beckfe137232008-07-14 09:59:08 +0200890 }
891 return count;
892}
893
894static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
895
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200896static struct bus_attribute *const ap_bus_attrs[] = {
897 &bus_attr_ap_domain,
898 &bus_attr_config_time,
899 &bus_attr_poll_thread,
Felix Beckcb17a632008-12-25 13:38:41 +0100900 &bus_attr_ap_interrupts,
Felix Beckfe137232008-07-14 09:59:08 +0200901 &bus_attr_poll_timeout,
902 NULL,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200903};
904
905/**
Felix Beck1749a812008-04-17 07:46:28 +0200906 * ap_select_domain(): Select an AP domain.
907 *
908 * Pick one of the 16 AP domains.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200909 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100910static int ap_select_domain(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200911{
912 int queue_depth, device_type, count, max_count, best_domain;
913 int rc, i, j;
914
Felix Beck1749a812008-04-17 07:46:28 +0200915 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200916 * We want to use a single domain. Either the one specified with
917 * the "domain=" parameter or the domain with the maximum number
918 * of devices.
919 */
920 if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS)
921 /* Domain has already been selected. */
922 return 0;
923 best_domain = -1;
924 max_count = 0;
925 for (i = 0; i < AP_DOMAINS; i++) {
926 count = 0;
927 for (j = 0; j < AP_DEVICES; j++) {
928 ap_qid_t qid = AP_MKQID(j, i);
929 rc = ap_query_queue(qid, &queue_depth, &device_type);
930 if (rc)
931 continue;
932 count++;
933 }
934 if (count > max_count) {
935 max_count = count;
936 best_domain = i;
937 }
938 }
939 if (best_domain >= 0){
940 ap_domain_index = best_domain;
941 return 0;
942 }
943 return -ENODEV;
944}
945
946/**
Felix Beck1749a812008-04-17 07:46:28 +0200947 * ap_probe_device_type(): Find the device type of an AP.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200948 * @ap_dev: pointer to the AP device.
Felix Beck1749a812008-04-17 07:46:28 +0200949 *
950 * Find the device type if query queue returned a device type of 0.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200951 */
952static int ap_probe_device_type(struct ap_device *ap_dev)
953{
954 static unsigned char msg[] = {
955 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
956 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
957 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
958 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
959 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50,
960 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,
961 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00,
962 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,
963 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
964 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,
965 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
966 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,
967 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00,
968 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
969 0x00,0x00,0x00,0x00,0xb8,0x05,0x00,0x00,
970 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
971 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
972 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
973 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
974 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
975 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
976 0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,
977 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
978 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
979 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20,
980 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,
981 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22,
982 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
983 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
984 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,
985 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,
986 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,
987 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
988 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,
989 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00,
990 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,
991 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01,
992 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,
993 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68,
994 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,
995 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0,
996 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,
997 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04,
998 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,
999 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d,
1000 };
1001 struct ap_queue_status status;
1002 unsigned long long psmid;
1003 char *reply;
1004 int rc, i;
1005
1006 reply = (void *) get_zeroed_page(GFP_KERNEL);
1007 if (!reply) {
1008 rc = -ENOMEM;
1009 goto out;
1010 }
1011
1012 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
Felix Becka6a5d732009-12-07 12:51:55 +01001013 msg, sizeof(msg), 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001014 if (status.response_code != AP_RESPONSE_NORMAL) {
1015 rc = -ENODEV;
1016 goto out_free;
1017 }
1018
1019 /* Wait for the test message to complete. */
1020 for (i = 0; i < 6; i++) {
1021 mdelay(300);
1022 status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
1023 if (status.response_code == AP_RESPONSE_NORMAL &&
1024 psmid == 0x0102030405060708ULL)
1025 break;
1026 }
1027 if (i < 6) {
1028 /* Got an answer. */
1029 if (reply[0] == 0x00 && reply[1] == 0x86)
1030 ap_dev->device_type = AP_DEVICE_TYPE_PCICC;
1031 else
1032 ap_dev->device_type = AP_DEVICE_TYPE_PCICA;
1033 rc = 0;
1034 } else
1035 rc = -ENODEV;
1036
1037out_free:
1038 free_page((unsigned long) reply);
1039out:
1040 return rc;
1041}
1042
Felix Beckcb17a632008-12-25 13:38:41 +01001043static void ap_interrupt_handler(void *unused1, void *unused2)
1044{
1045 tasklet_schedule(&ap_tasklet);
1046}
1047
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001048/**
Felix Beck1749a812008-04-17 07:46:28 +02001049 * __ap_scan_bus(): Scan the AP bus.
1050 * @dev: Pointer to device
1051 * @data: Pointer to data
1052 *
1053 * Scan the AP bus for new devices.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001054 */
1055static int __ap_scan_bus(struct device *dev, void *data)
1056{
1057 return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data;
1058}
1059
1060static void ap_device_release(struct device *dev)
1061{
1062 struct ap_device *ap_dev = to_ap_dev(dev);
1063
1064 kfree(ap_dev);
1065}
1066
Al Viro4927b3f2006-12-06 19:18:20 +00001067static void ap_scan_bus(struct work_struct *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001068{
1069 struct ap_device *ap_dev;
1070 struct device *dev;
1071 ap_qid_t qid;
1072 int queue_depth, device_type;
1073 int rc, i;
1074
1075 if (ap_select_domain() != 0)
1076 return;
1077 for (i = 0; i < AP_DEVICES; i++) {
1078 qid = AP_MKQID(i, ap_domain_index);
1079 dev = bus_find_device(&ap_bus_type, NULL,
1080 (void *)(unsigned long)qid,
1081 __ap_scan_bus);
Ralph Wuerthnerf3b017d2006-10-27 12:39:26 +02001082 rc = ap_query_queue(qid, &queue_depth, &device_type);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001083 if (dev) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001084 if (rc == -EBUSY) {
1085 set_current_state(TASK_UNINTERRUPTIBLE);
1086 schedule_timeout(AP_RESET_TIMEOUT);
1087 rc = ap_query_queue(qid, &queue_depth,
1088 &device_type);
1089 }
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001090 ap_dev = to_ap_dev(dev);
1091 spin_lock_bh(&ap_dev->lock);
1092 if (rc || ap_dev->unregistered) {
1093 spin_unlock_bh(&ap_dev->lock);
Felix Beck5314af62009-09-22 22:58:51 +02001094 if (ap_dev->unregistered)
1095 i--;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001096 device_unregister(dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001097 put_device(dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001098 continue;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001099 }
1100 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001101 put_device(dev);
1102 continue;
1103 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001104 if (rc)
1105 continue;
1106 rc = ap_init_queue(qid);
1107 if (rc)
1108 continue;
1109 ap_dev = kzalloc(sizeof(*ap_dev), GFP_KERNEL);
1110 if (!ap_dev)
1111 break;
1112 ap_dev->qid = qid;
1113 ap_dev->queue_depth = queue_depth;
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001114 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001115 spin_lock_init(&ap_dev->lock);
1116 INIT_LIST_HEAD(&ap_dev->pendingq);
1117 INIT_LIST_HEAD(&ap_dev->requestq);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001118 INIT_LIST_HEAD(&ap_dev->list);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001119 setup_timer(&ap_dev->timeout, ap_request_timeout,
1120 (unsigned long) ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001121 if (device_type == 0)
1122 ap_probe_device_type(ap_dev);
1123 else
1124 ap_dev->device_type = device_type;
1125
1126 ap_dev->device.bus = &ap_bus_type;
1127 ap_dev->device.parent = ap_root_device;
Felix Beckedc44fa2009-09-11 10:28:52 +02001128 if (dev_set_name(&ap_dev->device, "card%02x",
1129 AP_QID_DEVICE(ap_dev->qid))) {
1130 kfree(ap_dev);
1131 continue;
1132 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001133 ap_dev->device.release = ap_device_release;
1134 rc = device_register(&ap_dev->device);
1135 if (rc) {
Sebastian Ottc6304932009-09-11 10:28:38 +02001136 put_device(&ap_dev->device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001137 continue;
1138 }
1139 /* Add device attributes. */
1140 rc = sysfs_create_group(&ap_dev->device.kobj,
1141 &ap_dev_attr_group);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001142 if (!rc) {
1143 spin_lock_bh(&ap_dev->lock);
1144 ap_dev->unregistered = 0;
1145 spin_unlock_bh(&ap_dev->lock);
1146 }
1147 else
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001148 device_unregister(&ap_dev->device);
1149 }
1150}
1151
1152static void
1153ap_config_timeout(unsigned long ptr)
1154{
1155 queue_work(ap_work_queue, &ap_config_work);
1156 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1157 add_timer(&ap_config_timer);
1158}
1159
1160/**
Felix Beck1749a812008-04-17 07:46:28 +02001161 * ap_schedule_poll_timer(): Schedule poll timer.
1162 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001163 * Set up the timer to run the poll tasklet
1164 */
1165static inline void ap_schedule_poll_timer(void)
1166{
Felix Beck8d406c62009-07-24 12:39:53 +02001167 ktime_t hr_time;
Felix Beck93521312009-12-07 12:52:00 +01001168
1169 spin_lock_bh(&ap_poll_timer_lock);
Felix Beck772f5472009-06-22 12:08:16 +02001170 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beck93521312009-12-07 12:52:00 +01001171 goto out;
Felix Beckfe137232008-07-14 09:59:08 +02001172 if (hrtimer_is_queued(&ap_poll_timer))
Felix Beck93521312009-12-07 12:52:00 +01001173 goto out;
Felix Beck8d406c62009-07-24 12:39:53 +02001174 if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
1175 hr_time = ktime_set(0, poll_timeout);
1176 hrtimer_forward_now(&ap_poll_timer, hr_time);
1177 hrtimer_restart(&ap_poll_timer);
1178 }
Felix Beck93521312009-12-07 12:52:00 +01001179out:
1180 spin_unlock_bh(&ap_poll_timer_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001181}
1182
1183/**
Felix Beck1749a812008-04-17 07:46:28 +02001184 * ap_poll_read(): Receive pending reply messages from an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001185 * @ap_dev: pointer to the AP device
1186 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1187 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001188 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001189 * Returns 0 if the device is still present, -ENODEV if not.
1190 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001191static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001192{
1193 struct ap_queue_status status;
1194 struct ap_message *ap_msg;
1195
1196 if (ap_dev->queue_count <= 0)
1197 return 0;
1198 status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
1199 ap_dev->reply->message, ap_dev->reply->length);
1200 switch (status.response_code) {
1201 case AP_RESPONSE_NORMAL:
1202 atomic_dec(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001203 ap_decrease_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001204 list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
1205 if (ap_msg->psmid != ap_dev->reply->psmid)
1206 continue;
1207 list_del_init(&ap_msg->list);
1208 ap_dev->pendingq_count--;
1209 ap_dev->drv->receive(ap_dev, ap_msg, ap_dev->reply);
1210 break;
1211 }
1212 if (ap_dev->queue_count > 0)
1213 *flags |= 1;
1214 break;
1215 case AP_RESPONSE_NO_PENDING_REPLY:
1216 if (status.queue_empty) {
1217 /* The card shouldn't forget requests but who knows. */
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +02001218 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001219 ap_dev->queue_count = 0;
1220 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1221 ap_dev->requestq_count += ap_dev->pendingq_count;
1222 ap_dev->pendingq_count = 0;
1223 } else
1224 *flags |= 2;
1225 break;
1226 default:
1227 return -ENODEV;
1228 }
1229 return 0;
1230}
1231
1232/**
Felix Beck1749a812008-04-17 07:46:28 +02001233 * ap_poll_write(): Send messages from the request queue to an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001234 * @ap_dev: pointer to the AP device
1235 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1236 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001237 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001238 * Returns 0 if the device is still present, -ENODEV if not.
1239 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001240static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001241{
1242 struct ap_queue_status status;
1243 struct ap_message *ap_msg;
1244
1245 if (ap_dev->requestq_count <= 0 ||
1246 ap_dev->queue_count >= ap_dev->queue_depth)
1247 return 0;
1248 /* Start the next request on the queue. */
1249 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
1250 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001251 ap_msg->message, ap_msg->length, ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001252 switch (status.response_code) {
1253 case AP_RESPONSE_NORMAL:
1254 atomic_inc(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001255 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001256 list_move_tail(&ap_msg->list, &ap_dev->pendingq);
1257 ap_dev->requestq_count--;
1258 ap_dev->pendingq_count++;
1259 if (ap_dev->queue_count < ap_dev->queue_depth &&
1260 ap_dev->requestq_count > 0)
1261 *flags |= 1;
1262 *flags |= 2;
1263 break;
1264 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001265 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001266 *flags |= 2;
1267 break;
1268 case AP_RESPONSE_MESSAGE_TOO_BIG:
Felix Becka6a5d732009-12-07 12:51:55 +01001269 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001270 return -EINVAL;
1271 default:
1272 return -ENODEV;
1273 }
1274 return 0;
1275}
1276
1277/**
Felix Beck1749a812008-04-17 07:46:28 +02001278 * ap_poll_queue(): Poll AP device for pending replies and send new messages.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001279 * @ap_dev: pointer to the bus device
1280 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1281 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001282 *
1283 * Poll AP device for pending replies and send new messages. If either
1284 * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001285 * Returns 0.
1286 */
1287static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
1288{
1289 int rc;
1290
1291 rc = ap_poll_read(ap_dev, flags);
1292 if (rc)
1293 return rc;
1294 return ap_poll_write(ap_dev, flags);
1295}
1296
1297/**
Felix Beck1749a812008-04-17 07:46:28 +02001298 * __ap_queue_message(): Queue a message to a device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001299 * @ap_dev: pointer to the AP device
1300 * @ap_msg: the message to be queued
Felix Beck1749a812008-04-17 07:46:28 +02001301 *
1302 * Queue a message to a device. Returns 0 if successful.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001303 */
1304static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1305{
1306 struct ap_queue_status status;
1307
1308 if (list_empty(&ap_dev->requestq) &&
1309 ap_dev->queue_count < ap_dev->queue_depth) {
1310 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001311 ap_msg->message, ap_msg->length,
1312 ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001313 switch (status.response_code) {
1314 case AP_RESPONSE_NORMAL:
1315 list_add_tail(&ap_msg->list, &ap_dev->pendingq);
1316 atomic_inc(&ap_poll_requests);
1317 ap_dev->pendingq_count++;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001318 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001319 ap_dev->total_request_count++;
1320 break;
1321 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001322 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001323 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1324 ap_dev->requestq_count++;
1325 ap_dev->total_request_count++;
1326 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +01001327 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001328 case AP_RESPONSE_MESSAGE_TOO_BIG:
1329 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
1330 return -EINVAL;
1331 default: /* Device is gone. */
1332 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
1333 return -ENODEV;
1334 }
1335 } else {
1336 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1337 ap_dev->requestq_count++;
1338 ap_dev->total_request_count++;
1339 return -EBUSY;
1340 }
1341 ap_schedule_poll_timer();
1342 return 0;
1343}
1344
1345void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1346{
1347 unsigned long flags;
1348 int rc;
1349
1350 spin_lock_bh(&ap_dev->lock);
1351 if (!ap_dev->unregistered) {
1352 /* Make room on the queue by polling for finished requests. */
1353 rc = ap_poll_queue(ap_dev, &flags);
1354 if (!rc)
1355 rc = __ap_queue_message(ap_dev, ap_msg);
1356 if (!rc)
1357 wake_up(&ap_poll_wait);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001358 if (rc == -ENODEV)
1359 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001360 } else {
1361 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001362 rc = -ENODEV;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001363 }
1364 spin_unlock_bh(&ap_dev->lock);
1365 if (rc == -ENODEV)
1366 device_unregister(&ap_dev->device);
1367}
1368EXPORT_SYMBOL(ap_queue_message);
1369
1370/**
Felix Beck1749a812008-04-17 07:46:28 +02001371 * ap_cancel_message(): Cancel a crypto request.
1372 * @ap_dev: The AP device that has the message queued
1373 * @ap_msg: The message that is to be removed
1374 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001375 * Cancel a crypto request. This is done by removing the request
Felix Beck1749a812008-04-17 07:46:28 +02001376 * from the device pending or request queue. Note that the
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001377 * request stays on the AP queue. When it finishes the message
1378 * reply will be discarded because the psmid can't be found.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001379 */
1380void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1381{
1382 struct ap_message *tmp;
1383
1384 spin_lock_bh(&ap_dev->lock);
1385 if (!list_empty(&ap_msg->list)) {
1386 list_for_each_entry(tmp, &ap_dev->pendingq, list)
1387 if (tmp->psmid == ap_msg->psmid) {
1388 ap_dev->pendingq_count--;
1389 goto found;
1390 }
1391 ap_dev->requestq_count--;
1392 found:
1393 list_del_init(&ap_msg->list);
1394 }
1395 spin_unlock_bh(&ap_dev->lock);
1396}
1397EXPORT_SYMBOL(ap_cancel_message);
1398
1399/**
Felix Beck1749a812008-04-17 07:46:28 +02001400 * ap_poll_timeout(): AP receive polling for finished AP requests.
Felix Beckfe137232008-07-14 09:59:08 +02001401 * @unused: Unused pointer.
Felix Beck1749a812008-04-17 07:46:28 +02001402 *
Felix Beckfe137232008-07-14 09:59:08 +02001403 * Schedules the AP tasklet using a high resolution timer.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001404 */
Felix Beckfe137232008-07-14 09:59:08 +02001405static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001406{
1407 tasklet_schedule(&ap_tasklet);
Felix Beckfe137232008-07-14 09:59:08 +02001408 return HRTIMER_NORESTART;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001409}
1410
1411/**
Felix Beck1749a812008-04-17 07:46:28 +02001412 * ap_reset(): Reset a not responding AP device.
1413 * @ap_dev: Pointer to the AP device
1414 *
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001415 * Reset a not responding AP device and move all requests from the
1416 * pending queue to the request queue.
1417 */
1418static void ap_reset(struct ap_device *ap_dev)
1419{
1420 int rc;
1421
1422 ap_dev->reset = AP_RESET_IGNORE;
1423 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
1424 ap_dev->queue_count = 0;
1425 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1426 ap_dev->requestq_count += ap_dev->pendingq_count;
1427 ap_dev->pendingq_count = 0;
1428 rc = ap_init_queue(ap_dev->qid);
1429 if (rc == -ENODEV)
1430 ap_dev->unregistered = 1;
1431}
1432
Christian Maaser43c207e62008-12-25 13:38:42 +01001433static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001434{
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001435 if (!ap_dev->unregistered) {
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001436 if (ap_poll_queue(ap_dev, flags))
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001437 ap_dev->unregistered = 1;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001438 if (ap_dev->reset == AP_RESET_DO)
1439 ap_reset(ap_dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001440 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001441 return 0;
1442}
1443
Felix Beck1749a812008-04-17 07:46:28 +02001444/**
1445 * ap_poll_all(): Poll all AP devices.
1446 * @dummy: Unused variable
1447 *
1448 * Poll all AP devices on the bus in a round robin fashion. Continue
1449 * polling until bit 2^0 of the control flags is not set. If bit 2^1
1450 * of the control flags has been set arm the poll timer.
1451 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001452static void ap_poll_all(unsigned long dummy)
1453{
1454 unsigned long flags;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001455 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001456
Felix Beckcb17a632008-12-25 13:38:41 +01001457 /* Reset the indicator if interrupts are used. Thus new interrupts can
1458 * be received. Doing it in the beginning of the tasklet is therefor
1459 * important that no requests on any AP get lost.
1460 */
1461 if (ap_using_interrupts())
1462 xchg((u8 *)ap_interrupt_indicator, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001463 do {
1464 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001465 spin_lock(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001466 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001467 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001468 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001469 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001470 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001471 spin_unlock(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001472 } while (flags & 1);
1473 if (flags & 2)
1474 ap_schedule_poll_timer();
1475}
1476
1477/**
Felix Beck1749a812008-04-17 07:46:28 +02001478 * ap_poll_thread(): Thread that polls for finished requests.
1479 * @data: Unused pointer
1480 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001481 * AP bus poll thread. The purpose of this thread is to poll for
1482 * finished requests in a loop if there is a "free" cpu - that is
1483 * a cpu that doesn't have anything better to do. The polling stops
1484 * as soon as there is another task or if all messages have been
1485 * delivered.
1486 */
1487static int ap_poll_thread(void *data)
1488{
1489 DECLARE_WAITQUEUE(wait, current);
1490 unsigned long flags;
1491 int requests;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001492 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001493
Christian Borntraegerd83682b2006-10-06 16:38:22 +02001494 set_user_nice(current, 19);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001495 while (1) {
Felix Beck772f5472009-06-22 12:08:16 +02001496 if (ap_suspend_flag)
1497 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001498 if (need_resched()) {
1499 schedule();
1500 continue;
1501 }
1502 add_wait_queue(&ap_poll_wait, &wait);
1503 set_current_state(TASK_INTERRUPTIBLE);
1504 if (kthread_should_stop())
1505 break;
1506 requests = atomic_read(&ap_poll_requests);
1507 if (requests <= 0)
1508 schedule();
1509 set_current_state(TASK_RUNNING);
1510 remove_wait_queue(&ap_poll_wait, &wait);
1511
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001512 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001513 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001514 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001515 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001516 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001517 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001518 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001519 spin_unlock_bh(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001520 }
1521 set_current_state(TASK_RUNNING);
1522 remove_wait_queue(&ap_poll_wait, &wait);
1523 return 0;
1524}
1525
1526static int ap_poll_thread_start(void)
1527{
1528 int rc;
1529
Felix Beck772f5472009-06-22 12:08:16 +02001530 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beckcb17a632008-12-25 13:38:41 +01001531 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001532 mutex_lock(&ap_poll_thread_mutex);
1533 if (!ap_poll_kthread) {
1534 ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
1535 rc = IS_ERR(ap_poll_kthread) ? PTR_ERR(ap_poll_kthread) : 0;
1536 if (rc)
1537 ap_poll_kthread = NULL;
1538 }
1539 else
1540 rc = 0;
1541 mutex_unlock(&ap_poll_thread_mutex);
1542 return rc;
1543}
1544
1545static void ap_poll_thread_stop(void)
1546{
1547 mutex_lock(&ap_poll_thread_mutex);
1548 if (ap_poll_kthread) {
1549 kthread_stop(ap_poll_kthread);
1550 ap_poll_kthread = NULL;
1551 }
1552 mutex_unlock(&ap_poll_thread_mutex);
1553}
1554
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001555/**
Felix Beck1749a812008-04-17 07:46:28 +02001556 * ap_request_timeout(): Handling of request timeouts
1557 * @data: Holds the AP device.
1558 *
1559 * Handles request timeouts.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001560 */
1561static void ap_request_timeout(unsigned long data)
1562{
1563 struct ap_device *ap_dev = (struct ap_device *) data;
1564
Felix Beckcb17a632008-12-25 13:38:41 +01001565 if (ap_dev->reset == AP_RESET_ARMED) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001566 ap_dev->reset = AP_RESET_DO;
Felix Beckcb17a632008-12-25 13:38:41 +01001567
1568 if (ap_using_interrupts())
1569 tasklet_schedule(&ap_tasklet);
1570 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001571}
1572
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001573static void ap_reset_domain(void)
1574{
1575 int i;
1576
Ralph Wuerthner39aa7cf2007-10-12 16:11:29 +02001577 if (ap_domain_index != -1)
1578 for (i = 0; i < AP_DEVICES; i++)
1579 ap_reset_queue(AP_MKQID(i, ap_domain_index));
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001580}
1581
1582static void ap_reset_all(void)
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001583{
1584 int i, j;
1585
1586 for (i = 0; i < AP_DOMAINS; i++)
1587 for (j = 0; j < AP_DEVICES; j++)
1588 ap_reset_queue(AP_MKQID(j, i));
1589}
1590
1591static struct reset_call ap_reset_call = {
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001592 .fn = ap_reset_all,
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001593};
1594
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001595/**
Felix Beck1749a812008-04-17 07:46:28 +02001596 * ap_module_init(): The module initialization code.
1597 *
1598 * Initializes the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001599 */
1600int __init ap_module_init(void)
1601{
1602 int rc, i;
1603
1604 if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001605 pr_warning("%d is not a valid cryptographic domain\n",
1606 ap_domain_index);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001607 return -EINVAL;
1608 }
Felix Beck5314af62009-09-22 22:58:51 +02001609 /* In resume callback we need to know if the user had set the domain.
1610 * If so, we can not just reset it.
1611 */
1612 if (ap_domain_index >= 0)
1613 user_set_domain = 1;
1614
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001615 if (ap_instructions_available() != 0) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001616 pr_warning("The hardware system does not support "
1617 "AP instructions\n");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001618 return -ENODEV;
1619 }
Felix Beckcb17a632008-12-25 13:38:41 +01001620 if (ap_interrupts_available()) {
1621 isc_register(AP_ISC);
1622 ap_interrupt_indicator = s390_register_adapter_interrupt(
1623 &ap_interrupt_handler, NULL, AP_ISC);
1624 if (IS_ERR(ap_interrupt_indicator)) {
1625 ap_interrupt_indicator = NULL;
1626 isc_unregister(AP_ISC);
1627 }
1628 }
1629
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001630 register_reset_call(&ap_reset_call);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001631
1632 /* Create /sys/bus/ap. */
1633 rc = bus_register(&ap_bus_type);
1634 if (rc)
1635 goto out;
1636 for (i = 0; ap_bus_attrs[i]; i++) {
1637 rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]);
1638 if (rc)
1639 goto out_bus;
1640 }
1641
1642 /* Create /sys/devices/ap. */
Mark McLoughlin035da162008-12-15 12:58:29 +00001643 ap_root_device = root_device_register("ap");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001644 rc = IS_ERR(ap_root_device) ? PTR_ERR(ap_root_device) : 0;
1645 if (rc)
1646 goto out_bus;
1647
1648 ap_work_queue = create_singlethread_workqueue("kapwork");
1649 if (!ap_work_queue) {
1650 rc = -ENOMEM;
1651 goto out_root;
1652 }
1653
1654 if (ap_select_domain() == 0)
1655 ap_scan_bus(NULL);
1656
Felix Beck1749a812008-04-17 07:46:28 +02001657 /* Setup the AP bus rescan timer. */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001658 init_timer(&ap_config_timer);
1659 ap_config_timer.function = ap_config_timeout;
1660 ap_config_timer.data = 0;
1661 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1662 add_timer(&ap_config_timer);
1663
Felix Beckfe137232008-07-14 09:59:08 +02001664 /* Setup the high resultion poll timer.
1665 * If we are running under z/VM adjust polling to z/VM polling rate.
1666 */
1667 if (MACHINE_IS_VM)
1668 poll_timeout = 1500000;
Felix Beck93521312009-12-07 12:52:00 +01001669 spin_lock_init(&ap_poll_timer_lock);
Felix Beckfe137232008-07-14 09:59:08 +02001670 hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1671 ap_poll_timer.function = ap_poll_timeout;
1672
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001673 /* Start the low priority AP bus poll thread. */
1674 if (ap_thread_flag) {
1675 rc = ap_poll_thread_start();
1676 if (rc)
1677 goto out_work;
1678 }
1679
1680 return 0;
1681
1682out_work:
1683 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001684 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001685 destroy_workqueue(ap_work_queue);
1686out_root:
Mark McLoughlin035da162008-12-15 12:58:29 +00001687 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001688out_bus:
1689 while (i--)
1690 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1691 bus_unregister(&ap_bus_type);
1692out:
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001693 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001694 if (ap_using_interrupts()) {
1695 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1696 isc_unregister(AP_ISC);
1697 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001698 return rc;
1699}
1700
1701static int __ap_match_all(struct device *dev, void *data)
1702{
1703 return 1;
1704}
1705
1706/**
Felix Beck1749a812008-04-17 07:46:28 +02001707 * ap_modules_exit(): The module termination code
1708 *
1709 * Terminates the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001710 */
1711void ap_module_exit(void)
1712{
1713 int i;
1714 struct device *dev;
1715
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001716 ap_reset_domain();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001717 ap_poll_thread_stop();
1718 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001719 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001720 destroy_workqueue(ap_work_queue);
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001721 tasklet_kill(&ap_tasklet);
Mark McLoughlin035da162008-12-15 12:58:29 +00001722 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001723 while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
1724 __ap_match_all)))
1725 {
1726 device_unregister(dev);
1727 put_device(dev);
1728 }
1729 for (i = 0; ap_bus_attrs[i]; i++)
1730 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1731 bus_unregister(&ap_bus_type);
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001732 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001733 if (ap_using_interrupts()) {
1734 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1735 isc_unregister(AP_ISC);
1736 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001737}
1738
1739#ifndef CONFIG_ZCRYPT_MONOLITHIC
1740module_init(ap_module_init);
1741module_exit(ap_module_exit);
1742#endif