blob: 16e4a25596e78a03e53adc88d6170008b1ef3f2a [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
Felix Beckb1f933d2011-01-05 12:47:44 +0100225static inline struct ap_queue_status __ap_4096_commands_available(ap_qid_t qid,
226 int *support)
227{
228 register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
229 register struct ap_queue_status reg1 asm ("1");
230 register unsigned long reg2 asm ("2") = 0UL;
231
232 asm volatile(
233 ".long 0xb2af0000\n"
234 "0: la %1,0\n"
235 "1:\n"
236 EX_TABLE(0b, 1b)
237 : "+d" (reg0), "=d" (reg1), "=d" (reg2)
238 :
239 : "cc");
240
241 if (reg2 & 0x6000000000000000ULL)
242 *support = 1;
243 else
244 *support = 0;
245
246 return reg1;
247}
248
249/**
250 * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
251 * support.
252 * @qid: The AP queue number
253 *
254 * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
255 */
256int ap_4096_commands_available(ap_qid_t qid)
257{
258 struct ap_queue_status status;
259 int i, support = 0;
260 status = __ap_4096_commands_available(qid, &support);
261
262 for (i = 0; i < AP_MAX_RESET; i++) {
263 switch (status.response_code) {
264 case AP_RESPONSE_NORMAL:
265 return support;
266 case AP_RESPONSE_RESET_IN_PROGRESS:
267 case AP_RESPONSE_BUSY:
268 break;
269 case AP_RESPONSE_Q_NOT_AVAIL:
270 case AP_RESPONSE_DECONFIGURED:
271 case AP_RESPONSE_CHECKSTOPPED:
272 case AP_RESPONSE_INVALID_ADDRESS:
273 return 0;
274 case AP_RESPONSE_OTHERWISE_CHANGED:
275 break;
276 default:
277 break;
278 }
279 if (i < AP_MAX_RESET - 1) {
280 udelay(5);
281 status = __ap_4096_commands_available(qid, &support);
282 }
283 }
284 return support;
285}
286EXPORT_SYMBOL(ap_4096_commands_available);
287
Felix Beckcb17a632008-12-25 13:38:41 +0100288/**
289 * ap_queue_enable_interruption(): Enable interruption on an AP.
290 * @qid: The AP queue number
291 * @ind: the notification indicator byte
292 *
293 * Enables interruption on AP queue via ap_queue_interruption_control(). Based
294 * on the return value it waits a while and tests the AP queue if interrupts
295 * have been switched on using ap_test_queue().
296 */
297static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
298{
299#ifdef CONFIG_64BIT
300 struct ap_queue_status status;
301 int t_depth, t_device_type, rc, i;
302
303 rc = -EBUSY;
304 status = ap_queue_interruption_control(qid, ind);
305
306 for (i = 0; i < AP_MAX_RESET; i++) {
307 switch (status.response_code) {
308 case AP_RESPONSE_NORMAL:
309 if (status.int_enabled)
310 return 0;
311 break;
312 case AP_RESPONSE_RESET_IN_PROGRESS:
313 case AP_RESPONSE_BUSY:
314 break;
315 case AP_RESPONSE_Q_NOT_AVAIL:
316 case AP_RESPONSE_DECONFIGURED:
317 case AP_RESPONSE_CHECKSTOPPED:
318 case AP_RESPONSE_INVALID_ADDRESS:
319 return -ENODEV;
320 case AP_RESPONSE_OTHERWISE_CHANGED:
321 if (status.int_enabled)
322 return 0;
323 break;
324 default:
325 break;
326 }
327 if (i < AP_MAX_RESET - 1) {
328 udelay(5);
329 status = ap_test_queue(qid, &t_depth, &t_device_type);
330 }
331 }
332 return rc;
333#else
334 return -EINVAL;
335#endif
336}
337
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200338/**
Felix Beck1749a812008-04-17 07:46:28 +0200339 * __ap_send(): Send message to adjunct processor queue.
340 * @qid: The AP queue number
341 * @psmid: The program supplied message identifier
342 * @msg: The message text
343 * @length: The message length
Felix Becka6a5d732009-12-07 12:51:55 +0100344 * @special: Special Bit
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200345 *
Felix Beck1749a812008-04-17 07:46:28 +0200346 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200347 * Condition code 1 on NQAP can't happen because the L bit is 1.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200348 * Condition code 2 on NQAP also means the send is incomplete,
349 * because a segment boundary was reached. The NQAP is repeated.
350 */
351static inline struct ap_queue_status
Felix Becka6a5d732009-12-07 12:51:55 +0100352__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length,
353 unsigned int special)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200354{
355 typedef struct { char _[length]; } msgblock;
356 register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
357 register struct ap_queue_status reg1 asm ("1");
358 register unsigned long reg2 asm ("2") = (unsigned long) msg;
359 register unsigned long reg3 asm ("3") = (unsigned long) length;
360 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
361 register unsigned long reg5 asm ("5") = (unsigned int) psmid;
362
Felix Becka6a5d732009-12-07 12:51:55 +0100363 if (special == 1)
364 reg0 |= 0x400000UL;
365
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200366 asm volatile (
367 "0: .long 0xb2ad0042\n" /* DQAP */
368 " brc 2,0b"
369 : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
370 : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg)
371 : "cc" );
372 return reg1;
373}
374
375int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
376{
377 struct ap_queue_status status;
378
Felix Becka6a5d732009-12-07 12:51:55 +0100379 status = __ap_send(qid, psmid, msg, length, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200380 switch (status.response_code) {
381 case AP_RESPONSE_NORMAL:
382 return 0;
383 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200384 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200385 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +0100386 case AP_RESPONSE_REQ_FAC_NOT_INST:
387 return -EINVAL;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200388 default: /* Device is gone. */
389 return -ENODEV;
390 }
391}
392EXPORT_SYMBOL(ap_send);
393
Felix Beck1749a812008-04-17 07:46:28 +0200394/**
395 * __ap_recv(): Receive message from adjunct processor queue.
396 * @qid: The AP queue number
397 * @psmid: Pointer to program supplied message identifier
398 * @msg: The message text
399 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200400 *
Felix Beck1749a812008-04-17 07:46:28 +0200401 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200402 * Condition code 1 on DQAP means the receive has taken place
403 * but only partially. The response is incomplete, hence the
404 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200405 * Condition code 2 on DQAP also means the receive is incomplete,
406 * this time because a segment boundary was reached. Again, the
407 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200408 * Note that gpr2 is used by the DQAP instruction to keep track of
409 * any 'residual' length, in case the instruction gets interrupted.
410 * Hence it gets zeroed before the instruction.
411 */
412static inline struct ap_queue_status
413__ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
414{
415 typedef struct { char _[length]; } msgblock;
416 register unsigned long reg0 asm("0") = qid | 0x80000000UL;
417 register struct ap_queue_status reg1 asm ("1");
418 register unsigned long reg2 asm("2") = 0UL;
419 register unsigned long reg4 asm("4") = (unsigned long) msg;
420 register unsigned long reg5 asm("5") = (unsigned long) length;
421 register unsigned long reg6 asm("6") = 0UL;
422 register unsigned long reg7 asm("7") = 0UL;
423
424
425 asm volatile(
426 "0: .long 0xb2ae0064\n"
427 " brc 6,0b\n"
428 : "+d" (reg0), "=d" (reg1), "+d" (reg2),
429 "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
430 "=m" (*(msgblock *) msg) : : "cc" );
431 *psmid = (((unsigned long long) reg6) << 32) + reg7;
432 return reg1;
433}
434
435int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
436{
437 struct ap_queue_status status;
438
439 status = __ap_recv(qid, psmid, msg, length);
440 switch (status.response_code) {
441 case AP_RESPONSE_NORMAL:
442 return 0;
443 case AP_RESPONSE_NO_PENDING_REPLY:
444 if (status.queue_empty)
445 return -ENOENT;
446 return -EBUSY;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200447 case AP_RESPONSE_RESET_IN_PROGRESS:
448 return -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200449 default:
450 return -ENODEV;
451 }
452}
453EXPORT_SYMBOL(ap_recv);
454
455/**
Felix Beck1749a812008-04-17 07:46:28 +0200456 * ap_query_queue(): Check if an AP queue is available.
457 * @qid: The AP queue number
458 * @queue_depth: Pointer to queue depth value
459 * @device_type: Pointer to device type value
460 *
461 * The test is repeated for AP_MAX_RESET times.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200462 */
463static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
464{
465 struct ap_queue_status status;
466 int t_depth, t_device_type, rc, i;
467
468 rc = -EBUSY;
469 for (i = 0; i < AP_MAX_RESET; i++) {
470 status = ap_test_queue(qid, &t_depth, &t_device_type);
471 switch (status.response_code) {
472 case AP_RESPONSE_NORMAL:
473 *queue_depth = t_depth + 1;
474 *device_type = t_device_type;
475 rc = 0;
476 break;
477 case AP_RESPONSE_Q_NOT_AVAIL:
478 rc = -ENODEV;
479 break;
480 case AP_RESPONSE_RESET_IN_PROGRESS:
481 break;
482 case AP_RESPONSE_DECONFIGURED:
483 rc = -ENODEV;
484 break;
485 case AP_RESPONSE_CHECKSTOPPED:
486 rc = -ENODEV;
487 break;
Felix Beckcb17a632008-12-25 13:38:41 +0100488 case AP_RESPONSE_INVALID_ADDRESS:
489 rc = -ENODEV;
490 break;
491 case AP_RESPONSE_OTHERWISE_CHANGED:
492 break;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200493 case AP_RESPONSE_BUSY:
494 break;
495 default:
496 BUG();
497 }
498 if (rc != -EBUSY)
499 break;
500 if (i < AP_MAX_RESET - 1)
501 udelay(5);
502 }
503 return rc;
504}
505
506/**
Felix Beck1749a812008-04-17 07:46:28 +0200507 * ap_init_queue(): Reset an AP queue.
508 * @qid: The AP queue number
509 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200510 * Reset an AP queue and wait for it to become available again.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200511 */
512static int ap_init_queue(ap_qid_t qid)
513{
514 struct ap_queue_status status;
515 int rc, dummy, i;
516
517 rc = -ENODEV;
518 status = ap_reset_queue(qid);
519 for (i = 0; i < AP_MAX_RESET; i++) {
520 switch (status.response_code) {
521 case AP_RESPONSE_NORMAL:
522 if (status.queue_empty)
523 rc = 0;
524 break;
525 case AP_RESPONSE_Q_NOT_AVAIL:
526 case AP_RESPONSE_DECONFIGURED:
527 case AP_RESPONSE_CHECKSTOPPED:
528 i = AP_MAX_RESET; /* return with -ENODEV */
529 break;
530 case AP_RESPONSE_RESET_IN_PROGRESS:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200531 rc = -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200532 case AP_RESPONSE_BUSY:
533 default:
534 break;
535 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200536 if (rc != -ENODEV && rc != -EBUSY)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200537 break;
538 if (i < AP_MAX_RESET - 1) {
539 udelay(5);
540 status = ap_test_queue(qid, &dummy, &dummy);
541 }
542 }
Felix Beckcb17a632008-12-25 13:38:41 +0100543 if (rc == 0 && ap_using_interrupts()) {
544 rc = ap_queue_enable_interruption(qid, ap_interrupt_indicator);
545 /* If interruption mode is supported by the machine,
546 * but an AP can not be enabled for interruption then
547 * the AP will be discarded. */
548 if (rc)
549 pr_err("Registering adapter interrupts for "
550 "AP %d failed\n", AP_QID_DEVICE(qid));
551 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200552 return rc;
553}
554
555/**
Felix Beck1749a812008-04-17 07:46:28 +0200556 * ap_increase_queue_count(): Arm request timeout.
557 * @ap_dev: Pointer to an AP device.
558 *
559 * Arm request timeout if an AP device was idle and a new request is submitted.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200560 */
561static void ap_increase_queue_count(struct ap_device *ap_dev)
562{
563 int timeout = ap_dev->drv->request_timeout;
564
565 ap_dev->queue_count++;
566 if (ap_dev->queue_count == 1) {
567 mod_timer(&ap_dev->timeout, jiffies + timeout);
568 ap_dev->reset = AP_RESET_ARMED;
569 }
570}
571
572/**
Felix Beck1749a812008-04-17 07:46:28 +0200573 * ap_decrease_queue_count(): Decrease queue count.
574 * @ap_dev: Pointer to an AP device.
575 *
576 * If AP device is still alive, re-schedule request timeout if there are still
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200577 * pending requests.
578 */
579static void ap_decrease_queue_count(struct ap_device *ap_dev)
580{
581 int timeout = ap_dev->drv->request_timeout;
582
583 ap_dev->queue_count--;
584 if (ap_dev->queue_count > 0)
585 mod_timer(&ap_dev->timeout, jiffies + timeout);
586 else
Felix Beck1749a812008-04-17 07:46:28 +0200587 /*
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200588 * The timeout timer should to be disabled now - since
589 * del_timer_sync() is very expensive, we just tell via the
590 * reset flag to ignore the pending timeout timer.
591 */
592 ap_dev->reset = AP_RESET_IGNORE;
593}
594
Felix Beck1749a812008-04-17 07:46:28 +0200595/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200596 * AP device related attributes.
597 */
598static ssize_t ap_hwtype_show(struct device *dev,
599 struct device_attribute *attr, char *buf)
600{
601 struct ap_device *ap_dev = to_ap_dev(dev);
602 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type);
603}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200604
Christian Maaser43c207e62008-12-25 13:38:42 +0100605static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200606static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr,
607 char *buf)
608{
609 struct ap_device *ap_dev = to_ap_dev(dev);
610 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth);
611}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200612
Christian Maaser43c207e62008-12-25 13:38:42 +0100613static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200614static ssize_t ap_request_count_show(struct device *dev,
615 struct device_attribute *attr,
616 char *buf)
617{
618 struct ap_device *ap_dev = to_ap_dev(dev);
619 int rc;
620
621 spin_lock_bh(&ap_dev->lock);
622 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->total_request_count);
623 spin_unlock_bh(&ap_dev->lock);
624 return rc;
625}
626
627static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL);
628
629static ssize_t ap_modalias_show(struct device *dev,
630 struct device_attribute *attr, char *buf)
631{
632 return sprintf(buf, "ap:t%02X", to_ap_dev(dev)->device_type);
633}
634
635static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL);
636
637static struct attribute *ap_dev_attrs[] = {
638 &dev_attr_hwtype.attr,
639 &dev_attr_depth.attr,
640 &dev_attr_request_count.attr,
641 &dev_attr_modalias.attr,
642 NULL
643};
644static struct attribute_group ap_dev_attr_group = {
645 .attrs = ap_dev_attrs
646};
647
648/**
Felix Beck1749a812008-04-17 07:46:28 +0200649 * ap_bus_match()
650 * @dev: Pointer to device
651 * @drv: Pointer to device_driver
652 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200653 * AP bus driver registration/unregistration.
654 */
655static int ap_bus_match(struct device *dev, struct device_driver *drv)
656{
657 struct ap_device *ap_dev = to_ap_dev(dev);
658 struct ap_driver *ap_drv = to_ap_drv(drv);
659 struct ap_device_id *id;
660
Felix Beck1749a812008-04-17 07:46:28 +0200661 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200662 * Compare device type of the device with the list of
663 * supported types of the device_driver.
664 */
665 for (id = ap_drv->ids; id->match_flags; id++) {
666 if ((id->match_flags & AP_DEVICE_ID_MATCH_DEVICE_TYPE) &&
667 (id->dev_type != ap_dev->device_type))
668 continue;
669 return 1;
670 }
671 return 0;
672}
673
674/**
Felix Beck1749a812008-04-17 07:46:28 +0200675 * ap_uevent(): Uevent function for AP devices.
676 * @dev: Pointer to device
677 * @env: Pointer to kobj_uevent_env
678 *
679 * It sets up a single environment variable DEV_TYPE which contains the
680 * hardware device type.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200681 */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200682static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200683{
684 struct ap_device *ap_dev = to_ap_dev(dev);
Kay Sievers7eff2e72007-08-14 15:15:12 +0200685 int retval = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200686
687 if (!ap_dev)
688 return -ENODEV;
689
690 /* Set up DEV_TYPE environment variable. */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200691 retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700692 if (retval)
693 return retval;
694
Cornelia Huck66a4263b2006-12-04 15:40:10 +0100695 /* Add MODALIAS= */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200696 retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700697
Eric Rannaudbf624562007-03-30 22:23:12 -0700698 return retval;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200699}
700
Felix Beck772f5472009-06-22 12:08:16 +0200701static int ap_bus_suspend(struct device *dev, pm_message_t state)
702{
703 struct ap_device *ap_dev = to_ap_dev(dev);
704 unsigned long flags;
705
706 if (!ap_suspend_flag) {
707 ap_suspend_flag = 1;
708
709 /* Disable scanning for devices, thus we do not want to scan
710 * for them after removing.
711 */
712 del_timer_sync(&ap_config_timer);
713 if (ap_work_queue != NULL) {
714 destroy_workqueue(ap_work_queue);
715 ap_work_queue = NULL;
716 }
Felix Beck5314af62009-09-22 22:58:51 +0200717
Felix Beck772f5472009-06-22 12:08:16 +0200718 tasklet_disable(&ap_tasklet);
719 }
720 /* Poll on the device until all requests are finished. */
721 do {
722 flags = 0;
Felix Beck95f15562009-09-11 10:28:51 +0200723 spin_lock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200724 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +0200725 spin_unlock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200726 } while ((flags & 1) || (flags & 2));
727
Felix Beck5314af62009-09-22 22:58:51 +0200728 spin_lock_bh(&ap_dev->lock);
729 ap_dev->unregistered = 1;
730 spin_unlock_bh(&ap_dev->lock);
731
Felix Beck772f5472009-06-22 12:08:16 +0200732 return 0;
733}
734
735static int ap_bus_resume(struct device *dev)
736{
737 int rc = 0;
738 struct ap_device *ap_dev = to_ap_dev(dev);
739
740 if (ap_suspend_flag) {
741 ap_suspend_flag = 0;
742 if (!ap_interrupts_available())
743 ap_interrupt_indicator = NULL;
Felix Beck5314af62009-09-22 22:58:51 +0200744 if (!user_set_domain) {
745 ap_domain_index = -1;
746 ap_select_domain();
747 }
Felix Beck772f5472009-06-22 12:08:16 +0200748 init_timer(&ap_config_timer);
749 ap_config_timer.function = ap_config_timeout;
750 ap_config_timer.data = 0;
751 ap_config_timer.expires = jiffies + ap_config_time * HZ;
752 add_timer(&ap_config_timer);
753 ap_work_queue = create_singlethread_workqueue("kapwork");
754 if (!ap_work_queue)
755 return -ENOMEM;
756 tasklet_enable(&ap_tasklet);
757 if (!ap_using_interrupts())
758 ap_schedule_poll_timer();
759 else
760 tasklet_schedule(&ap_tasklet);
761 if (ap_thread_flag)
762 rc = ap_poll_thread_start();
Felix Beck772f5472009-06-22 12:08:16 +0200763 }
Felix Beck5314af62009-09-22 22:58:51 +0200764 if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) {
765 spin_lock_bh(&ap_dev->lock);
766 ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid),
767 ap_domain_index);
768 spin_unlock_bh(&ap_dev->lock);
769 }
770 queue_work(ap_work_queue, &ap_config_work);
Felix Beck772f5472009-06-22 12:08:16 +0200771
772 return rc;
773}
774
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200775static struct bus_type ap_bus_type = {
776 .name = "ap",
777 .match = &ap_bus_match,
778 .uevent = &ap_uevent,
Felix Beck772f5472009-06-22 12:08:16 +0200779 .suspend = ap_bus_suspend,
780 .resume = ap_bus_resume
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200781};
782
783static int ap_device_probe(struct device *dev)
784{
785 struct ap_device *ap_dev = to_ap_dev(dev);
786 struct ap_driver *ap_drv = to_ap_drv(dev->driver);
787 int rc;
788
789 ap_dev->drv = ap_drv;
790 rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100791 if (!rc) {
Christian Maaser43c207e62008-12-25 13:38:42 +0100792 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100793 list_add(&ap_dev->list, &ap_device_list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100794 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100795 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200796 return rc;
797}
798
799/**
Felix Beck1749a812008-04-17 07:46:28 +0200800 * __ap_flush_queue(): Flush requests.
801 * @ap_dev: Pointer to the AP device
802 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200803 * Flush all requests from the request/pending queue of an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200804 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100805static void __ap_flush_queue(struct ap_device *ap_dev)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200806{
807 struct ap_message *ap_msg, *next;
808
809 list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
810 list_del_init(&ap_msg->list);
811 ap_dev->pendingq_count--;
812 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
813 }
814 list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
815 list_del_init(&ap_msg->list);
816 ap_dev->requestq_count--;
817 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
818 }
819}
820
821void ap_flush_queue(struct ap_device *ap_dev)
822{
823 spin_lock_bh(&ap_dev->lock);
824 __ap_flush_queue(ap_dev);
825 spin_unlock_bh(&ap_dev->lock);
826}
827EXPORT_SYMBOL(ap_flush_queue);
828
829static int ap_device_remove(struct device *dev)
830{
831 struct ap_device *ap_dev = to_ap_dev(dev);
832 struct ap_driver *ap_drv = ap_dev->drv;
833
Ralph Wuerthner4e562962006-10-04 20:02:05 +0200834 ap_flush_queue(ap_dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200835 del_timer_sync(&ap_dev->timeout);
Christian Maaser43c207e62008-12-25 13:38:42 +0100836 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +0100837 list_del_init(&ap_dev->list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100838 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100839 if (ap_drv->remove)
840 ap_drv->remove(ap_dev);
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +0200841 spin_lock_bh(&ap_dev->lock);
842 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
843 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200844 return 0;
845}
846
847int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
848 char *name)
849{
850 struct device_driver *drv = &ap_drv->driver;
851
852 drv->bus = &ap_bus_type;
853 drv->probe = ap_device_probe;
854 drv->remove = ap_device_remove;
855 drv->owner = owner;
856 drv->name = name;
857 return driver_register(drv);
858}
859EXPORT_SYMBOL(ap_driver_register);
860
861void ap_driver_unregister(struct ap_driver *ap_drv)
862{
863 driver_unregister(&ap_drv->driver);
864}
865EXPORT_SYMBOL(ap_driver_unregister);
866
Felix Beck1749a812008-04-17 07:46:28 +0200867/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200868 * AP bus attributes.
869 */
870static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
871{
872 return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
873}
874
875static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
876
877static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
878{
879 return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
880}
881
Felix Beckcb17a632008-12-25 13:38:41 +0100882static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
883{
884 return snprintf(buf, PAGE_SIZE, "%d\n",
885 ap_using_interrupts() ? 1 : 0);
886}
887
888static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL);
889
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200890static ssize_t ap_config_time_store(struct bus_type *bus,
891 const char *buf, size_t count)
892{
893 int time;
894
895 if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120)
896 return -EINVAL;
897 ap_config_time = time;
898 if (!timer_pending(&ap_config_timer) ||
899 !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) {
900 ap_config_timer.expires = jiffies + ap_config_time * HZ;
901 add_timer(&ap_config_timer);
902 }
903 return count;
904}
905
906static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store);
907
908static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf)
909{
910 return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
911}
912
913static ssize_t ap_poll_thread_store(struct bus_type *bus,
914 const char *buf, size_t count)
915{
916 int flag, rc;
917
918 if (sscanf(buf, "%d\n", &flag) != 1)
919 return -EINVAL;
920 if (flag) {
921 rc = ap_poll_thread_start();
922 if (rc)
923 return rc;
924 }
925 else
926 ap_poll_thread_stop();
927 return count;
928}
929
930static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
931
Felix Beckfe137232008-07-14 09:59:08 +0200932static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
933{
934 return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
935}
936
937static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
938 size_t count)
939{
940 unsigned long long time;
941 ktime_t hr_time;
942
943 /* 120 seconds = maximum poll interval */
Felix Beckcb17a632008-12-25 13:38:41 +0100944 if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 ||
945 time > 120000000000ULL)
Felix Beckfe137232008-07-14 09:59:08 +0200946 return -EINVAL;
947 poll_timeout = time;
948 hr_time = ktime_set(0, poll_timeout);
949
950 if (!hrtimer_is_queued(&ap_poll_timer) ||
Arjan van de Ven6c644ea2008-09-01 15:20:30 -0700951 !hrtimer_forward(&ap_poll_timer, hrtimer_get_expires(&ap_poll_timer), hr_time)) {
952 hrtimer_set_expires(&ap_poll_timer, hr_time);
953 hrtimer_start_expires(&ap_poll_timer, HRTIMER_MODE_ABS);
Felix Beckfe137232008-07-14 09:59:08 +0200954 }
955 return count;
956}
957
958static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
959
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200960static struct bus_attribute *const ap_bus_attrs[] = {
961 &bus_attr_ap_domain,
962 &bus_attr_config_time,
963 &bus_attr_poll_thread,
Felix Beckcb17a632008-12-25 13:38:41 +0100964 &bus_attr_ap_interrupts,
Felix Beckfe137232008-07-14 09:59:08 +0200965 &bus_attr_poll_timeout,
966 NULL,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200967};
968
969/**
Felix Beck1749a812008-04-17 07:46:28 +0200970 * ap_select_domain(): Select an AP domain.
971 *
972 * Pick one of the 16 AP domains.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200973 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100974static int ap_select_domain(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200975{
976 int queue_depth, device_type, count, max_count, best_domain;
977 int rc, i, j;
978
Felix Beck1749a812008-04-17 07:46:28 +0200979 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200980 * We want to use a single domain. Either the one specified with
981 * the "domain=" parameter or the domain with the maximum number
982 * of devices.
983 */
984 if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS)
985 /* Domain has already been selected. */
986 return 0;
987 best_domain = -1;
988 max_count = 0;
989 for (i = 0; i < AP_DOMAINS; i++) {
990 count = 0;
991 for (j = 0; j < AP_DEVICES; j++) {
992 ap_qid_t qid = AP_MKQID(j, i);
993 rc = ap_query_queue(qid, &queue_depth, &device_type);
994 if (rc)
995 continue;
996 count++;
997 }
998 if (count > max_count) {
999 max_count = count;
1000 best_domain = i;
1001 }
1002 }
1003 if (best_domain >= 0){
1004 ap_domain_index = best_domain;
1005 return 0;
1006 }
1007 return -ENODEV;
1008}
1009
1010/**
Felix Beck1749a812008-04-17 07:46:28 +02001011 * ap_probe_device_type(): Find the device type of an AP.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001012 * @ap_dev: pointer to the AP device.
Felix Beck1749a812008-04-17 07:46:28 +02001013 *
1014 * Find the device type if query queue returned a device type of 0.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001015 */
1016static int ap_probe_device_type(struct ap_device *ap_dev)
1017{
1018 static unsigned char msg[] = {
1019 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
1020 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1021 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
1022 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1023 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50,
1024 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,
1025 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00,
1026 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,
1027 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1028 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,
1029 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1030 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,
1031 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00,
1032 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1033 0x00,0x00,0x00,0x00,0xb8,0x05,0x00,0x00,
1034 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1035 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1036 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1037 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1038 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1039 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1040 0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,
1041 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1042 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
1043 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20,
1044 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,
1045 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22,
1046 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1047 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
1048 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,
1049 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,
1050 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,
1051 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1052 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,
1053 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00,
1054 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,
1055 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01,
1056 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,
1057 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68,
1058 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,
1059 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0,
1060 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,
1061 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04,
1062 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,
1063 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d,
1064 };
1065 struct ap_queue_status status;
1066 unsigned long long psmid;
1067 char *reply;
1068 int rc, i;
1069
1070 reply = (void *) get_zeroed_page(GFP_KERNEL);
1071 if (!reply) {
1072 rc = -ENOMEM;
1073 goto out;
1074 }
1075
1076 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
Felix Becka6a5d732009-12-07 12:51:55 +01001077 msg, sizeof(msg), 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001078 if (status.response_code != AP_RESPONSE_NORMAL) {
1079 rc = -ENODEV;
1080 goto out_free;
1081 }
1082
1083 /* Wait for the test message to complete. */
1084 for (i = 0; i < 6; i++) {
1085 mdelay(300);
1086 status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
1087 if (status.response_code == AP_RESPONSE_NORMAL &&
1088 psmid == 0x0102030405060708ULL)
1089 break;
1090 }
1091 if (i < 6) {
1092 /* Got an answer. */
1093 if (reply[0] == 0x00 && reply[1] == 0x86)
1094 ap_dev->device_type = AP_DEVICE_TYPE_PCICC;
1095 else
1096 ap_dev->device_type = AP_DEVICE_TYPE_PCICA;
1097 rc = 0;
1098 } else
1099 rc = -ENODEV;
1100
1101out_free:
1102 free_page((unsigned long) reply);
1103out:
1104 return rc;
1105}
1106
Felix Beckcb17a632008-12-25 13:38:41 +01001107static void ap_interrupt_handler(void *unused1, void *unused2)
1108{
Holger Dengler62d146f2011-01-05 12:47:38 +01001109 kstat_cpu(smp_processor_id()).irqs[IOINT_APB]++;
Felix Beckcb17a632008-12-25 13:38:41 +01001110 tasklet_schedule(&ap_tasklet);
1111}
1112
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001113/**
Felix Beck1749a812008-04-17 07:46:28 +02001114 * __ap_scan_bus(): Scan the AP bus.
1115 * @dev: Pointer to device
1116 * @data: Pointer to data
1117 *
1118 * Scan the AP bus for new devices.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001119 */
1120static int __ap_scan_bus(struct device *dev, void *data)
1121{
1122 return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data;
1123}
1124
1125static void ap_device_release(struct device *dev)
1126{
1127 struct ap_device *ap_dev = to_ap_dev(dev);
1128
1129 kfree(ap_dev);
1130}
1131
Al Viro4927b3f2006-12-06 19:18:20 +00001132static void ap_scan_bus(struct work_struct *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001133{
1134 struct ap_device *ap_dev;
1135 struct device *dev;
1136 ap_qid_t qid;
1137 int queue_depth, device_type;
1138 int rc, i;
1139
1140 if (ap_select_domain() != 0)
1141 return;
1142 for (i = 0; i < AP_DEVICES; i++) {
1143 qid = AP_MKQID(i, ap_domain_index);
1144 dev = bus_find_device(&ap_bus_type, NULL,
1145 (void *)(unsigned long)qid,
1146 __ap_scan_bus);
Ralph Wuerthnerf3b017d2006-10-27 12:39:26 +02001147 rc = ap_query_queue(qid, &queue_depth, &device_type);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001148 if (dev) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001149 if (rc == -EBUSY) {
1150 set_current_state(TASK_UNINTERRUPTIBLE);
1151 schedule_timeout(AP_RESET_TIMEOUT);
1152 rc = ap_query_queue(qid, &queue_depth,
1153 &device_type);
1154 }
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001155 ap_dev = to_ap_dev(dev);
1156 spin_lock_bh(&ap_dev->lock);
1157 if (rc || ap_dev->unregistered) {
1158 spin_unlock_bh(&ap_dev->lock);
Felix Beck5314af62009-09-22 22:58:51 +02001159 if (ap_dev->unregistered)
1160 i--;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001161 device_unregister(dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001162 put_device(dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001163 continue;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001164 }
1165 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001166 put_device(dev);
1167 continue;
1168 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001169 if (rc)
1170 continue;
1171 rc = ap_init_queue(qid);
1172 if (rc)
1173 continue;
1174 ap_dev = kzalloc(sizeof(*ap_dev), GFP_KERNEL);
1175 if (!ap_dev)
1176 break;
1177 ap_dev->qid = qid;
1178 ap_dev->queue_depth = queue_depth;
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001179 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001180 spin_lock_init(&ap_dev->lock);
1181 INIT_LIST_HEAD(&ap_dev->pendingq);
1182 INIT_LIST_HEAD(&ap_dev->requestq);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001183 INIT_LIST_HEAD(&ap_dev->list);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001184 setup_timer(&ap_dev->timeout, ap_request_timeout,
1185 (unsigned long) ap_dev);
Holger Denglercf2d0072011-05-23 10:24:30 +02001186 if (device_type == 0) {
1187 if (ap_probe_device_type(ap_dev)) {
1188 kfree(ap_dev);
1189 continue;
1190 }
1191 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001192 else
1193 ap_dev->device_type = device_type;
1194
1195 ap_dev->device.bus = &ap_bus_type;
1196 ap_dev->device.parent = ap_root_device;
Felix Beckedc44fa2009-09-11 10:28:52 +02001197 if (dev_set_name(&ap_dev->device, "card%02x",
1198 AP_QID_DEVICE(ap_dev->qid))) {
1199 kfree(ap_dev);
1200 continue;
1201 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001202 ap_dev->device.release = ap_device_release;
1203 rc = device_register(&ap_dev->device);
1204 if (rc) {
Sebastian Ottc6304932009-09-11 10:28:38 +02001205 put_device(&ap_dev->device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001206 continue;
1207 }
1208 /* Add device attributes. */
1209 rc = sysfs_create_group(&ap_dev->device.kobj,
1210 &ap_dev_attr_group);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001211 if (!rc) {
1212 spin_lock_bh(&ap_dev->lock);
1213 ap_dev->unregistered = 0;
1214 spin_unlock_bh(&ap_dev->lock);
1215 }
1216 else
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001217 device_unregister(&ap_dev->device);
1218 }
1219}
1220
1221static void
1222ap_config_timeout(unsigned long ptr)
1223{
1224 queue_work(ap_work_queue, &ap_config_work);
1225 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1226 add_timer(&ap_config_timer);
1227}
1228
1229/**
Felix Beck1749a812008-04-17 07:46:28 +02001230 * ap_schedule_poll_timer(): Schedule poll timer.
1231 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001232 * Set up the timer to run the poll tasklet
1233 */
1234static inline void ap_schedule_poll_timer(void)
1235{
Felix Beck8d406c62009-07-24 12:39:53 +02001236 ktime_t hr_time;
Felix Beck93521312009-12-07 12:52:00 +01001237
1238 spin_lock_bh(&ap_poll_timer_lock);
Felix Beck772f5472009-06-22 12:08:16 +02001239 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beck93521312009-12-07 12:52:00 +01001240 goto out;
Felix Beckfe137232008-07-14 09:59:08 +02001241 if (hrtimer_is_queued(&ap_poll_timer))
Felix Beck93521312009-12-07 12:52:00 +01001242 goto out;
Felix Beck8d406c62009-07-24 12:39:53 +02001243 if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
1244 hr_time = ktime_set(0, poll_timeout);
1245 hrtimer_forward_now(&ap_poll_timer, hr_time);
1246 hrtimer_restart(&ap_poll_timer);
1247 }
Felix Beck93521312009-12-07 12:52:00 +01001248out:
1249 spin_unlock_bh(&ap_poll_timer_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001250}
1251
1252/**
Felix Beck1749a812008-04-17 07:46:28 +02001253 * ap_poll_read(): Receive pending reply messages from an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001254 * @ap_dev: pointer to the AP device
1255 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1256 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001257 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001258 * Returns 0 if the device is still present, -ENODEV if not.
1259 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001260static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001261{
1262 struct ap_queue_status status;
1263 struct ap_message *ap_msg;
1264
1265 if (ap_dev->queue_count <= 0)
1266 return 0;
1267 status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
1268 ap_dev->reply->message, ap_dev->reply->length);
1269 switch (status.response_code) {
1270 case AP_RESPONSE_NORMAL:
1271 atomic_dec(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001272 ap_decrease_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001273 list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
1274 if (ap_msg->psmid != ap_dev->reply->psmid)
1275 continue;
1276 list_del_init(&ap_msg->list);
1277 ap_dev->pendingq_count--;
1278 ap_dev->drv->receive(ap_dev, ap_msg, ap_dev->reply);
1279 break;
1280 }
1281 if (ap_dev->queue_count > 0)
1282 *flags |= 1;
1283 break;
1284 case AP_RESPONSE_NO_PENDING_REPLY:
1285 if (status.queue_empty) {
1286 /* The card shouldn't forget requests but who knows. */
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +02001287 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001288 ap_dev->queue_count = 0;
1289 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1290 ap_dev->requestq_count += ap_dev->pendingq_count;
1291 ap_dev->pendingq_count = 0;
1292 } else
1293 *flags |= 2;
1294 break;
1295 default:
1296 return -ENODEV;
1297 }
1298 return 0;
1299}
1300
1301/**
Felix Beck1749a812008-04-17 07:46:28 +02001302 * ap_poll_write(): Send messages from the request queue to an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001303 * @ap_dev: pointer to the AP device
1304 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1305 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001306 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001307 * Returns 0 if the device is still present, -ENODEV if not.
1308 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001309static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001310{
1311 struct ap_queue_status status;
1312 struct ap_message *ap_msg;
1313
1314 if (ap_dev->requestq_count <= 0 ||
1315 ap_dev->queue_count >= ap_dev->queue_depth)
1316 return 0;
1317 /* Start the next request on the queue. */
1318 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
1319 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001320 ap_msg->message, ap_msg->length, ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001321 switch (status.response_code) {
1322 case AP_RESPONSE_NORMAL:
1323 atomic_inc(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001324 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001325 list_move_tail(&ap_msg->list, &ap_dev->pendingq);
1326 ap_dev->requestq_count--;
1327 ap_dev->pendingq_count++;
1328 if (ap_dev->queue_count < ap_dev->queue_depth &&
1329 ap_dev->requestq_count > 0)
1330 *flags |= 1;
1331 *flags |= 2;
1332 break;
1333 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001334 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001335 *flags |= 2;
1336 break;
1337 case AP_RESPONSE_MESSAGE_TOO_BIG:
Felix Becka6a5d732009-12-07 12:51:55 +01001338 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001339 return -EINVAL;
1340 default:
1341 return -ENODEV;
1342 }
1343 return 0;
1344}
1345
1346/**
Felix Beck1749a812008-04-17 07:46:28 +02001347 * ap_poll_queue(): Poll AP device for pending replies and send new messages.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001348 * @ap_dev: pointer to the bus device
1349 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1350 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001351 *
1352 * Poll AP device for pending replies and send new messages. If either
1353 * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001354 * Returns 0.
1355 */
1356static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
1357{
1358 int rc;
1359
1360 rc = ap_poll_read(ap_dev, flags);
1361 if (rc)
1362 return rc;
1363 return ap_poll_write(ap_dev, flags);
1364}
1365
1366/**
Felix Beck1749a812008-04-17 07:46:28 +02001367 * __ap_queue_message(): Queue a message to a device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001368 * @ap_dev: pointer to the AP device
1369 * @ap_msg: the message to be queued
Felix Beck1749a812008-04-17 07:46:28 +02001370 *
1371 * Queue a message to a device. Returns 0 if successful.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001372 */
1373static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1374{
1375 struct ap_queue_status status;
1376
1377 if (list_empty(&ap_dev->requestq) &&
1378 ap_dev->queue_count < ap_dev->queue_depth) {
1379 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001380 ap_msg->message, ap_msg->length,
1381 ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001382 switch (status.response_code) {
1383 case AP_RESPONSE_NORMAL:
1384 list_add_tail(&ap_msg->list, &ap_dev->pendingq);
1385 atomic_inc(&ap_poll_requests);
1386 ap_dev->pendingq_count++;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001387 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001388 ap_dev->total_request_count++;
1389 break;
1390 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001391 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001392 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1393 ap_dev->requestq_count++;
1394 ap_dev->total_request_count++;
1395 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +01001396 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001397 case AP_RESPONSE_MESSAGE_TOO_BIG:
1398 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
1399 return -EINVAL;
1400 default: /* Device is gone. */
1401 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
1402 return -ENODEV;
1403 }
1404 } else {
1405 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1406 ap_dev->requestq_count++;
1407 ap_dev->total_request_count++;
1408 return -EBUSY;
1409 }
1410 ap_schedule_poll_timer();
1411 return 0;
1412}
1413
1414void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1415{
1416 unsigned long flags;
1417 int rc;
1418
1419 spin_lock_bh(&ap_dev->lock);
1420 if (!ap_dev->unregistered) {
1421 /* Make room on the queue by polling for finished requests. */
1422 rc = ap_poll_queue(ap_dev, &flags);
1423 if (!rc)
1424 rc = __ap_queue_message(ap_dev, ap_msg);
1425 if (!rc)
1426 wake_up(&ap_poll_wait);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001427 if (rc == -ENODEV)
1428 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001429 } else {
1430 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001431 rc = -ENODEV;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001432 }
1433 spin_unlock_bh(&ap_dev->lock);
1434 if (rc == -ENODEV)
1435 device_unregister(&ap_dev->device);
1436}
1437EXPORT_SYMBOL(ap_queue_message);
1438
1439/**
Felix Beck1749a812008-04-17 07:46:28 +02001440 * ap_cancel_message(): Cancel a crypto request.
1441 * @ap_dev: The AP device that has the message queued
1442 * @ap_msg: The message that is to be removed
1443 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001444 * Cancel a crypto request. This is done by removing the request
Felix Beck1749a812008-04-17 07:46:28 +02001445 * from the device pending or request queue. Note that the
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001446 * request stays on the AP queue. When it finishes the message
1447 * reply will be discarded because the psmid can't be found.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001448 */
1449void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1450{
1451 struct ap_message *tmp;
1452
1453 spin_lock_bh(&ap_dev->lock);
1454 if (!list_empty(&ap_msg->list)) {
1455 list_for_each_entry(tmp, &ap_dev->pendingq, list)
1456 if (tmp->psmid == ap_msg->psmid) {
1457 ap_dev->pendingq_count--;
1458 goto found;
1459 }
1460 ap_dev->requestq_count--;
1461 found:
1462 list_del_init(&ap_msg->list);
1463 }
1464 spin_unlock_bh(&ap_dev->lock);
1465}
1466EXPORT_SYMBOL(ap_cancel_message);
1467
1468/**
Felix Beck1749a812008-04-17 07:46:28 +02001469 * ap_poll_timeout(): AP receive polling for finished AP requests.
Felix Beckfe137232008-07-14 09:59:08 +02001470 * @unused: Unused pointer.
Felix Beck1749a812008-04-17 07:46:28 +02001471 *
Felix Beckfe137232008-07-14 09:59:08 +02001472 * Schedules the AP tasklet using a high resolution timer.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001473 */
Felix Beckfe137232008-07-14 09:59:08 +02001474static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001475{
1476 tasklet_schedule(&ap_tasklet);
Felix Beckfe137232008-07-14 09:59:08 +02001477 return HRTIMER_NORESTART;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001478}
1479
1480/**
Felix Beck1749a812008-04-17 07:46:28 +02001481 * ap_reset(): Reset a not responding AP device.
1482 * @ap_dev: Pointer to the AP device
1483 *
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001484 * Reset a not responding AP device and move all requests from the
1485 * pending queue to the request queue.
1486 */
1487static void ap_reset(struct ap_device *ap_dev)
1488{
1489 int rc;
1490
1491 ap_dev->reset = AP_RESET_IGNORE;
1492 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
1493 ap_dev->queue_count = 0;
1494 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1495 ap_dev->requestq_count += ap_dev->pendingq_count;
1496 ap_dev->pendingq_count = 0;
1497 rc = ap_init_queue(ap_dev->qid);
1498 if (rc == -ENODEV)
1499 ap_dev->unregistered = 1;
1500}
1501
Christian Maaser43c207e62008-12-25 13:38:42 +01001502static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001503{
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001504 if (!ap_dev->unregistered) {
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001505 if (ap_poll_queue(ap_dev, flags))
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001506 ap_dev->unregistered = 1;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001507 if (ap_dev->reset == AP_RESET_DO)
1508 ap_reset(ap_dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001509 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001510 return 0;
1511}
1512
Felix Beck1749a812008-04-17 07:46:28 +02001513/**
1514 * ap_poll_all(): Poll all AP devices.
1515 * @dummy: Unused variable
1516 *
1517 * Poll all AP devices on the bus in a round robin fashion. Continue
1518 * polling until bit 2^0 of the control flags is not set. If bit 2^1
1519 * of the control flags has been set arm the poll timer.
1520 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001521static void ap_poll_all(unsigned long dummy)
1522{
1523 unsigned long flags;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001524 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001525
Felix Beckcb17a632008-12-25 13:38:41 +01001526 /* Reset the indicator if interrupts are used. Thus new interrupts can
1527 * be received. Doing it in the beginning of the tasklet is therefor
1528 * important that no requests on any AP get lost.
1529 */
1530 if (ap_using_interrupts())
1531 xchg((u8 *)ap_interrupt_indicator, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001532 do {
1533 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001534 spin_lock(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001535 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001536 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001537 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001538 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001539 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001540 spin_unlock(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001541 } while (flags & 1);
1542 if (flags & 2)
1543 ap_schedule_poll_timer();
1544}
1545
1546/**
Felix Beck1749a812008-04-17 07:46:28 +02001547 * ap_poll_thread(): Thread that polls for finished requests.
1548 * @data: Unused pointer
1549 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001550 * AP bus poll thread. The purpose of this thread is to poll for
1551 * finished requests in a loop if there is a "free" cpu - that is
1552 * a cpu that doesn't have anything better to do. The polling stops
1553 * as soon as there is another task or if all messages have been
1554 * delivered.
1555 */
1556static int ap_poll_thread(void *data)
1557{
1558 DECLARE_WAITQUEUE(wait, current);
1559 unsigned long flags;
1560 int requests;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001561 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001562
Christian Borntraegerd83682b2006-10-06 16:38:22 +02001563 set_user_nice(current, 19);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001564 while (1) {
Felix Beck772f5472009-06-22 12:08:16 +02001565 if (ap_suspend_flag)
1566 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001567 if (need_resched()) {
1568 schedule();
1569 continue;
1570 }
1571 add_wait_queue(&ap_poll_wait, &wait);
1572 set_current_state(TASK_INTERRUPTIBLE);
1573 if (kthread_should_stop())
1574 break;
1575 requests = atomic_read(&ap_poll_requests);
1576 if (requests <= 0)
1577 schedule();
1578 set_current_state(TASK_RUNNING);
1579 remove_wait_queue(&ap_poll_wait, &wait);
1580
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001581 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001582 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001583 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001584 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001585 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001586 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001587 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001588 spin_unlock_bh(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001589 }
1590 set_current_state(TASK_RUNNING);
1591 remove_wait_queue(&ap_poll_wait, &wait);
1592 return 0;
1593}
1594
1595static int ap_poll_thread_start(void)
1596{
1597 int rc;
1598
Felix Beck772f5472009-06-22 12:08:16 +02001599 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beckcb17a632008-12-25 13:38:41 +01001600 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001601 mutex_lock(&ap_poll_thread_mutex);
1602 if (!ap_poll_kthread) {
1603 ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
1604 rc = IS_ERR(ap_poll_kthread) ? PTR_ERR(ap_poll_kthread) : 0;
1605 if (rc)
1606 ap_poll_kthread = NULL;
1607 }
1608 else
1609 rc = 0;
1610 mutex_unlock(&ap_poll_thread_mutex);
1611 return rc;
1612}
1613
1614static void ap_poll_thread_stop(void)
1615{
1616 mutex_lock(&ap_poll_thread_mutex);
1617 if (ap_poll_kthread) {
1618 kthread_stop(ap_poll_kthread);
1619 ap_poll_kthread = NULL;
1620 }
1621 mutex_unlock(&ap_poll_thread_mutex);
1622}
1623
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001624/**
Felix Beck1749a812008-04-17 07:46:28 +02001625 * ap_request_timeout(): Handling of request timeouts
1626 * @data: Holds the AP device.
1627 *
1628 * Handles request timeouts.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001629 */
1630static void ap_request_timeout(unsigned long data)
1631{
1632 struct ap_device *ap_dev = (struct ap_device *) data;
1633
Felix Beckcb17a632008-12-25 13:38:41 +01001634 if (ap_dev->reset == AP_RESET_ARMED) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001635 ap_dev->reset = AP_RESET_DO;
Felix Beckcb17a632008-12-25 13:38:41 +01001636
1637 if (ap_using_interrupts())
1638 tasklet_schedule(&ap_tasklet);
1639 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001640}
1641
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001642static void ap_reset_domain(void)
1643{
1644 int i;
1645
Ralph Wuerthner39aa7cf2007-10-12 16:11:29 +02001646 if (ap_domain_index != -1)
1647 for (i = 0; i < AP_DEVICES; i++)
1648 ap_reset_queue(AP_MKQID(i, ap_domain_index));
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001649}
1650
1651static void ap_reset_all(void)
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001652{
1653 int i, j;
1654
1655 for (i = 0; i < AP_DOMAINS; i++)
1656 for (j = 0; j < AP_DEVICES; j++)
1657 ap_reset_queue(AP_MKQID(j, i));
1658}
1659
1660static struct reset_call ap_reset_call = {
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001661 .fn = ap_reset_all,
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001662};
1663
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001664/**
Felix Beck1749a812008-04-17 07:46:28 +02001665 * ap_module_init(): The module initialization code.
1666 *
1667 * Initializes the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001668 */
1669int __init ap_module_init(void)
1670{
1671 int rc, i;
1672
1673 if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001674 pr_warning("%d is not a valid cryptographic domain\n",
1675 ap_domain_index);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001676 return -EINVAL;
1677 }
Felix Beck5314af62009-09-22 22:58:51 +02001678 /* In resume callback we need to know if the user had set the domain.
1679 * If so, we can not just reset it.
1680 */
1681 if (ap_domain_index >= 0)
1682 user_set_domain = 1;
1683
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001684 if (ap_instructions_available() != 0) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001685 pr_warning("The hardware system does not support "
1686 "AP instructions\n");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001687 return -ENODEV;
1688 }
Felix Beckcb17a632008-12-25 13:38:41 +01001689 if (ap_interrupts_available()) {
1690 isc_register(AP_ISC);
1691 ap_interrupt_indicator = s390_register_adapter_interrupt(
1692 &ap_interrupt_handler, NULL, AP_ISC);
1693 if (IS_ERR(ap_interrupt_indicator)) {
1694 ap_interrupt_indicator = NULL;
1695 isc_unregister(AP_ISC);
1696 }
1697 }
1698
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001699 register_reset_call(&ap_reset_call);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001700
1701 /* Create /sys/bus/ap. */
1702 rc = bus_register(&ap_bus_type);
1703 if (rc)
1704 goto out;
1705 for (i = 0; ap_bus_attrs[i]; i++) {
1706 rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]);
1707 if (rc)
1708 goto out_bus;
1709 }
1710
1711 /* Create /sys/devices/ap. */
Mark McLoughlin035da162008-12-15 12:58:29 +00001712 ap_root_device = root_device_register("ap");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001713 rc = IS_ERR(ap_root_device) ? PTR_ERR(ap_root_device) : 0;
1714 if (rc)
1715 goto out_bus;
1716
1717 ap_work_queue = create_singlethread_workqueue("kapwork");
1718 if (!ap_work_queue) {
1719 rc = -ENOMEM;
1720 goto out_root;
1721 }
1722
1723 if (ap_select_domain() == 0)
1724 ap_scan_bus(NULL);
1725
Felix Beck1749a812008-04-17 07:46:28 +02001726 /* Setup the AP bus rescan timer. */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001727 init_timer(&ap_config_timer);
1728 ap_config_timer.function = ap_config_timeout;
1729 ap_config_timer.data = 0;
1730 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1731 add_timer(&ap_config_timer);
1732
Felix Beckfe137232008-07-14 09:59:08 +02001733 /* Setup the high resultion poll timer.
1734 * If we are running under z/VM adjust polling to z/VM polling rate.
1735 */
1736 if (MACHINE_IS_VM)
1737 poll_timeout = 1500000;
Felix Beck93521312009-12-07 12:52:00 +01001738 spin_lock_init(&ap_poll_timer_lock);
Felix Beckfe137232008-07-14 09:59:08 +02001739 hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1740 ap_poll_timer.function = ap_poll_timeout;
1741
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001742 /* Start the low priority AP bus poll thread. */
1743 if (ap_thread_flag) {
1744 rc = ap_poll_thread_start();
1745 if (rc)
1746 goto out_work;
1747 }
1748
1749 return 0;
1750
1751out_work:
1752 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001753 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001754 destroy_workqueue(ap_work_queue);
1755out_root:
Mark McLoughlin035da162008-12-15 12:58:29 +00001756 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001757out_bus:
1758 while (i--)
1759 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1760 bus_unregister(&ap_bus_type);
1761out:
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001762 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001763 if (ap_using_interrupts()) {
1764 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1765 isc_unregister(AP_ISC);
1766 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001767 return rc;
1768}
1769
1770static int __ap_match_all(struct device *dev, void *data)
1771{
1772 return 1;
1773}
1774
1775/**
Felix Beck1749a812008-04-17 07:46:28 +02001776 * ap_modules_exit(): The module termination code
1777 *
1778 * Terminates the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001779 */
1780void ap_module_exit(void)
1781{
1782 int i;
1783 struct device *dev;
1784
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001785 ap_reset_domain();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001786 ap_poll_thread_stop();
1787 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001788 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001789 destroy_workqueue(ap_work_queue);
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001790 tasklet_kill(&ap_tasklet);
Mark McLoughlin035da162008-12-15 12:58:29 +00001791 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001792 while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
1793 __ap_match_all)))
1794 {
1795 device_unregister(dev);
1796 put_device(dev);
1797 }
1798 for (i = 0; ap_bus_attrs[i]; i++)
1799 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1800 bus_unregister(&ap_bus_type);
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001801 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001802 if (ap_using_interrupts()) {
1803 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1804 isc_unregister(AP_ISC);
1805 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001806}
1807
1808#ifndef CONFIG_ZCRYPT_MONOLITHIC
1809module_init(ap_module_init);
1810module_exit(ap_module_exit);
1811#endif