blob: 4f37c45ee11472d224804cf46d644c9adfd3d6a7 [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
Holger Dengler62d146f2011-01-05 12:47:38 +010030#include <linux/kernel_stat.h>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020031#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/delay.h>
34#include <linux/err.h>
35#include <linux/interrupt.h>
36#include <linux/workqueue.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090037#include <linux/slab.h>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020038#include <linux/notifier.h>
39#include <linux/kthread.h>
40#include <linux/mutex.h>
Ralph Wuerthner85eca852006-12-08 15:54:07 +010041#include <asm/reset.h>
Felix Beckcb17a632008-12-25 13:38:41 +010042#include <asm/airq.h>
43#include <asm/atomic.h>
44#include <asm/system.h>
45#include <asm/isc.h>
Felix Beckfe137232008-07-14 09:59:08 +020046#include <linux/hrtimer.h>
47#include <linux/ktime.h>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020048
49#include "ap_bus.h"
50
51/* Some prototypes. */
Al Viro4927b3f2006-12-06 19:18:20 +000052static void ap_scan_bus(struct work_struct *);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020053static void ap_poll_all(unsigned long);
Felix Beckfe137232008-07-14 09:59:08 +020054static enum hrtimer_restart ap_poll_timeout(struct hrtimer *);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020055static int ap_poll_thread_start(void);
56static void ap_poll_thread_stop(void);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +020057static void ap_request_timeout(unsigned long);
Felix Beckcb17a632008-12-25 13:38:41 +010058static inline void ap_schedule_poll_timer(void);
Felix Beck772f5472009-06-22 12:08:16 +020059static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags);
60static int ap_device_remove(struct device *dev);
61static int ap_device_probe(struct device *dev);
62static void ap_interrupt_handler(void *unused1, void *unused2);
63static void ap_reset(struct ap_device *ap_dev);
64static void ap_config_timeout(unsigned long ptr);
Felix Beck5314af62009-09-22 22:58:51 +020065static int ap_select_domain(void);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020066
Felix Beck1749a812008-04-17 07:46:28 +020067/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020068 * Module description.
69 */
70MODULE_AUTHOR("IBM Corporation");
71MODULE_DESCRIPTION("Adjunct Processor Bus driver, "
72 "Copyright 2006 IBM Corporation");
73MODULE_LICENSE("GPL");
74
Felix Beck1749a812008-04-17 07:46:28 +020075/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020076 * Module parameter
77 */
78int ap_domain_index = -1; /* Adjunct Processor Domain Index */
79module_param_named(domain, ap_domain_index, int, 0000);
80MODULE_PARM_DESC(domain, "domain index for ap devices");
81EXPORT_SYMBOL(ap_domain_index);
82
Felix Beckb90b34c2008-02-09 18:24:30 +010083static int ap_thread_flag = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +020084module_param_named(poll_thread, ap_thread_flag, int, 0000);
Felix Beckb90b34c2008-02-09 18:24:30 +010085MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off).");
Martin Schwidefsky1534c382006-09-20 15:58:25 +020086
87static struct device *ap_root_device = NULL;
Christian Maaser43c207e62008-12-25 13:38:42 +010088static DEFINE_SPINLOCK(ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +010089static LIST_HEAD(ap_device_list);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020090
Felix Beck1749a812008-04-17 07:46:28 +020091/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020092 * Workqueue & timer for bus rescan.
93 */
94static struct workqueue_struct *ap_work_queue;
95static struct timer_list ap_config_timer;
96static int ap_config_time = AP_CONFIG_TIME;
Al Viro4927b3f2006-12-06 19:18:20 +000097static DECLARE_WORK(ap_config_work, ap_scan_bus);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020098
Felix Beck1749a812008-04-17 07:46:28 +020099/*
Felix Beckcb17a632008-12-25 13:38:41 +0100100 * Tasklet & timer for AP request polling and interrupts
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200101 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200102static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0);
103static atomic_t ap_poll_requests = ATOMIC_INIT(0);
104static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
105static struct task_struct *ap_poll_kthread = NULL;
106static DEFINE_MUTEX(ap_poll_thread_mutex);
Felix Beck93521312009-12-07 12:52:00 +0100107static DEFINE_SPINLOCK(ap_poll_timer_lock);
Felix Beckcb17a632008-12-25 13:38:41 +0100108static void *ap_interrupt_indicator;
Felix Beckfe137232008-07-14 09:59:08 +0200109static struct hrtimer ap_poll_timer;
110/* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
111 * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
112static unsigned long long poll_timeout = 250000;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200113
Felix Beck772f5472009-06-22 12:08:16 +0200114/* Suspend flag */
115static int ap_suspend_flag;
Felix Beck5314af62009-09-22 22:58:51 +0200116/* Flag to check if domain was set through module parameter domain=. This is
117 * important when supsend and resume is done in a z/VM environment where the
118 * domain might change. */
119static int user_set_domain = 0;
Felix Beck772f5472009-06-22 12:08:16 +0200120static struct bus_type ap_bus_type;
121
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200122/**
Felix Beckcb17a632008-12-25 13:38:41 +0100123 * ap_using_interrupts() - Returns non-zero if interrupt support is
124 * available.
125 */
126static inline int ap_using_interrupts(void)
127{
128 return ap_interrupt_indicator != NULL;
129}
130
131/**
Felix Beck1749a812008-04-17 07:46:28 +0200132 * ap_intructions_available() - Test if AP instructions are available.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200133 *
Felix Beck1749a812008-04-17 07:46:28 +0200134 * Returns 0 if the AP instructions are installed.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200135 */
136static inline int ap_instructions_available(void)
137{
138 register unsigned long reg0 asm ("0") = AP_MKQID(0,0);
139 register unsigned long reg1 asm ("1") = -ENODEV;
140 register unsigned long reg2 asm ("2") = 0UL;
141
142 asm volatile(
143 " .long 0xb2af0000\n" /* PQAP(TAPQ) */
144 "0: la %1,0\n"
145 "1:\n"
146 EX_TABLE(0b, 1b)
147 : "+d" (reg0), "+d" (reg1), "+d" (reg2) : : "cc" );
148 return reg1;
149}
150
151/**
Felix Beckcb17a632008-12-25 13:38:41 +0100152 * ap_interrupts_available(): Test if AP interrupts are available.
153 *
154 * Returns 1 if AP interrupts are available.
155 */
156static int ap_interrupts_available(void)
157{
Felix Beck53ec24b12011-01-05 12:46:44 +0100158 return test_facility(2) && test_facility(65);
Felix Beckcb17a632008-12-25 13:38:41 +0100159}
160
161/**
Felix Beck1749a812008-04-17 07:46:28 +0200162 * ap_test_queue(): Test adjunct processor queue.
163 * @qid: The AP queue number
164 * @queue_depth: Pointer to queue depth value
165 * @device_type: Pointer to device type value
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200166 *
Felix Beck1749a812008-04-17 07:46:28 +0200167 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200168 */
169static inline struct ap_queue_status
170ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
171{
172 register unsigned long reg0 asm ("0") = qid;
173 register struct ap_queue_status reg1 asm ("1");
174 register unsigned long reg2 asm ("2") = 0UL;
175
176 asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
177 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
178 *device_type = (int) (reg2 >> 24);
179 *queue_depth = (int) (reg2 & 0xff);
180 return reg1;
181}
182
183/**
Felix Beck1749a812008-04-17 07:46:28 +0200184 * ap_reset_queue(): Reset adjunct processor queue.
185 * @qid: The AP queue number
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200186 *
Felix Beck1749a812008-04-17 07:46:28 +0200187 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200188 */
189static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
190{
191 register unsigned long reg0 asm ("0") = qid | 0x01000000UL;
192 register struct ap_queue_status reg1 asm ("1");
193 register unsigned long reg2 asm ("2") = 0UL;
194
195 asm volatile(
196 ".long 0xb2af0000" /* PQAP(RAPQ) */
197 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
198 return reg1;
199}
200
Felix Beckcb17a632008-12-25 13:38:41 +0100201#ifdef CONFIG_64BIT
202/**
203 * ap_queue_interruption_control(): Enable interruption for a specific AP.
204 * @qid: The AP queue number
205 * @ind: The notification indicator byte
206 *
207 * Returns AP queue status.
208 */
209static inline struct ap_queue_status
210ap_queue_interruption_control(ap_qid_t qid, void *ind)
211{
212 register unsigned long reg0 asm ("0") = qid | 0x03000000UL;
213 register unsigned long reg1_in asm ("1") = 0x0000800000000000UL | AP_ISC;
214 register struct ap_queue_status reg1_out asm ("1");
215 register void *reg2 asm ("2") = ind;
216 asm volatile(
217 ".long 0xb2af0000" /* PQAP(RAPQ) */
218 : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
219 :
220 : "cc" );
221 return reg1_out;
222}
223#endif
224
225/**
226 * ap_queue_enable_interruption(): Enable interruption on an AP.
227 * @qid: The AP queue number
228 * @ind: the notification indicator byte
229 *
230 * Enables interruption on AP queue via ap_queue_interruption_control(). Based
231 * on the return value it waits a while and tests the AP queue if interrupts
232 * have been switched on using ap_test_queue().
233 */
234static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
235{
236#ifdef CONFIG_64BIT
237 struct ap_queue_status status;
238 int t_depth, t_device_type, rc, i;
239
240 rc = -EBUSY;
241 status = ap_queue_interruption_control(qid, ind);
242
243 for (i = 0; i < AP_MAX_RESET; i++) {
244 switch (status.response_code) {
245 case AP_RESPONSE_NORMAL:
246 if (status.int_enabled)
247 return 0;
248 break;
249 case AP_RESPONSE_RESET_IN_PROGRESS:
250 case AP_RESPONSE_BUSY:
251 break;
252 case AP_RESPONSE_Q_NOT_AVAIL:
253 case AP_RESPONSE_DECONFIGURED:
254 case AP_RESPONSE_CHECKSTOPPED:
255 case AP_RESPONSE_INVALID_ADDRESS:
256 return -ENODEV;
257 case AP_RESPONSE_OTHERWISE_CHANGED:
258 if (status.int_enabled)
259 return 0;
260 break;
261 default:
262 break;
263 }
264 if (i < AP_MAX_RESET - 1) {
265 udelay(5);
266 status = ap_test_queue(qid, &t_depth, &t_device_type);
267 }
268 }
269 return rc;
270#else
271 return -EINVAL;
272#endif
273}
274
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200275/**
Felix Beck1749a812008-04-17 07:46:28 +0200276 * __ap_send(): Send message to adjunct processor queue.
277 * @qid: The AP queue number
278 * @psmid: The program supplied message identifier
279 * @msg: The message text
280 * @length: The message length
Felix Becka6a5d732009-12-07 12:51:55 +0100281 * @special: Special Bit
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200282 *
Felix Beck1749a812008-04-17 07:46:28 +0200283 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200284 * Condition code 1 on NQAP can't happen because the L bit is 1.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200285 * Condition code 2 on NQAP also means the send is incomplete,
286 * because a segment boundary was reached. The NQAP is repeated.
287 */
288static inline struct ap_queue_status
Felix Becka6a5d732009-12-07 12:51:55 +0100289__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length,
290 unsigned int special)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200291{
292 typedef struct { char _[length]; } msgblock;
293 register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
294 register struct ap_queue_status reg1 asm ("1");
295 register unsigned long reg2 asm ("2") = (unsigned long) msg;
296 register unsigned long reg3 asm ("3") = (unsigned long) length;
297 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
298 register unsigned long reg5 asm ("5") = (unsigned int) psmid;
299
Felix Becka6a5d732009-12-07 12:51:55 +0100300 if (special == 1)
301 reg0 |= 0x400000UL;
302
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200303 asm volatile (
304 "0: .long 0xb2ad0042\n" /* DQAP */
305 " brc 2,0b"
306 : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
307 : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg)
308 : "cc" );
309 return reg1;
310}
311
312int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
313{
314 struct ap_queue_status status;
315
Felix Becka6a5d732009-12-07 12:51:55 +0100316 status = __ap_send(qid, psmid, msg, length, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200317 switch (status.response_code) {
318 case AP_RESPONSE_NORMAL:
319 return 0;
320 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200321 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200322 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +0100323 case AP_RESPONSE_REQ_FAC_NOT_INST:
324 return -EINVAL;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200325 default: /* Device is gone. */
326 return -ENODEV;
327 }
328}
329EXPORT_SYMBOL(ap_send);
330
Felix Beck1749a812008-04-17 07:46:28 +0200331/**
332 * __ap_recv(): Receive message from adjunct processor queue.
333 * @qid: The AP queue number
334 * @psmid: Pointer to program supplied message identifier
335 * @msg: The message text
336 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200337 *
Felix Beck1749a812008-04-17 07:46:28 +0200338 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200339 * Condition code 1 on DQAP means the receive has taken place
340 * but only partially. The response is incomplete, hence the
341 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200342 * Condition code 2 on DQAP also means the receive is incomplete,
343 * this time because a segment boundary was reached. Again, the
344 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200345 * Note that gpr2 is used by the DQAP instruction to keep track of
346 * any 'residual' length, in case the instruction gets interrupted.
347 * Hence it gets zeroed before the instruction.
348 */
349static inline struct ap_queue_status
350__ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
351{
352 typedef struct { char _[length]; } msgblock;
353 register unsigned long reg0 asm("0") = qid | 0x80000000UL;
354 register struct ap_queue_status reg1 asm ("1");
355 register unsigned long reg2 asm("2") = 0UL;
356 register unsigned long reg4 asm("4") = (unsigned long) msg;
357 register unsigned long reg5 asm("5") = (unsigned long) length;
358 register unsigned long reg6 asm("6") = 0UL;
359 register unsigned long reg7 asm("7") = 0UL;
360
361
362 asm volatile(
363 "0: .long 0xb2ae0064\n"
364 " brc 6,0b\n"
365 : "+d" (reg0), "=d" (reg1), "+d" (reg2),
366 "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
367 "=m" (*(msgblock *) msg) : : "cc" );
368 *psmid = (((unsigned long long) reg6) << 32) + reg7;
369 return reg1;
370}
371
372int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
373{
374 struct ap_queue_status status;
375
376 status = __ap_recv(qid, psmid, msg, length);
377 switch (status.response_code) {
378 case AP_RESPONSE_NORMAL:
379 return 0;
380 case AP_RESPONSE_NO_PENDING_REPLY:
381 if (status.queue_empty)
382 return -ENOENT;
383 return -EBUSY;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200384 case AP_RESPONSE_RESET_IN_PROGRESS:
385 return -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200386 default:
387 return -ENODEV;
388 }
389}
390EXPORT_SYMBOL(ap_recv);
391
392/**
Felix Beck1749a812008-04-17 07:46:28 +0200393 * ap_query_queue(): Check if an AP queue is available.
394 * @qid: The AP queue number
395 * @queue_depth: Pointer to queue depth value
396 * @device_type: Pointer to device type value
397 *
398 * The test is repeated for AP_MAX_RESET times.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200399 */
400static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
401{
402 struct ap_queue_status status;
403 int t_depth, t_device_type, rc, i;
404
405 rc = -EBUSY;
406 for (i = 0; i < AP_MAX_RESET; i++) {
407 status = ap_test_queue(qid, &t_depth, &t_device_type);
408 switch (status.response_code) {
409 case AP_RESPONSE_NORMAL:
410 *queue_depth = t_depth + 1;
411 *device_type = t_device_type;
412 rc = 0;
413 break;
414 case AP_RESPONSE_Q_NOT_AVAIL:
415 rc = -ENODEV;
416 break;
417 case AP_RESPONSE_RESET_IN_PROGRESS:
418 break;
419 case AP_RESPONSE_DECONFIGURED:
420 rc = -ENODEV;
421 break;
422 case AP_RESPONSE_CHECKSTOPPED:
423 rc = -ENODEV;
424 break;
Felix Beckcb17a632008-12-25 13:38:41 +0100425 case AP_RESPONSE_INVALID_ADDRESS:
426 rc = -ENODEV;
427 break;
428 case AP_RESPONSE_OTHERWISE_CHANGED:
429 break;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200430 case AP_RESPONSE_BUSY:
431 break;
432 default:
433 BUG();
434 }
435 if (rc != -EBUSY)
436 break;
437 if (i < AP_MAX_RESET - 1)
438 udelay(5);
439 }
440 return rc;
441}
442
443/**
Felix Beck1749a812008-04-17 07:46:28 +0200444 * ap_init_queue(): Reset an AP queue.
445 * @qid: The AP queue number
446 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200447 * Reset an AP queue and wait for it to become available again.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200448 */
449static int ap_init_queue(ap_qid_t qid)
450{
451 struct ap_queue_status status;
452 int rc, dummy, i;
453
454 rc = -ENODEV;
455 status = ap_reset_queue(qid);
456 for (i = 0; i < AP_MAX_RESET; i++) {
457 switch (status.response_code) {
458 case AP_RESPONSE_NORMAL:
459 if (status.queue_empty)
460 rc = 0;
461 break;
462 case AP_RESPONSE_Q_NOT_AVAIL:
463 case AP_RESPONSE_DECONFIGURED:
464 case AP_RESPONSE_CHECKSTOPPED:
465 i = AP_MAX_RESET; /* return with -ENODEV */
466 break;
467 case AP_RESPONSE_RESET_IN_PROGRESS:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200468 rc = -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200469 case AP_RESPONSE_BUSY:
470 default:
471 break;
472 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200473 if (rc != -ENODEV && rc != -EBUSY)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200474 break;
475 if (i < AP_MAX_RESET - 1) {
476 udelay(5);
477 status = ap_test_queue(qid, &dummy, &dummy);
478 }
479 }
Felix Beckcb17a632008-12-25 13:38:41 +0100480 if (rc == 0 && ap_using_interrupts()) {
481 rc = ap_queue_enable_interruption(qid, ap_interrupt_indicator);
482 /* If interruption mode is supported by the machine,
483 * but an AP can not be enabled for interruption then
484 * the AP will be discarded. */
485 if (rc)
486 pr_err("Registering adapter interrupts for "
487 "AP %d failed\n", AP_QID_DEVICE(qid));
488 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200489 return rc;
490}
491
492/**
Felix Beck1749a812008-04-17 07:46:28 +0200493 * ap_increase_queue_count(): Arm request timeout.
494 * @ap_dev: Pointer to an AP device.
495 *
496 * Arm request timeout if an AP device was idle and a new request is submitted.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200497 */
498static void ap_increase_queue_count(struct ap_device *ap_dev)
499{
500 int timeout = ap_dev->drv->request_timeout;
501
502 ap_dev->queue_count++;
503 if (ap_dev->queue_count == 1) {
504 mod_timer(&ap_dev->timeout, jiffies + timeout);
505 ap_dev->reset = AP_RESET_ARMED;
506 }
507}
508
509/**
Felix Beck1749a812008-04-17 07:46:28 +0200510 * ap_decrease_queue_count(): Decrease queue count.
511 * @ap_dev: Pointer to an AP device.
512 *
513 * If AP device is still alive, re-schedule request timeout if there are still
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200514 * pending requests.
515 */
516static void ap_decrease_queue_count(struct ap_device *ap_dev)
517{
518 int timeout = ap_dev->drv->request_timeout;
519
520 ap_dev->queue_count--;
521 if (ap_dev->queue_count > 0)
522 mod_timer(&ap_dev->timeout, jiffies + timeout);
523 else
Felix Beck1749a812008-04-17 07:46:28 +0200524 /*
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200525 * The timeout timer should to be disabled now - since
526 * del_timer_sync() is very expensive, we just tell via the
527 * reset flag to ignore the pending timeout timer.
528 */
529 ap_dev->reset = AP_RESET_IGNORE;
530}
531
Felix Beck1749a812008-04-17 07:46:28 +0200532/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200533 * AP device related attributes.
534 */
535static ssize_t ap_hwtype_show(struct device *dev,
536 struct device_attribute *attr, char *buf)
537{
538 struct ap_device *ap_dev = to_ap_dev(dev);
539 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type);
540}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200541
Christian Maaser43c207e62008-12-25 13:38:42 +0100542static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200543static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr,
544 char *buf)
545{
546 struct ap_device *ap_dev = to_ap_dev(dev);
547 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth);
548}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200549
Christian Maaser43c207e62008-12-25 13:38:42 +0100550static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200551static ssize_t ap_request_count_show(struct device *dev,
552 struct device_attribute *attr,
553 char *buf)
554{
555 struct ap_device *ap_dev = to_ap_dev(dev);
556 int rc;
557
558 spin_lock_bh(&ap_dev->lock);
559 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->total_request_count);
560 spin_unlock_bh(&ap_dev->lock);
561 return rc;
562}
563
564static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL);
565
566static ssize_t ap_modalias_show(struct device *dev,
567 struct device_attribute *attr, char *buf)
568{
569 return sprintf(buf, "ap:t%02X", to_ap_dev(dev)->device_type);
570}
571
572static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL);
573
574static struct attribute *ap_dev_attrs[] = {
575 &dev_attr_hwtype.attr,
576 &dev_attr_depth.attr,
577 &dev_attr_request_count.attr,
578 &dev_attr_modalias.attr,
579 NULL
580};
581static struct attribute_group ap_dev_attr_group = {
582 .attrs = ap_dev_attrs
583};
584
585/**
Felix Beck1749a812008-04-17 07:46:28 +0200586 * ap_bus_match()
587 * @dev: Pointer to device
588 * @drv: Pointer to device_driver
589 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200590 * AP bus driver registration/unregistration.
591 */
592static int ap_bus_match(struct device *dev, struct device_driver *drv)
593{
594 struct ap_device *ap_dev = to_ap_dev(dev);
595 struct ap_driver *ap_drv = to_ap_drv(drv);
596 struct ap_device_id *id;
597
Felix Beck1749a812008-04-17 07:46:28 +0200598 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200599 * Compare device type of the device with the list of
600 * supported types of the device_driver.
601 */
602 for (id = ap_drv->ids; id->match_flags; id++) {
603 if ((id->match_flags & AP_DEVICE_ID_MATCH_DEVICE_TYPE) &&
604 (id->dev_type != ap_dev->device_type))
605 continue;
606 return 1;
607 }
608 return 0;
609}
610
611/**
Felix Beck1749a812008-04-17 07:46:28 +0200612 * ap_uevent(): Uevent function for AP devices.
613 * @dev: Pointer to device
614 * @env: Pointer to kobj_uevent_env
615 *
616 * It sets up a single environment variable DEV_TYPE which contains the
617 * hardware device type.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200618 */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200619static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200620{
621 struct ap_device *ap_dev = to_ap_dev(dev);
Kay Sievers7eff2e72007-08-14 15:15:12 +0200622 int retval = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200623
624 if (!ap_dev)
625 return -ENODEV;
626
627 /* Set up DEV_TYPE environment variable. */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200628 retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700629 if (retval)
630 return retval;
631
Cornelia Huck66a42632006-12-04 15:40:10 +0100632 /* Add MODALIAS= */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200633 retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700634
Eric Rannaudbf624562007-03-30 22:23:12 -0700635 return retval;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200636}
637
Felix Beck772f5472009-06-22 12:08:16 +0200638static int ap_bus_suspend(struct device *dev, pm_message_t state)
639{
640 struct ap_device *ap_dev = to_ap_dev(dev);
641 unsigned long flags;
642
643 if (!ap_suspend_flag) {
644 ap_suspend_flag = 1;
645
646 /* Disable scanning for devices, thus we do not want to scan
647 * for them after removing.
648 */
649 del_timer_sync(&ap_config_timer);
650 if (ap_work_queue != NULL) {
651 destroy_workqueue(ap_work_queue);
652 ap_work_queue = NULL;
653 }
Felix Beck5314af62009-09-22 22:58:51 +0200654
Felix Beck772f5472009-06-22 12:08:16 +0200655 tasklet_disable(&ap_tasklet);
656 }
657 /* Poll on the device until all requests are finished. */
658 do {
659 flags = 0;
Felix Beck95f15562009-09-11 10:28:51 +0200660 spin_lock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200661 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +0200662 spin_unlock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200663 } while ((flags & 1) || (flags & 2));
664
Felix Beck5314af62009-09-22 22:58:51 +0200665 spin_lock_bh(&ap_dev->lock);
666 ap_dev->unregistered = 1;
667 spin_unlock_bh(&ap_dev->lock);
668
Felix Beck772f5472009-06-22 12:08:16 +0200669 return 0;
670}
671
672static int ap_bus_resume(struct device *dev)
673{
674 int rc = 0;
675 struct ap_device *ap_dev = to_ap_dev(dev);
676
677 if (ap_suspend_flag) {
678 ap_suspend_flag = 0;
679 if (!ap_interrupts_available())
680 ap_interrupt_indicator = NULL;
Felix Beck5314af62009-09-22 22:58:51 +0200681 if (!user_set_domain) {
682 ap_domain_index = -1;
683 ap_select_domain();
684 }
Felix Beck772f5472009-06-22 12:08:16 +0200685 init_timer(&ap_config_timer);
686 ap_config_timer.function = ap_config_timeout;
687 ap_config_timer.data = 0;
688 ap_config_timer.expires = jiffies + ap_config_time * HZ;
689 add_timer(&ap_config_timer);
690 ap_work_queue = create_singlethread_workqueue("kapwork");
691 if (!ap_work_queue)
692 return -ENOMEM;
693 tasklet_enable(&ap_tasklet);
694 if (!ap_using_interrupts())
695 ap_schedule_poll_timer();
696 else
697 tasklet_schedule(&ap_tasklet);
698 if (ap_thread_flag)
699 rc = ap_poll_thread_start();
Felix Beck772f5472009-06-22 12:08:16 +0200700 }
Felix Beck5314af62009-09-22 22:58:51 +0200701 if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) {
702 spin_lock_bh(&ap_dev->lock);
703 ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid),
704 ap_domain_index);
705 spin_unlock_bh(&ap_dev->lock);
706 }
707 queue_work(ap_work_queue, &ap_config_work);
Felix Beck772f5472009-06-22 12:08:16 +0200708
709 return rc;
710}
711
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200712static struct bus_type ap_bus_type = {
713 .name = "ap",
714 .match = &ap_bus_match,
715 .uevent = &ap_uevent,
Felix Beck772f5472009-06-22 12:08:16 +0200716 .suspend = ap_bus_suspend,
717 .resume = ap_bus_resume
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200718};
719
720static int ap_device_probe(struct device *dev)
721{
722 struct ap_device *ap_dev = to_ap_dev(dev);
723 struct ap_driver *ap_drv = to_ap_drv(dev->driver);
724 int rc;
725
726 ap_dev->drv = ap_drv;
727 rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100728 if (!rc) {
Christian Maaser43c207e62008-12-25 13:38:42 +0100729 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100730 list_add(&ap_dev->list, &ap_device_list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100731 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100732 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200733 return rc;
734}
735
736/**
Felix Beck1749a812008-04-17 07:46:28 +0200737 * __ap_flush_queue(): Flush requests.
738 * @ap_dev: Pointer to the AP device
739 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200740 * Flush all requests from the request/pending queue of an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200741 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100742static void __ap_flush_queue(struct ap_device *ap_dev)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200743{
744 struct ap_message *ap_msg, *next;
745
746 list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
747 list_del_init(&ap_msg->list);
748 ap_dev->pendingq_count--;
749 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
750 }
751 list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
752 list_del_init(&ap_msg->list);
753 ap_dev->requestq_count--;
754 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
755 }
756}
757
758void ap_flush_queue(struct ap_device *ap_dev)
759{
760 spin_lock_bh(&ap_dev->lock);
761 __ap_flush_queue(ap_dev);
762 spin_unlock_bh(&ap_dev->lock);
763}
764EXPORT_SYMBOL(ap_flush_queue);
765
766static int ap_device_remove(struct device *dev)
767{
768 struct ap_device *ap_dev = to_ap_dev(dev);
769 struct ap_driver *ap_drv = ap_dev->drv;
770
Ralph Wuerthner4e562962006-10-04 20:02:05 +0200771 ap_flush_queue(ap_dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200772 del_timer_sync(&ap_dev->timeout);
Christian Maaser43c207e62008-12-25 13:38:42 +0100773 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +0100774 list_del_init(&ap_dev->list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100775 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100776 if (ap_drv->remove)
777 ap_drv->remove(ap_dev);
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +0200778 spin_lock_bh(&ap_dev->lock);
779 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
780 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200781 return 0;
782}
783
784int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
785 char *name)
786{
787 struct device_driver *drv = &ap_drv->driver;
788
789 drv->bus = &ap_bus_type;
790 drv->probe = ap_device_probe;
791 drv->remove = ap_device_remove;
792 drv->owner = owner;
793 drv->name = name;
794 return driver_register(drv);
795}
796EXPORT_SYMBOL(ap_driver_register);
797
798void ap_driver_unregister(struct ap_driver *ap_drv)
799{
800 driver_unregister(&ap_drv->driver);
801}
802EXPORT_SYMBOL(ap_driver_unregister);
803
Felix Beck1749a812008-04-17 07:46:28 +0200804/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200805 * AP bus attributes.
806 */
807static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
808{
809 return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
810}
811
812static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
813
814static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
815{
816 return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
817}
818
Felix Beckcb17a632008-12-25 13:38:41 +0100819static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
820{
821 return snprintf(buf, PAGE_SIZE, "%d\n",
822 ap_using_interrupts() ? 1 : 0);
823}
824
825static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL);
826
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200827static ssize_t ap_config_time_store(struct bus_type *bus,
828 const char *buf, size_t count)
829{
830 int time;
831
832 if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120)
833 return -EINVAL;
834 ap_config_time = time;
835 if (!timer_pending(&ap_config_timer) ||
836 !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) {
837 ap_config_timer.expires = jiffies + ap_config_time * HZ;
838 add_timer(&ap_config_timer);
839 }
840 return count;
841}
842
843static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store);
844
845static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf)
846{
847 return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
848}
849
850static ssize_t ap_poll_thread_store(struct bus_type *bus,
851 const char *buf, size_t count)
852{
853 int flag, rc;
854
855 if (sscanf(buf, "%d\n", &flag) != 1)
856 return -EINVAL;
857 if (flag) {
858 rc = ap_poll_thread_start();
859 if (rc)
860 return rc;
861 }
862 else
863 ap_poll_thread_stop();
864 return count;
865}
866
867static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
868
Felix Beckfe137232008-07-14 09:59:08 +0200869static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
870{
871 return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
872}
873
874static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
875 size_t count)
876{
877 unsigned long long time;
878 ktime_t hr_time;
879
880 /* 120 seconds = maximum poll interval */
Felix Beckcb17a632008-12-25 13:38:41 +0100881 if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 ||
882 time > 120000000000ULL)
Felix Beckfe137232008-07-14 09:59:08 +0200883 return -EINVAL;
884 poll_timeout = time;
885 hr_time = ktime_set(0, poll_timeout);
886
887 if (!hrtimer_is_queued(&ap_poll_timer) ||
Arjan van de Ven6c644ea2008-09-01 15:20:30 -0700888 !hrtimer_forward(&ap_poll_timer, hrtimer_get_expires(&ap_poll_timer), hr_time)) {
889 hrtimer_set_expires(&ap_poll_timer, hr_time);
890 hrtimer_start_expires(&ap_poll_timer, HRTIMER_MODE_ABS);
Felix Beckfe137232008-07-14 09:59:08 +0200891 }
892 return count;
893}
894
895static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
896
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200897static struct bus_attribute *const ap_bus_attrs[] = {
898 &bus_attr_ap_domain,
899 &bus_attr_config_time,
900 &bus_attr_poll_thread,
Felix Beckcb17a632008-12-25 13:38:41 +0100901 &bus_attr_ap_interrupts,
Felix Beckfe137232008-07-14 09:59:08 +0200902 &bus_attr_poll_timeout,
903 NULL,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200904};
905
906/**
Felix Beck1749a812008-04-17 07:46:28 +0200907 * ap_select_domain(): Select an AP domain.
908 *
909 * Pick one of the 16 AP domains.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200910 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100911static int ap_select_domain(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200912{
913 int queue_depth, device_type, count, max_count, best_domain;
914 int rc, i, j;
915
Felix Beck1749a812008-04-17 07:46:28 +0200916 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200917 * We want to use a single domain. Either the one specified with
918 * the "domain=" parameter or the domain with the maximum number
919 * of devices.
920 */
921 if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS)
922 /* Domain has already been selected. */
923 return 0;
924 best_domain = -1;
925 max_count = 0;
926 for (i = 0; i < AP_DOMAINS; i++) {
927 count = 0;
928 for (j = 0; j < AP_DEVICES; j++) {
929 ap_qid_t qid = AP_MKQID(j, i);
930 rc = ap_query_queue(qid, &queue_depth, &device_type);
931 if (rc)
932 continue;
933 count++;
934 }
935 if (count > max_count) {
936 max_count = count;
937 best_domain = i;
938 }
939 }
940 if (best_domain >= 0){
941 ap_domain_index = best_domain;
942 return 0;
943 }
944 return -ENODEV;
945}
946
947/**
Felix Beck1749a812008-04-17 07:46:28 +0200948 * ap_probe_device_type(): Find the device type of an AP.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200949 * @ap_dev: pointer to the AP device.
Felix Beck1749a812008-04-17 07:46:28 +0200950 *
951 * Find the device type if query queue returned a device type of 0.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200952 */
953static int ap_probe_device_type(struct ap_device *ap_dev)
954{
955 static unsigned char msg[] = {
956 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
957 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
958 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
959 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
960 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50,
961 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,
962 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00,
963 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,
964 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
965 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,
966 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
967 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,
968 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00,
969 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
970 0x00,0x00,0x00,0x00,0xb8,0x05,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,0x00,0x00,0x00,0x00,0x00,0x00,
977 0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,
978 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
979 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
980 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20,
981 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,
982 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22,
983 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
984 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
985 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,
986 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,
987 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,
988 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
989 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,
990 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00,
991 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,
992 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01,
993 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,
994 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68,
995 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,
996 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0,
997 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,
998 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04,
999 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,
1000 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d,
1001 };
1002 struct ap_queue_status status;
1003 unsigned long long psmid;
1004 char *reply;
1005 int rc, i;
1006
1007 reply = (void *) get_zeroed_page(GFP_KERNEL);
1008 if (!reply) {
1009 rc = -ENOMEM;
1010 goto out;
1011 }
1012
1013 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
Felix Becka6a5d732009-12-07 12:51:55 +01001014 msg, sizeof(msg), 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001015 if (status.response_code != AP_RESPONSE_NORMAL) {
1016 rc = -ENODEV;
1017 goto out_free;
1018 }
1019
1020 /* Wait for the test message to complete. */
1021 for (i = 0; i < 6; i++) {
1022 mdelay(300);
1023 status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
1024 if (status.response_code == AP_RESPONSE_NORMAL &&
1025 psmid == 0x0102030405060708ULL)
1026 break;
1027 }
1028 if (i < 6) {
1029 /* Got an answer. */
1030 if (reply[0] == 0x00 && reply[1] == 0x86)
1031 ap_dev->device_type = AP_DEVICE_TYPE_PCICC;
1032 else
1033 ap_dev->device_type = AP_DEVICE_TYPE_PCICA;
1034 rc = 0;
1035 } else
1036 rc = -ENODEV;
1037
1038out_free:
1039 free_page((unsigned long) reply);
1040out:
1041 return rc;
1042}
1043
Felix Beckcb17a632008-12-25 13:38:41 +01001044static void ap_interrupt_handler(void *unused1, void *unused2)
1045{
Holger Dengler62d146f2011-01-05 12:47:38 +01001046 kstat_cpu(smp_processor_id()).irqs[IOINT_APB]++;
Felix Beckcb17a632008-12-25 13:38:41 +01001047 tasklet_schedule(&ap_tasklet);
1048}
1049
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001050/**
Felix Beck1749a812008-04-17 07:46:28 +02001051 * __ap_scan_bus(): Scan the AP bus.
1052 * @dev: Pointer to device
1053 * @data: Pointer to data
1054 *
1055 * Scan the AP bus for new devices.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001056 */
1057static int __ap_scan_bus(struct device *dev, void *data)
1058{
1059 return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data;
1060}
1061
1062static void ap_device_release(struct device *dev)
1063{
1064 struct ap_device *ap_dev = to_ap_dev(dev);
1065
1066 kfree(ap_dev);
1067}
1068
Al Viro4927b3f2006-12-06 19:18:20 +00001069static void ap_scan_bus(struct work_struct *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001070{
1071 struct ap_device *ap_dev;
1072 struct device *dev;
1073 ap_qid_t qid;
1074 int queue_depth, device_type;
1075 int rc, i;
1076
1077 if (ap_select_domain() != 0)
1078 return;
1079 for (i = 0; i < AP_DEVICES; i++) {
1080 qid = AP_MKQID(i, ap_domain_index);
1081 dev = bus_find_device(&ap_bus_type, NULL,
1082 (void *)(unsigned long)qid,
1083 __ap_scan_bus);
Ralph Wuerthnerf3b017d2006-10-27 12:39:26 +02001084 rc = ap_query_queue(qid, &queue_depth, &device_type);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001085 if (dev) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001086 if (rc == -EBUSY) {
1087 set_current_state(TASK_UNINTERRUPTIBLE);
1088 schedule_timeout(AP_RESET_TIMEOUT);
1089 rc = ap_query_queue(qid, &queue_depth,
1090 &device_type);
1091 }
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001092 ap_dev = to_ap_dev(dev);
1093 spin_lock_bh(&ap_dev->lock);
1094 if (rc || ap_dev->unregistered) {
1095 spin_unlock_bh(&ap_dev->lock);
Felix Beck5314af62009-09-22 22:58:51 +02001096 if (ap_dev->unregistered)
1097 i--;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001098 device_unregister(dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001099 put_device(dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001100 continue;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001101 }
1102 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001103 put_device(dev);
1104 continue;
1105 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001106 if (rc)
1107 continue;
1108 rc = ap_init_queue(qid);
1109 if (rc)
1110 continue;
1111 ap_dev = kzalloc(sizeof(*ap_dev), GFP_KERNEL);
1112 if (!ap_dev)
1113 break;
1114 ap_dev->qid = qid;
1115 ap_dev->queue_depth = queue_depth;
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001116 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001117 spin_lock_init(&ap_dev->lock);
1118 INIT_LIST_HEAD(&ap_dev->pendingq);
1119 INIT_LIST_HEAD(&ap_dev->requestq);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001120 INIT_LIST_HEAD(&ap_dev->list);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001121 setup_timer(&ap_dev->timeout, ap_request_timeout,
1122 (unsigned long) ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001123 if (device_type == 0)
1124 ap_probe_device_type(ap_dev);
1125 else
1126 ap_dev->device_type = device_type;
1127
1128 ap_dev->device.bus = &ap_bus_type;
1129 ap_dev->device.parent = ap_root_device;
Felix Beckedc44fa2009-09-11 10:28:52 +02001130 if (dev_set_name(&ap_dev->device, "card%02x",
1131 AP_QID_DEVICE(ap_dev->qid))) {
1132 kfree(ap_dev);
1133 continue;
1134 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001135 ap_dev->device.release = ap_device_release;
1136 rc = device_register(&ap_dev->device);
1137 if (rc) {
Sebastian Ottc6304932009-09-11 10:28:38 +02001138 put_device(&ap_dev->device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001139 continue;
1140 }
1141 /* Add device attributes. */
1142 rc = sysfs_create_group(&ap_dev->device.kobj,
1143 &ap_dev_attr_group);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001144 if (!rc) {
1145 spin_lock_bh(&ap_dev->lock);
1146 ap_dev->unregistered = 0;
1147 spin_unlock_bh(&ap_dev->lock);
1148 }
1149 else
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001150 device_unregister(&ap_dev->device);
1151 }
1152}
1153
1154static void
1155ap_config_timeout(unsigned long ptr)
1156{
1157 queue_work(ap_work_queue, &ap_config_work);
1158 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1159 add_timer(&ap_config_timer);
1160}
1161
1162/**
Felix Beck1749a812008-04-17 07:46:28 +02001163 * ap_schedule_poll_timer(): Schedule poll timer.
1164 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001165 * Set up the timer to run the poll tasklet
1166 */
1167static inline void ap_schedule_poll_timer(void)
1168{
Felix Beck8d406c62009-07-24 12:39:53 +02001169 ktime_t hr_time;
Felix Beck93521312009-12-07 12:52:00 +01001170
1171 spin_lock_bh(&ap_poll_timer_lock);
Felix Beck772f5472009-06-22 12:08:16 +02001172 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beck93521312009-12-07 12:52:00 +01001173 goto out;
Felix Beckfe137232008-07-14 09:59:08 +02001174 if (hrtimer_is_queued(&ap_poll_timer))
Felix Beck93521312009-12-07 12:52:00 +01001175 goto out;
Felix Beck8d406c62009-07-24 12:39:53 +02001176 if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
1177 hr_time = ktime_set(0, poll_timeout);
1178 hrtimer_forward_now(&ap_poll_timer, hr_time);
1179 hrtimer_restart(&ap_poll_timer);
1180 }
Felix Beck93521312009-12-07 12:52:00 +01001181out:
1182 spin_unlock_bh(&ap_poll_timer_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001183}
1184
1185/**
Felix Beck1749a812008-04-17 07:46:28 +02001186 * ap_poll_read(): Receive pending reply messages from an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001187 * @ap_dev: pointer to the AP device
1188 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1189 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001190 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001191 * Returns 0 if the device is still present, -ENODEV if not.
1192 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001193static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001194{
1195 struct ap_queue_status status;
1196 struct ap_message *ap_msg;
1197
1198 if (ap_dev->queue_count <= 0)
1199 return 0;
1200 status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
1201 ap_dev->reply->message, ap_dev->reply->length);
1202 switch (status.response_code) {
1203 case AP_RESPONSE_NORMAL:
1204 atomic_dec(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001205 ap_decrease_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001206 list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
1207 if (ap_msg->psmid != ap_dev->reply->psmid)
1208 continue;
1209 list_del_init(&ap_msg->list);
1210 ap_dev->pendingq_count--;
1211 ap_dev->drv->receive(ap_dev, ap_msg, ap_dev->reply);
1212 break;
1213 }
1214 if (ap_dev->queue_count > 0)
1215 *flags |= 1;
1216 break;
1217 case AP_RESPONSE_NO_PENDING_REPLY:
1218 if (status.queue_empty) {
1219 /* The card shouldn't forget requests but who knows. */
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +02001220 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001221 ap_dev->queue_count = 0;
1222 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1223 ap_dev->requestq_count += ap_dev->pendingq_count;
1224 ap_dev->pendingq_count = 0;
1225 } else
1226 *flags |= 2;
1227 break;
1228 default:
1229 return -ENODEV;
1230 }
1231 return 0;
1232}
1233
1234/**
Felix Beck1749a812008-04-17 07:46:28 +02001235 * ap_poll_write(): Send messages from the request queue to an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001236 * @ap_dev: pointer to the AP device
1237 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1238 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001239 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001240 * Returns 0 if the device is still present, -ENODEV if not.
1241 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001242static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001243{
1244 struct ap_queue_status status;
1245 struct ap_message *ap_msg;
1246
1247 if (ap_dev->requestq_count <= 0 ||
1248 ap_dev->queue_count >= ap_dev->queue_depth)
1249 return 0;
1250 /* Start the next request on the queue. */
1251 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
1252 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001253 ap_msg->message, ap_msg->length, ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001254 switch (status.response_code) {
1255 case AP_RESPONSE_NORMAL:
1256 atomic_inc(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001257 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001258 list_move_tail(&ap_msg->list, &ap_dev->pendingq);
1259 ap_dev->requestq_count--;
1260 ap_dev->pendingq_count++;
1261 if (ap_dev->queue_count < ap_dev->queue_depth &&
1262 ap_dev->requestq_count > 0)
1263 *flags |= 1;
1264 *flags |= 2;
1265 break;
1266 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001267 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001268 *flags |= 2;
1269 break;
1270 case AP_RESPONSE_MESSAGE_TOO_BIG:
Felix Becka6a5d732009-12-07 12:51:55 +01001271 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001272 return -EINVAL;
1273 default:
1274 return -ENODEV;
1275 }
1276 return 0;
1277}
1278
1279/**
Felix Beck1749a812008-04-17 07:46:28 +02001280 * ap_poll_queue(): Poll AP device for pending replies and send new messages.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001281 * @ap_dev: pointer to the bus device
1282 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1283 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001284 *
1285 * Poll AP device for pending replies and send new messages. If either
1286 * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001287 * Returns 0.
1288 */
1289static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
1290{
1291 int rc;
1292
1293 rc = ap_poll_read(ap_dev, flags);
1294 if (rc)
1295 return rc;
1296 return ap_poll_write(ap_dev, flags);
1297}
1298
1299/**
Felix Beck1749a812008-04-17 07:46:28 +02001300 * __ap_queue_message(): Queue a message to a device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001301 * @ap_dev: pointer to the AP device
1302 * @ap_msg: the message to be queued
Felix Beck1749a812008-04-17 07:46:28 +02001303 *
1304 * Queue a message to a device. Returns 0 if successful.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001305 */
1306static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1307{
1308 struct ap_queue_status status;
1309
1310 if (list_empty(&ap_dev->requestq) &&
1311 ap_dev->queue_count < ap_dev->queue_depth) {
1312 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001313 ap_msg->message, ap_msg->length,
1314 ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001315 switch (status.response_code) {
1316 case AP_RESPONSE_NORMAL:
1317 list_add_tail(&ap_msg->list, &ap_dev->pendingq);
1318 atomic_inc(&ap_poll_requests);
1319 ap_dev->pendingq_count++;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001320 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001321 ap_dev->total_request_count++;
1322 break;
1323 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001324 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001325 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1326 ap_dev->requestq_count++;
1327 ap_dev->total_request_count++;
1328 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +01001329 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001330 case AP_RESPONSE_MESSAGE_TOO_BIG:
1331 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
1332 return -EINVAL;
1333 default: /* Device is gone. */
1334 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
1335 return -ENODEV;
1336 }
1337 } else {
1338 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1339 ap_dev->requestq_count++;
1340 ap_dev->total_request_count++;
1341 return -EBUSY;
1342 }
1343 ap_schedule_poll_timer();
1344 return 0;
1345}
1346
1347void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1348{
1349 unsigned long flags;
1350 int rc;
1351
1352 spin_lock_bh(&ap_dev->lock);
1353 if (!ap_dev->unregistered) {
1354 /* Make room on the queue by polling for finished requests. */
1355 rc = ap_poll_queue(ap_dev, &flags);
1356 if (!rc)
1357 rc = __ap_queue_message(ap_dev, ap_msg);
1358 if (!rc)
1359 wake_up(&ap_poll_wait);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001360 if (rc == -ENODEV)
1361 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001362 } else {
1363 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001364 rc = -ENODEV;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001365 }
1366 spin_unlock_bh(&ap_dev->lock);
1367 if (rc == -ENODEV)
1368 device_unregister(&ap_dev->device);
1369}
1370EXPORT_SYMBOL(ap_queue_message);
1371
1372/**
Felix Beck1749a812008-04-17 07:46:28 +02001373 * ap_cancel_message(): Cancel a crypto request.
1374 * @ap_dev: The AP device that has the message queued
1375 * @ap_msg: The message that is to be removed
1376 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001377 * Cancel a crypto request. This is done by removing the request
Felix Beck1749a812008-04-17 07:46:28 +02001378 * from the device pending or request queue. Note that the
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001379 * request stays on the AP queue. When it finishes the message
1380 * reply will be discarded because the psmid can't be found.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001381 */
1382void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1383{
1384 struct ap_message *tmp;
1385
1386 spin_lock_bh(&ap_dev->lock);
1387 if (!list_empty(&ap_msg->list)) {
1388 list_for_each_entry(tmp, &ap_dev->pendingq, list)
1389 if (tmp->psmid == ap_msg->psmid) {
1390 ap_dev->pendingq_count--;
1391 goto found;
1392 }
1393 ap_dev->requestq_count--;
1394 found:
1395 list_del_init(&ap_msg->list);
1396 }
1397 spin_unlock_bh(&ap_dev->lock);
1398}
1399EXPORT_SYMBOL(ap_cancel_message);
1400
1401/**
Felix Beck1749a812008-04-17 07:46:28 +02001402 * ap_poll_timeout(): AP receive polling for finished AP requests.
Felix Beckfe137232008-07-14 09:59:08 +02001403 * @unused: Unused pointer.
Felix Beck1749a812008-04-17 07:46:28 +02001404 *
Felix Beckfe137232008-07-14 09:59:08 +02001405 * Schedules the AP tasklet using a high resolution timer.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001406 */
Felix Beckfe137232008-07-14 09:59:08 +02001407static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001408{
1409 tasklet_schedule(&ap_tasklet);
Felix Beckfe137232008-07-14 09:59:08 +02001410 return HRTIMER_NORESTART;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001411}
1412
1413/**
Felix Beck1749a812008-04-17 07:46:28 +02001414 * ap_reset(): Reset a not responding AP device.
1415 * @ap_dev: Pointer to the AP device
1416 *
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001417 * Reset a not responding AP device and move all requests from the
1418 * pending queue to the request queue.
1419 */
1420static void ap_reset(struct ap_device *ap_dev)
1421{
1422 int rc;
1423
1424 ap_dev->reset = AP_RESET_IGNORE;
1425 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
1426 ap_dev->queue_count = 0;
1427 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1428 ap_dev->requestq_count += ap_dev->pendingq_count;
1429 ap_dev->pendingq_count = 0;
1430 rc = ap_init_queue(ap_dev->qid);
1431 if (rc == -ENODEV)
1432 ap_dev->unregistered = 1;
1433}
1434
Christian Maaser43c207e62008-12-25 13:38:42 +01001435static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001436{
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001437 if (!ap_dev->unregistered) {
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001438 if (ap_poll_queue(ap_dev, flags))
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001439 ap_dev->unregistered = 1;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001440 if (ap_dev->reset == AP_RESET_DO)
1441 ap_reset(ap_dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001442 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001443 return 0;
1444}
1445
Felix Beck1749a812008-04-17 07:46:28 +02001446/**
1447 * ap_poll_all(): Poll all AP devices.
1448 * @dummy: Unused variable
1449 *
1450 * Poll all AP devices on the bus in a round robin fashion. Continue
1451 * polling until bit 2^0 of the control flags is not set. If bit 2^1
1452 * of the control flags has been set arm the poll timer.
1453 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001454static void ap_poll_all(unsigned long dummy)
1455{
1456 unsigned long flags;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001457 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001458
Felix Beckcb17a632008-12-25 13:38:41 +01001459 /* Reset the indicator if interrupts are used. Thus new interrupts can
1460 * be received. Doing it in the beginning of the tasklet is therefor
1461 * important that no requests on any AP get lost.
1462 */
1463 if (ap_using_interrupts())
1464 xchg((u8 *)ap_interrupt_indicator, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001465 do {
1466 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001467 spin_lock(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001468 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001469 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001470 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001471 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001472 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001473 spin_unlock(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001474 } while (flags & 1);
1475 if (flags & 2)
1476 ap_schedule_poll_timer();
1477}
1478
1479/**
Felix Beck1749a812008-04-17 07:46:28 +02001480 * ap_poll_thread(): Thread that polls for finished requests.
1481 * @data: Unused pointer
1482 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001483 * AP bus poll thread. The purpose of this thread is to poll for
1484 * finished requests in a loop if there is a "free" cpu - that is
1485 * a cpu that doesn't have anything better to do. The polling stops
1486 * as soon as there is another task or if all messages have been
1487 * delivered.
1488 */
1489static int ap_poll_thread(void *data)
1490{
1491 DECLARE_WAITQUEUE(wait, current);
1492 unsigned long flags;
1493 int requests;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001494 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001495
Christian Borntraegerd83682b2006-10-06 16:38:22 +02001496 set_user_nice(current, 19);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001497 while (1) {
Felix Beck772f5472009-06-22 12:08:16 +02001498 if (ap_suspend_flag)
1499 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001500 if (need_resched()) {
1501 schedule();
1502 continue;
1503 }
1504 add_wait_queue(&ap_poll_wait, &wait);
1505 set_current_state(TASK_INTERRUPTIBLE);
1506 if (kthread_should_stop())
1507 break;
1508 requests = atomic_read(&ap_poll_requests);
1509 if (requests <= 0)
1510 schedule();
1511 set_current_state(TASK_RUNNING);
1512 remove_wait_queue(&ap_poll_wait, &wait);
1513
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001514 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001515 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001516 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001517 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001518 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001519 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001520 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001521 spin_unlock_bh(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001522 }
1523 set_current_state(TASK_RUNNING);
1524 remove_wait_queue(&ap_poll_wait, &wait);
1525 return 0;
1526}
1527
1528static int ap_poll_thread_start(void)
1529{
1530 int rc;
1531
Felix Beck772f5472009-06-22 12:08:16 +02001532 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beckcb17a632008-12-25 13:38:41 +01001533 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001534 mutex_lock(&ap_poll_thread_mutex);
1535 if (!ap_poll_kthread) {
1536 ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
1537 rc = IS_ERR(ap_poll_kthread) ? PTR_ERR(ap_poll_kthread) : 0;
1538 if (rc)
1539 ap_poll_kthread = NULL;
1540 }
1541 else
1542 rc = 0;
1543 mutex_unlock(&ap_poll_thread_mutex);
1544 return rc;
1545}
1546
1547static void ap_poll_thread_stop(void)
1548{
1549 mutex_lock(&ap_poll_thread_mutex);
1550 if (ap_poll_kthread) {
1551 kthread_stop(ap_poll_kthread);
1552 ap_poll_kthread = NULL;
1553 }
1554 mutex_unlock(&ap_poll_thread_mutex);
1555}
1556
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001557/**
Felix Beck1749a812008-04-17 07:46:28 +02001558 * ap_request_timeout(): Handling of request timeouts
1559 * @data: Holds the AP device.
1560 *
1561 * Handles request timeouts.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001562 */
1563static void ap_request_timeout(unsigned long data)
1564{
1565 struct ap_device *ap_dev = (struct ap_device *) data;
1566
Felix Beckcb17a632008-12-25 13:38:41 +01001567 if (ap_dev->reset == AP_RESET_ARMED) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001568 ap_dev->reset = AP_RESET_DO;
Felix Beckcb17a632008-12-25 13:38:41 +01001569
1570 if (ap_using_interrupts())
1571 tasklet_schedule(&ap_tasklet);
1572 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001573}
1574
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001575static void ap_reset_domain(void)
1576{
1577 int i;
1578
Ralph Wuerthner39aa7cf2007-10-12 16:11:29 +02001579 if (ap_domain_index != -1)
1580 for (i = 0; i < AP_DEVICES; i++)
1581 ap_reset_queue(AP_MKQID(i, ap_domain_index));
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001582}
1583
1584static void ap_reset_all(void)
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001585{
1586 int i, j;
1587
1588 for (i = 0; i < AP_DOMAINS; i++)
1589 for (j = 0; j < AP_DEVICES; j++)
1590 ap_reset_queue(AP_MKQID(j, i));
1591}
1592
1593static struct reset_call ap_reset_call = {
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001594 .fn = ap_reset_all,
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001595};
1596
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001597/**
Felix Beck1749a812008-04-17 07:46:28 +02001598 * ap_module_init(): The module initialization code.
1599 *
1600 * Initializes the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001601 */
1602int __init ap_module_init(void)
1603{
1604 int rc, i;
1605
1606 if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001607 pr_warning("%d is not a valid cryptographic domain\n",
1608 ap_domain_index);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001609 return -EINVAL;
1610 }
Felix Beck5314af62009-09-22 22:58:51 +02001611 /* In resume callback we need to know if the user had set the domain.
1612 * If so, we can not just reset it.
1613 */
1614 if (ap_domain_index >= 0)
1615 user_set_domain = 1;
1616
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001617 if (ap_instructions_available() != 0) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001618 pr_warning("The hardware system does not support "
1619 "AP instructions\n");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001620 return -ENODEV;
1621 }
Felix Beckcb17a632008-12-25 13:38:41 +01001622 if (ap_interrupts_available()) {
1623 isc_register(AP_ISC);
1624 ap_interrupt_indicator = s390_register_adapter_interrupt(
1625 &ap_interrupt_handler, NULL, AP_ISC);
1626 if (IS_ERR(ap_interrupt_indicator)) {
1627 ap_interrupt_indicator = NULL;
1628 isc_unregister(AP_ISC);
1629 }
1630 }
1631
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001632 register_reset_call(&ap_reset_call);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001633
1634 /* Create /sys/bus/ap. */
1635 rc = bus_register(&ap_bus_type);
1636 if (rc)
1637 goto out;
1638 for (i = 0; ap_bus_attrs[i]; i++) {
1639 rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]);
1640 if (rc)
1641 goto out_bus;
1642 }
1643
1644 /* Create /sys/devices/ap. */
Mark McLoughlin035da162008-12-15 12:58:29 +00001645 ap_root_device = root_device_register("ap");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001646 rc = IS_ERR(ap_root_device) ? PTR_ERR(ap_root_device) : 0;
1647 if (rc)
1648 goto out_bus;
1649
1650 ap_work_queue = create_singlethread_workqueue("kapwork");
1651 if (!ap_work_queue) {
1652 rc = -ENOMEM;
1653 goto out_root;
1654 }
1655
1656 if (ap_select_domain() == 0)
1657 ap_scan_bus(NULL);
1658
Felix Beck1749a812008-04-17 07:46:28 +02001659 /* Setup the AP bus rescan timer. */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001660 init_timer(&ap_config_timer);
1661 ap_config_timer.function = ap_config_timeout;
1662 ap_config_timer.data = 0;
1663 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1664 add_timer(&ap_config_timer);
1665
Felix Beckfe137232008-07-14 09:59:08 +02001666 /* Setup the high resultion poll timer.
1667 * If we are running under z/VM adjust polling to z/VM polling rate.
1668 */
1669 if (MACHINE_IS_VM)
1670 poll_timeout = 1500000;
Felix Beck93521312009-12-07 12:52:00 +01001671 spin_lock_init(&ap_poll_timer_lock);
Felix Beckfe137232008-07-14 09:59:08 +02001672 hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1673 ap_poll_timer.function = ap_poll_timeout;
1674
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001675 /* Start the low priority AP bus poll thread. */
1676 if (ap_thread_flag) {
1677 rc = ap_poll_thread_start();
1678 if (rc)
1679 goto out_work;
1680 }
1681
1682 return 0;
1683
1684out_work:
1685 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001686 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001687 destroy_workqueue(ap_work_queue);
1688out_root:
Mark McLoughlin035da162008-12-15 12:58:29 +00001689 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001690out_bus:
1691 while (i--)
1692 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1693 bus_unregister(&ap_bus_type);
1694out:
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001695 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001696 if (ap_using_interrupts()) {
1697 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1698 isc_unregister(AP_ISC);
1699 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001700 return rc;
1701}
1702
1703static int __ap_match_all(struct device *dev, void *data)
1704{
1705 return 1;
1706}
1707
1708/**
Felix Beck1749a812008-04-17 07:46:28 +02001709 * ap_modules_exit(): The module termination code
1710 *
1711 * Terminates the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001712 */
1713void ap_module_exit(void)
1714{
1715 int i;
1716 struct device *dev;
1717
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001718 ap_reset_domain();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001719 ap_poll_thread_stop();
1720 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001721 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001722 destroy_workqueue(ap_work_queue);
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001723 tasklet_kill(&ap_tasklet);
Mark McLoughlin035da162008-12-15 12:58:29 +00001724 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001725 while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
1726 __ap_match_all)))
1727 {
1728 device_unregister(dev);
1729 put_device(dev);
1730 }
1731 for (i = 0; ap_bus_attrs[i]; i++)
1732 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1733 bus_unregister(&ap_bus_type);
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001734 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001735 if (ap_using_interrupts()) {
1736 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1737 isc_unregister(AP_ISC);
1738 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001739}
1740
1741#ifndef CONFIG_ZCRYPT_MONOLITHIC
1742module_init(ap_module_init);
1743module_exit(ap_module_exit);
1744#endif