blob: c5c121f14c997848c1f6cbea669116f05515d9ae [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>
Holger Dengler6bed05b2011-07-24 10:48:25 +02009 * Holger Dengler <hd@linux.vnet.ibm.com>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020010 *
11 * Adjunct processor bus.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
Martin Schwidefsky136f7a12008-12-25 13:39:46 +010028#define KMSG_COMPONENT "ap"
29#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
30
Holger Dengler62d146f2011-01-05 12:47:38 +010031#include <linux/kernel_stat.h>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020032#include <linux/module.h>
33#include <linux/init.h>
34#include <linux/delay.h>
35#include <linux/err.h>
36#include <linux/interrupt.h>
37#include <linux/workqueue.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090038#include <linux/slab.h>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020039#include <linux/notifier.h>
40#include <linux/kthread.h>
41#include <linux/mutex.h>
Ralph Wuerthner85eca852006-12-08 15:54:07 +010042#include <asm/reset.h>
Felix Beckcb17a632008-12-25 13:38:41 +010043#include <asm/airq.h>
Arun Sharma600634972011-07-26 16:09:06 -070044#include <linux/atomic.h>
Felix Beckcb17a632008-12-25 13:38:41 +010045#include <asm/system.h>
46#include <asm/isc.h>
Felix Beckfe137232008-07-14 09:59:08 +020047#include <linux/hrtimer.h>
48#include <linux/ktime.h>
David Howellsa0616cd2012-03-28 18:30:02 +010049#include <asm/facility.h>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020050
51#include "ap_bus.h"
52
53/* Some prototypes. */
Al Viro4927b3f2006-12-06 19:18:20 +000054static void ap_scan_bus(struct work_struct *);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020055static void ap_poll_all(unsigned long);
Felix Beckfe137232008-07-14 09:59:08 +020056static enum hrtimer_restart ap_poll_timeout(struct hrtimer *);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020057static int ap_poll_thread_start(void);
58static void ap_poll_thread_stop(void);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +020059static void ap_request_timeout(unsigned long);
Felix Beckcb17a632008-12-25 13:38:41 +010060static inline void ap_schedule_poll_timer(void);
Felix Beck772f5472009-06-22 12:08:16 +020061static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags);
62static int ap_device_remove(struct device *dev);
63static int ap_device_probe(struct device *dev);
64static void ap_interrupt_handler(void *unused1, void *unused2);
65static void ap_reset(struct ap_device *ap_dev);
66static void ap_config_timeout(unsigned long ptr);
Felix Beck5314af62009-09-22 22:58:51 +020067static int ap_select_domain(void);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020068
Felix Beck1749a812008-04-17 07:46:28 +020069/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020070 * Module description.
71 */
72MODULE_AUTHOR("IBM Corporation");
73MODULE_DESCRIPTION("Adjunct Processor Bus driver, "
74 "Copyright 2006 IBM Corporation");
75MODULE_LICENSE("GPL");
76
Felix Beck1749a812008-04-17 07:46:28 +020077/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020078 * Module parameter
79 */
80int ap_domain_index = -1; /* Adjunct Processor Domain Index */
81module_param_named(domain, ap_domain_index, int, 0000);
82MODULE_PARM_DESC(domain, "domain index for ap devices");
83EXPORT_SYMBOL(ap_domain_index);
84
Felix Beckb90b34c2008-02-09 18:24:30 +010085static int ap_thread_flag = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +020086module_param_named(poll_thread, ap_thread_flag, int, 0000);
Felix Beckb90b34c2008-02-09 18:24:30 +010087MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off).");
Martin Schwidefsky1534c382006-09-20 15:58:25 +020088
89static struct device *ap_root_device = NULL;
Christian Maaser43c207e62008-12-25 13:38:42 +010090static DEFINE_SPINLOCK(ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +010091static LIST_HEAD(ap_device_list);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020092
Felix Beck1749a812008-04-17 07:46:28 +020093/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020094 * Workqueue & timer for bus rescan.
95 */
96static struct workqueue_struct *ap_work_queue;
97static struct timer_list ap_config_timer;
98static int ap_config_time = AP_CONFIG_TIME;
Al Viro4927b3f2006-12-06 19:18:20 +000099static DECLARE_WORK(ap_config_work, ap_scan_bus);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200100
Felix Beck1749a812008-04-17 07:46:28 +0200101/*
Felix Beckcb17a632008-12-25 13:38:41 +0100102 * Tasklet & timer for AP request polling and interrupts
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200103 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200104static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0);
105static atomic_t ap_poll_requests = ATOMIC_INIT(0);
106static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
107static struct task_struct *ap_poll_kthread = NULL;
108static DEFINE_MUTEX(ap_poll_thread_mutex);
Felix Beck93521312009-12-07 12:52:00 +0100109static DEFINE_SPINLOCK(ap_poll_timer_lock);
Felix Beckcb17a632008-12-25 13:38:41 +0100110static void *ap_interrupt_indicator;
Felix Beckfe137232008-07-14 09:59:08 +0200111static struct hrtimer ap_poll_timer;
112/* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
113 * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
114static unsigned long long poll_timeout = 250000;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200115
Felix Beck772f5472009-06-22 12:08:16 +0200116/* Suspend flag */
117static int ap_suspend_flag;
Felix Beck5314af62009-09-22 22:58:51 +0200118/* Flag to check if domain was set through module parameter domain=. This is
119 * important when supsend and resume is done in a z/VM environment where the
120 * domain might change. */
121static int user_set_domain = 0;
Felix Beck772f5472009-06-22 12:08:16 +0200122static struct bus_type ap_bus_type;
123
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200124/**
Felix Beckcb17a632008-12-25 13:38:41 +0100125 * ap_using_interrupts() - Returns non-zero if interrupt support is
126 * available.
127 */
128static inline int ap_using_interrupts(void)
129{
130 return ap_interrupt_indicator != NULL;
131}
132
133/**
Felix Beck1749a812008-04-17 07:46:28 +0200134 * ap_intructions_available() - Test if AP instructions are available.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200135 *
Felix Beck1749a812008-04-17 07:46:28 +0200136 * Returns 0 if the AP instructions are installed.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200137 */
138static inline int ap_instructions_available(void)
139{
140 register unsigned long reg0 asm ("0") = AP_MKQID(0,0);
141 register unsigned long reg1 asm ("1") = -ENODEV;
142 register unsigned long reg2 asm ("2") = 0UL;
143
144 asm volatile(
145 " .long 0xb2af0000\n" /* PQAP(TAPQ) */
146 "0: la %1,0\n"
147 "1:\n"
148 EX_TABLE(0b, 1b)
149 : "+d" (reg0), "+d" (reg1), "+d" (reg2) : : "cc" );
150 return reg1;
151}
152
153/**
Felix Beckcb17a632008-12-25 13:38:41 +0100154 * ap_interrupts_available(): Test if AP interrupts are available.
155 *
156 * Returns 1 if AP interrupts are available.
157 */
158static int ap_interrupts_available(void)
159{
Felix Beck53ec24b12011-01-05 12:46:44 +0100160 return test_facility(2) && test_facility(65);
Felix Beckcb17a632008-12-25 13:38:41 +0100161}
162
163/**
Felix Beck1749a812008-04-17 07:46:28 +0200164 * ap_test_queue(): Test adjunct processor queue.
165 * @qid: The AP queue number
166 * @queue_depth: Pointer to queue depth value
167 * @device_type: Pointer to device type value
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200168 *
Felix Beck1749a812008-04-17 07:46:28 +0200169 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200170 */
171static inline struct ap_queue_status
172ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
173{
174 register unsigned long reg0 asm ("0") = qid;
175 register struct ap_queue_status reg1 asm ("1");
176 register unsigned long reg2 asm ("2") = 0UL;
177
178 asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
179 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
180 *device_type = (int) (reg2 >> 24);
181 *queue_depth = (int) (reg2 & 0xff);
182 return reg1;
183}
184
185/**
Felix Beck1749a812008-04-17 07:46:28 +0200186 * ap_reset_queue(): Reset adjunct processor queue.
187 * @qid: The AP queue number
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200188 *
Felix Beck1749a812008-04-17 07:46:28 +0200189 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200190 */
191static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
192{
193 register unsigned long reg0 asm ("0") = qid | 0x01000000UL;
194 register struct ap_queue_status reg1 asm ("1");
195 register unsigned long reg2 asm ("2") = 0UL;
196
197 asm volatile(
198 ".long 0xb2af0000" /* PQAP(RAPQ) */
199 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
200 return reg1;
201}
202
Felix Beckcb17a632008-12-25 13:38:41 +0100203#ifdef CONFIG_64BIT
204/**
205 * ap_queue_interruption_control(): Enable interruption for a specific AP.
206 * @qid: The AP queue number
207 * @ind: The notification indicator byte
208 *
209 * Returns AP queue status.
210 */
211static inline struct ap_queue_status
212ap_queue_interruption_control(ap_qid_t qid, void *ind)
213{
214 register unsigned long reg0 asm ("0") = qid | 0x03000000UL;
215 register unsigned long reg1_in asm ("1") = 0x0000800000000000UL | AP_ISC;
216 register struct ap_queue_status reg1_out asm ("1");
217 register void *reg2 asm ("2") = ind;
218 asm volatile(
219 ".long 0xb2af0000" /* PQAP(RAPQ) */
220 : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
221 :
222 : "cc" );
223 return reg1_out;
224}
225#endif
226
Holger Dengler6bed05b2011-07-24 10:48:25 +0200227#ifdef CONFIG_64BIT
228static inline struct ap_queue_status
229__ap_query_functions(ap_qid_t qid, unsigned int *functions)
Felix Beckb1f933d2011-01-05 12:47:44 +0100230{
231 register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
Holger Dengler6bed05b2011-07-24 10:48:25 +0200232 register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
233 register unsigned long reg2 asm ("2");
Felix Beckb1f933d2011-01-05 12:47:44 +0100234
235 asm volatile(
236 ".long 0xb2af0000\n"
Holger Dengler6bed05b2011-07-24 10:48:25 +0200237 "0:\n"
238 EX_TABLE(0b, 0b)
239 : "+d" (reg0), "+d" (reg1), "=d" (reg2)
Felix Beckb1f933d2011-01-05 12:47:44 +0100240 :
241 : "cc");
242
Holger Dengler6bed05b2011-07-24 10:48:25 +0200243 *functions = (unsigned int)(reg2 >> 32);
Felix Beckb1f933d2011-01-05 12:47:44 +0100244 return reg1;
245}
Holger Dengler6bed05b2011-07-24 10:48:25 +0200246#endif
247
248/**
249 * ap_query_functions(): Query supported functions.
250 * @qid: The AP queue number
251 * @functions: Pointer to functions field.
252 *
253 * Returns
254 * 0 on success.
255 * -ENODEV if queue not valid.
256 * -EBUSY if device busy.
257 * -EINVAL if query function is not supported
258 */
259static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
260{
261#ifdef CONFIG_64BIT
262 struct ap_queue_status status;
263 int i;
264 status = __ap_query_functions(qid, functions);
265
266 for (i = 0; i < AP_MAX_RESET; i++) {
267 if (ap_queue_status_invalid_test(&status))
268 return -ENODEV;
269
270 switch (status.response_code) {
271 case AP_RESPONSE_NORMAL:
272 return 0;
273 case AP_RESPONSE_RESET_IN_PROGRESS:
274 case AP_RESPONSE_BUSY:
275 break;
276 case AP_RESPONSE_Q_NOT_AVAIL:
277 case AP_RESPONSE_DECONFIGURED:
278 case AP_RESPONSE_CHECKSTOPPED:
279 case AP_RESPONSE_INVALID_ADDRESS:
280 return -ENODEV;
281 case AP_RESPONSE_OTHERWISE_CHANGED:
282 break;
283 default:
284 break;
285 }
286 if (i < AP_MAX_RESET - 1) {
287 udelay(5);
288 status = __ap_query_functions(qid, functions);
289 }
290 }
291 return -EBUSY;
292#else
293 return -EINVAL;
294#endif
295}
Felix Beckb1f933d2011-01-05 12:47:44 +0100296
297/**
298 * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
299 * support.
300 * @qid: The AP queue number
301 *
302 * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
303 */
304int ap_4096_commands_available(ap_qid_t qid)
305{
Holger Dengler6bed05b2011-07-24 10:48:25 +0200306 unsigned int functions;
Felix Beckb1f933d2011-01-05 12:47:44 +0100307
Holger Dengler6bed05b2011-07-24 10:48:25 +0200308 if (ap_query_functions(qid, &functions))
309 return 0;
310
311 return test_ap_facility(functions, 1) &&
312 test_ap_facility(functions, 2);
Felix Beckb1f933d2011-01-05 12:47:44 +0100313}
314EXPORT_SYMBOL(ap_4096_commands_available);
315
Felix Beckcb17a632008-12-25 13:38:41 +0100316/**
317 * ap_queue_enable_interruption(): Enable interruption on an AP.
318 * @qid: The AP queue number
319 * @ind: the notification indicator byte
320 *
321 * Enables interruption on AP queue via ap_queue_interruption_control(). Based
322 * on the return value it waits a while and tests the AP queue if interrupts
323 * have been switched on using ap_test_queue().
324 */
325static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
326{
327#ifdef CONFIG_64BIT
328 struct ap_queue_status status;
329 int t_depth, t_device_type, rc, i;
330
331 rc = -EBUSY;
332 status = ap_queue_interruption_control(qid, ind);
333
334 for (i = 0; i < AP_MAX_RESET; i++) {
335 switch (status.response_code) {
336 case AP_RESPONSE_NORMAL:
337 if (status.int_enabled)
338 return 0;
339 break;
340 case AP_RESPONSE_RESET_IN_PROGRESS:
341 case AP_RESPONSE_BUSY:
342 break;
343 case AP_RESPONSE_Q_NOT_AVAIL:
344 case AP_RESPONSE_DECONFIGURED:
345 case AP_RESPONSE_CHECKSTOPPED:
346 case AP_RESPONSE_INVALID_ADDRESS:
347 return -ENODEV;
348 case AP_RESPONSE_OTHERWISE_CHANGED:
349 if (status.int_enabled)
350 return 0;
351 break;
352 default:
353 break;
354 }
355 if (i < AP_MAX_RESET - 1) {
356 udelay(5);
357 status = ap_test_queue(qid, &t_depth, &t_device_type);
358 }
359 }
360 return rc;
361#else
362 return -EINVAL;
363#endif
364}
365
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200366/**
Felix Beck1749a812008-04-17 07:46:28 +0200367 * __ap_send(): Send message to adjunct processor queue.
368 * @qid: The AP queue number
369 * @psmid: The program supplied message identifier
370 * @msg: The message text
371 * @length: The message length
Felix Becka6a5d732009-12-07 12:51:55 +0100372 * @special: Special Bit
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200373 *
Felix Beck1749a812008-04-17 07:46:28 +0200374 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200375 * Condition code 1 on NQAP can't happen because the L bit is 1.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200376 * Condition code 2 on NQAP also means the send is incomplete,
377 * because a segment boundary was reached. The NQAP is repeated.
378 */
379static inline struct ap_queue_status
Felix Becka6a5d732009-12-07 12:51:55 +0100380__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length,
381 unsigned int special)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200382{
383 typedef struct { char _[length]; } msgblock;
384 register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
385 register struct ap_queue_status reg1 asm ("1");
386 register unsigned long reg2 asm ("2") = (unsigned long) msg;
387 register unsigned long reg3 asm ("3") = (unsigned long) length;
388 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
389 register unsigned long reg5 asm ("5") = (unsigned int) psmid;
390
Felix Becka6a5d732009-12-07 12:51:55 +0100391 if (special == 1)
392 reg0 |= 0x400000UL;
393
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200394 asm volatile (
395 "0: .long 0xb2ad0042\n" /* DQAP */
396 " brc 2,0b"
397 : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
398 : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg)
399 : "cc" );
400 return reg1;
401}
402
403int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
404{
405 struct ap_queue_status status;
406
Felix Becka6a5d732009-12-07 12:51:55 +0100407 status = __ap_send(qid, psmid, msg, length, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200408 switch (status.response_code) {
409 case AP_RESPONSE_NORMAL:
410 return 0;
411 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200412 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200413 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +0100414 case AP_RESPONSE_REQ_FAC_NOT_INST:
415 return -EINVAL;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200416 default: /* Device is gone. */
417 return -ENODEV;
418 }
419}
420EXPORT_SYMBOL(ap_send);
421
Felix Beck1749a812008-04-17 07:46:28 +0200422/**
423 * __ap_recv(): Receive message from adjunct processor queue.
424 * @qid: The AP queue number
425 * @psmid: Pointer to program supplied message identifier
426 * @msg: The message text
427 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200428 *
Felix Beck1749a812008-04-17 07:46:28 +0200429 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200430 * Condition code 1 on DQAP means the receive has taken place
431 * but only partially. The response is incomplete, hence the
432 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200433 * Condition code 2 on DQAP also means the receive is incomplete,
434 * this time because a segment boundary was reached. Again, the
435 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200436 * Note that gpr2 is used by the DQAP instruction to keep track of
437 * any 'residual' length, in case the instruction gets interrupted.
438 * Hence it gets zeroed before the instruction.
439 */
440static inline struct ap_queue_status
441__ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
442{
443 typedef struct { char _[length]; } msgblock;
444 register unsigned long reg0 asm("0") = qid | 0x80000000UL;
445 register struct ap_queue_status reg1 asm ("1");
446 register unsigned long reg2 asm("2") = 0UL;
447 register unsigned long reg4 asm("4") = (unsigned long) msg;
448 register unsigned long reg5 asm("5") = (unsigned long) length;
449 register unsigned long reg6 asm("6") = 0UL;
450 register unsigned long reg7 asm("7") = 0UL;
451
452
453 asm volatile(
454 "0: .long 0xb2ae0064\n"
455 " brc 6,0b\n"
456 : "+d" (reg0), "=d" (reg1), "+d" (reg2),
457 "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
458 "=m" (*(msgblock *) msg) : : "cc" );
459 *psmid = (((unsigned long long) reg6) << 32) + reg7;
460 return reg1;
461}
462
463int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
464{
465 struct ap_queue_status status;
466
467 status = __ap_recv(qid, psmid, msg, length);
468 switch (status.response_code) {
469 case AP_RESPONSE_NORMAL:
470 return 0;
471 case AP_RESPONSE_NO_PENDING_REPLY:
472 if (status.queue_empty)
473 return -ENOENT;
474 return -EBUSY;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200475 case AP_RESPONSE_RESET_IN_PROGRESS:
476 return -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200477 default:
478 return -ENODEV;
479 }
480}
481EXPORT_SYMBOL(ap_recv);
482
483/**
Felix Beck1749a812008-04-17 07:46:28 +0200484 * ap_query_queue(): Check if an AP queue is available.
485 * @qid: The AP queue number
486 * @queue_depth: Pointer to queue depth value
487 * @device_type: Pointer to device type value
488 *
489 * The test is repeated for AP_MAX_RESET times.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200490 */
491static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
492{
493 struct ap_queue_status status;
494 int t_depth, t_device_type, rc, i;
495
496 rc = -EBUSY;
497 for (i = 0; i < AP_MAX_RESET; i++) {
498 status = ap_test_queue(qid, &t_depth, &t_device_type);
499 switch (status.response_code) {
500 case AP_RESPONSE_NORMAL:
501 *queue_depth = t_depth + 1;
502 *device_type = t_device_type;
503 rc = 0;
504 break;
505 case AP_RESPONSE_Q_NOT_AVAIL:
506 rc = -ENODEV;
507 break;
508 case AP_RESPONSE_RESET_IN_PROGRESS:
509 break;
510 case AP_RESPONSE_DECONFIGURED:
511 rc = -ENODEV;
512 break;
513 case AP_RESPONSE_CHECKSTOPPED:
514 rc = -ENODEV;
515 break;
Felix Beckcb17a632008-12-25 13:38:41 +0100516 case AP_RESPONSE_INVALID_ADDRESS:
517 rc = -ENODEV;
518 break;
519 case AP_RESPONSE_OTHERWISE_CHANGED:
520 break;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200521 case AP_RESPONSE_BUSY:
522 break;
523 default:
524 BUG();
525 }
526 if (rc != -EBUSY)
527 break;
528 if (i < AP_MAX_RESET - 1)
529 udelay(5);
530 }
531 return rc;
532}
533
534/**
Felix Beck1749a812008-04-17 07:46:28 +0200535 * ap_init_queue(): Reset an AP queue.
536 * @qid: The AP queue number
537 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200538 * Reset an AP queue and wait for it to become available again.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200539 */
540static int ap_init_queue(ap_qid_t qid)
541{
542 struct ap_queue_status status;
543 int rc, dummy, i;
544
545 rc = -ENODEV;
546 status = ap_reset_queue(qid);
547 for (i = 0; i < AP_MAX_RESET; i++) {
548 switch (status.response_code) {
549 case AP_RESPONSE_NORMAL:
550 if (status.queue_empty)
551 rc = 0;
552 break;
553 case AP_RESPONSE_Q_NOT_AVAIL:
554 case AP_RESPONSE_DECONFIGURED:
555 case AP_RESPONSE_CHECKSTOPPED:
556 i = AP_MAX_RESET; /* return with -ENODEV */
557 break;
558 case AP_RESPONSE_RESET_IN_PROGRESS:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200559 rc = -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200560 case AP_RESPONSE_BUSY:
561 default:
562 break;
563 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200564 if (rc != -ENODEV && rc != -EBUSY)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200565 break;
566 if (i < AP_MAX_RESET - 1) {
567 udelay(5);
568 status = ap_test_queue(qid, &dummy, &dummy);
569 }
570 }
Felix Beckcb17a632008-12-25 13:38:41 +0100571 if (rc == 0 && ap_using_interrupts()) {
572 rc = ap_queue_enable_interruption(qid, ap_interrupt_indicator);
573 /* If interruption mode is supported by the machine,
574 * but an AP can not be enabled for interruption then
575 * the AP will be discarded. */
576 if (rc)
577 pr_err("Registering adapter interrupts for "
578 "AP %d failed\n", AP_QID_DEVICE(qid));
579 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200580 return rc;
581}
582
583/**
Felix Beck1749a812008-04-17 07:46:28 +0200584 * ap_increase_queue_count(): Arm request timeout.
585 * @ap_dev: Pointer to an AP device.
586 *
587 * Arm request timeout if an AP device was idle and a new request is submitted.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200588 */
589static void ap_increase_queue_count(struct ap_device *ap_dev)
590{
591 int timeout = ap_dev->drv->request_timeout;
592
593 ap_dev->queue_count++;
594 if (ap_dev->queue_count == 1) {
595 mod_timer(&ap_dev->timeout, jiffies + timeout);
596 ap_dev->reset = AP_RESET_ARMED;
597 }
598}
599
600/**
Felix Beck1749a812008-04-17 07:46:28 +0200601 * ap_decrease_queue_count(): Decrease queue count.
602 * @ap_dev: Pointer to an AP device.
603 *
604 * If AP device is still alive, re-schedule request timeout if there are still
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200605 * pending requests.
606 */
607static void ap_decrease_queue_count(struct ap_device *ap_dev)
608{
609 int timeout = ap_dev->drv->request_timeout;
610
611 ap_dev->queue_count--;
612 if (ap_dev->queue_count > 0)
613 mod_timer(&ap_dev->timeout, jiffies + timeout);
614 else
Felix Beck1749a812008-04-17 07:46:28 +0200615 /*
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200616 * The timeout timer should to be disabled now - since
617 * del_timer_sync() is very expensive, we just tell via the
618 * reset flag to ignore the pending timeout timer.
619 */
620 ap_dev->reset = AP_RESET_IGNORE;
621}
622
Felix Beck1749a812008-04-17 07:46:28 +0200623/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200624 * AP device related attributes.
625 */
626static ssize_t ap_hwtype_show(struct device *dev,
627 struct device_attribute *attr, char *buf)
628{
629 struct ap_device *ap_dev = to_ap_dev(dev);
630 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type);
631}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200632
Christian Maaser43c207e62008-12-25 13:38:42 +0100633static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200634static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr,
635 char *buf)
636{
637 struct ap_device *ap_dev = to_ap_dev(dev);
638 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth);
639}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200640
Christian Maaser43c207e62008-12-25 13:38:42 +0100641static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200642static ssize_t ap_request_count_show(struct device *dev,
643 struct device_attribute *attr,
644 char *buf)
645{
646 struct ap_device *ap_dev = to_ap_dev(dev);
647 int rc;
648
649 spin_lock_bh(&ap_dev->lock);
650 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->total_request_count);
651 spin_unlock_bh(&ap_dev->lock);
652 return rc;
653}
654
655static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL);
656
657static ssize_t ap_modalias_show(struct device *dev,
658 struct device_attribute *attr, char *buf)
659{
660 return sprintf(buf, "ap:t%02X", to_ap_dev(dev)->device_type);
661}
662
663static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL);
664
665static struct attribute *ap_dev_attrs[] = {
666 &dev_attr_hwtype.attr,
667 &dev_attr_depth.attr,
668 &dev_attr_request_count.attr,
669 &dev_attr_modalias.attr,
670 NULL
671};
672static struct attribute_group ap_dev_attr_group = {
673 .attrs = ap_dev_attrs
674};
675
676/**
Felix Beck1749a812008-04-17 07:46:28 +0200677 * ap_bus_match()
678 * @dev: Pointer to device
679 * @drv: Pointer to device_driver
680 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200681 * AP bus driver registration/unregistration.
682 */
683static int ap_bus_match(struct device *dev, struct device_driver *drv)
684{
685 struct ap_device *ap_dev = to_ap_dev(dev);
686 struct ap_driver *ap_drv = to_ap_drv(drv);
687 struct ap_device_id *id;
688
Felix Beck1749a812008-04-17 07:46:28 +0200689 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200690 * Compare device type of the device with the list of
691 * supported types of the device_driver.
692 */
693 for (id = ap_drv->ids; id->match_flags; id++) {
694 if ((id->match_flags & AP_DEVICE_ID_MATCH_DEVICE_TYPE) &&
695 (id->dev_type != ap_dev->device_type))
696 continue;
697 return 1;
698 }
699 return 0;
700}
701
702/**
Felix Beck1749a812008-04-17 07:46:28 +0200703 * ap_uevent(): Uevent function for AP devices.
704 * @dev: Pointer to device
705 * @env: Pointer to kobj_uevent_env
706 *
707 * It sets up a single environment variable DEV_TYPE which contains the
708 * hardware device type.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200709 */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200710static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200711{
712 struct ap_device *ap_dev = to_ap_dev(dev);
Kay Sievers7eff2e72007-08-14 15:15:12 +0200713 int retval = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200714
715 if (!ap_dev)
716 return -ENODEV;
717
718 /* Set up DEV_TYPE environment variable. */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200719 retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700720 if (retval)
721 return retval;
722
Cornelia Huck66a4263b2006-12-04 15:40:10 +0100723 /* Add MODALIAS= */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200724 retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700725
Eric Rannaudbf624562007-03-30 22:23:12 -0700726 return retval;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200727}
728
Felix Beck772f5472009-06-22 12:08:16 +0200729static int ap_bus_suspend(struct device *dev, pm_message_t state)
730{
731 struct ap_device *ap_dev = to_ap_dev(dev);
732 unsigned long flags;
733
734 if (!ap_suspend_flag) {
735 ap_suspend_flag = 1;
736
737 /* Disable scanning for devices, thus we do not want to scan
738 * for them after removing.
739 */
740 del_timer_sync(&ap_config_timer);
741 if (ap_work_queue != NULL) {
742 destroy_workqueue(ap_work_queue);
743 ap_work_queue = NULL;
744 }
Felix Beck5314af62009-09-22 22:58:51 +0200745
Felix Beck772f5472009-06-22 12:08:16 +0200746 tasklet_disable(&ap_tasklet);
747 }
748 /* Poll on the device until all requests are finished. */
749 do {
750 flags = 0;
Felix Beck95f15562009-09-11 10:28:51 +0200751 spin_lock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200752 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +0200753 spin_unlock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200754 } while ((flags & 1) || (flags & 2));
755
Felix Beck5314af62009-09-22 22:58:51 +0200756 spin_lock_bh(&ap_dev->lock);
757 ap_dev->unregistered = 1;
758 spin_unlock_bh(&ap_dev->lock);
759
Felix Beck772f5472009-06-22 12:08:16 +0200760 return 0;
761}
762
763static int ap_bus_resume(struct device *dev)
764{
765 int rc = 0;
766 struct ap_device *ap_dev = to_ap_dev(dev);
767
768 if (ap_suspend_flag) {
769 ap_suspend_flag = 0;
770 if (!ap_interrupts_available())
771 ap_interrupt_indicator = NULL;
Felix Beck5314af62009-09-22 22:58:51 +0200772 if (!user_set_domain) {
773 ap_domain_index = -1;
774 ap_select_domain();
775 }
Felix Beck772f5472009-06-22 12:08:16 +0200776 init_timer(&ap_config_timer);
777 ap_config_timer.function = ap_config_timeout;
778 ap_config_timer.data = 0;
779 ap_config_timer.expires = jiffies + ap_config_time * HZ;
780 add_timer(&ap_config_timer);
781 ap_work_queue = create_singlethread_workqueue("kapwork");
782 if (!ap_work_queue)
783 return -ENOMEM;
784 tasklet_enable(&ap_tasklet);
785 if (!ap_using_interrupts())
786 ap_schedule_poll_timer();
787 else
788 tasklet_schedule(&ap_tasklet);
789 if (ap_thread_flag)
790 rc = ap_poll_thread_start();
Felix Beck772f5472009-06-22 12:08:16 +0200791 }
Felix Beck5314af62009-09-22 22:58:51 +0200792 if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) {
793 spin_lock_bh(&ap_dev->lock);
794 ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid),
795 ap_domain_index);
796 spin_unlock_bh(&ap_dev->lock);
797 }
798 queue_work(ap_work_queue, &ap_config_work);
Felix Beck772f5472009-06-22 12:08:16 +0200799
800 return rc;
801}
802
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200803static struct bus_type ap_bus_type = {
804 .name = "ap",
805 .match = &ap_bus_match,
806 .uevent = &ap_uevent,
Felix Beck772f5472009-06-22 12:08:16 +0200807 .suspend = ap_bus_suspend,
808 .resume = ap_bus_resume
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200809};
810
811static int ap_device_probe(struct device *dev)
812{
813 struct ap_device *ap_dev = to_ap_dev(dev);
814 struct ap_driver *ap_drv = to_ap_drv(dev->driver);
815 int rc;
816
817 ap_dev->drv = ap_drv;
818 rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100819 if (!rc) {
Christian Maaser43c207e62008-12-25 13:38:42 +0100820 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100821 list_add(&ap_dev->list, &ap_device_list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100822 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100823 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200824 return rc;
825}
826
827/**
Felix Beck1749a812008-04-17 07:46:28 +0200828 * __ap_flush_queue(): Flush requests.
829 * @ap_dev: Pointer to the AP device
830 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200831 * Flush all requests from the request/pending queue of an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200832 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100833static void __ap_flush_queue(struct ap_device *ap_dev)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200834{
835 struct ap_message *ap_msg, *next;
836
837 list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
838 list_del_init(&ap_msg->list);
839 ap_dev->pendingq_count--;
840 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
841 }
842 list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
843 list_del_init(&ap_msg->list);
844 ap_dev->requestq_count--;
845 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
846 }
847}
848
849void ap_flush_queue(struct ap_device *ap_dev)
850{
851 spin_lock_bh(&ap_dev->lock);
852 __ap_flush_queue(ap_dev);
853 spin_unlock_bh(&ap_dev->lock);
854}
855EXPORT_SYMBOL(ap_flush_queue);
856
857static int ap_device_remove(struct device *dev)
858{
859 struct ap_device *ap_dev = to_ap_dev(dev);
860 struct ap_driver *ap_drv = ap_dev->drv;
861
Ralph Wuerthner4e562962006-10-04 20:02:05 +0200862 ap_flush_queue(ap_dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200863 del_timer_sync(&ap_dev->timeout);
Christian Maaser43c207e62008-12-25 13:38:42 +0100864 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +0100865 list_del_init(&ap_dev->list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100866 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100867 if (ap_drv->remove)
868 ap_drv->remove(ap_dev);
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +0200869 spin_lock_bh(&ap_dev->lock);
870 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
871 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200872 return 0;
873}
874
875int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
876 char *name)
877{
878 struct device_driver *drv = &ap_drv->driver;
879
880 drv->bus = &ap_bus_type;
881 drv->probe = ap_device_probe;
882 drv->remove = ap_device_remove;
883 drv->owner = owner;
884 drv->name = name;
885 return driver_register(drv);
886}
887EXPORT_SYMBOL(ap_driver_register);
888
889void ap_driver_unregister(struct ap_driver *ap_drv)
890{
891 driver_unregister(&ap_drv->driver);
892}
893EXPORT_SYMBOL(ap_driver_unregister);
894
Felix Beck1749a812008-04-17 07:46:28 +0200895/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200896 * AP bus attributes.
897 */
898static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
899{
900 return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
901}
902
903static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
904
905static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
906{
907 return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
908}
909
Felix Beckcb17a632008-12-25 13:38:41 +0100910static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
911{
912 return snprintf(buf, PAGE_SIZE, "%d\n",
913 ap_using_interrupts() ? 1 : 0);
914}
915
916static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL);
917
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200918static ssize_t ap_config_time_store(struct bus_type *bus,
919 const char *buf, size_t count)
920{
921 int time;
922
923 if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120)
924 return -EINVAL;
925 ap_config_time = time;
926 if (!timer_pending(&ap_config_timer) ||
927 !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) {
928 ap_config_timer.expires = jiffies + ap_config_time * HZ;
929 add_timer(&ap_config_timer);
930 }
931 return count;
932}
933
934static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store);
935
936static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf)
937{
938 return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
939}
940
941static ssize_t ap_poll_thread_store(struct bus_type *bus,
942 const char *buf, size_t count)
943{
944 int flag, rc;
945
946 if (sscanf(buf, "%d\n", &flag) != 1)
947 return -EINVAL;
948 if (flag) {
949 rc = ap_poll_thread_start();
950 if (rc)
951 return rc;
952 }
953 else
954 ap_poll_thread_stop();
955 return count;
956}
957
958static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
959
Felix Beckfe137232008-07-14 09:59:08 +0200960static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
961{
962 return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
963}
964
965static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
966 size_t count)
967{
968 unsigned long long time;
969 ktime_t hr_time;
970
971 /* 120 seconds = maximum poll interval */
Felix Beckcb17a632008-12-25 13:38:41 +0100972 if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 ||
973 time > 120000000000ULL)
Felix Beckfe137232008-07-14 09:59:08 +0200974 return -EINVAL;
975 poll_timeout = time;
976 hr_time = ktime_set(0, poll_timeout);
977
978 if (!hrtimer_is_queued(&ap_poll_timer) ||
Arjan van de Ven6c644ea2008-09-01 15:20:30 -0700979 !hrtimer_forward(&ap_poll_timer, hrtimer_get_expires(&ap_poll_timer), hr_time)) {
980 hrtimer_set_expires(&ap_poll_timer, hr_time);
981 hrtimer_start_expires(&ap_poll_timer, HRTIMER_MODE_ABS);
Felix Beckfe137232008-07-14 09:59:08 +0200982 }
983 return count;
984}
985
986static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
987
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200988static struct bus_attribute *const ap_bus_attrs[] = {
989 &bus_attr_ap_domain,
990 &bus_attr_config_time,
991 &bus_attr_poll_thread,
Felix Beckcb17a632008-12-25 13:38:41 +0100992 &bus_attr_ap_interrupts,
Felix Beckfe137232008-07-14 09:59:08 +0200993 &bus_attr_poll_timeout,
994 NULL,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200995};
996
997/**
Felix Beck1749a812008-04-17 07:46:28 +0200998 * ap_select_domain(): Select an AP domain.
999 *
1000 * Pick one of the 16 AP domains.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001001 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001002static int ap_select_domain(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001003{
1004 int queue_depth, device_type, count, max_count, best_domain;
1005 int rc, i, j;
1006
Felix Beck1749a812008-04-17 07:46:28 +02001007 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001008 * We want to use a single domain. Either the one specified with
1009 * the "domain=" parameter or the domain with the maximum number
1010 * of devices.
1011 */
1012 if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS)
1013 /* Domain has already been selected. */
1014 return 0;
1015 best_domain = -1;
1016 max_count = 0;
1017 for (i = 0; i < AP_DOMAINS; i++) {
1018 count = 0;
1019 for (j = 0; j < AP_DEVICES; j++) {
1020 ap_qid_t qid = AP_MKQID(j, i);
1021 rc = ap_query_queue(qid, &queue_depth, &device_type);
1022 if (rc)
1023 continue;
1024 count++;
1025 }
1026 if (count > max_count) {
1027 max_count = count;
1028 best_domain = i;
1029 }
1030 }
1031 if (best_domain >= 0){
1032 ap_domain_index = best_domain;
1033 return 0;
1034 }
1035 return -ENODEV;
1036}
1037
1038/**
Felix Beck1749a812008-04-17 07:46:28 +02001039 * ap_probe_device_type(): Find the device type of an AP.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001040 * @ap_dev: pointer to the AP device.
Felix Beck1749a812008-04-17 07:46:28 +02001041 *
1042 * Find the device type if query queue returned a device type of 0.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001043 */
1044static int ap_probe_device_type(struct ap_device *ap_dev)
1045{
1046 static unsigned char msg[] = {
1047 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
1048 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1049 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
1050 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1051 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50,
1052 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,
1053 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00,
1054 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,
1055 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1056 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,
1057 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1058 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,
1059 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00,
1060 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1061 0x00,0x00,0x00,0x00,0xb8,0x05,0x00,0x00,
1062 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1063 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1064 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1065 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1066 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1067 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1068 0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,
1069 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1070 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
1071 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20,
1072 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,
1073 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22,
1074 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1075 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
1076 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,
1077 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,
1078 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,
1079 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1080 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,
1081 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00,
1082 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,
1083 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01,
1084 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,
1085 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68,
1086 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,
1087 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0,
1088 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,
1089 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04,
1090 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,
1091 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d,
1092 };
1093 struct ap_queue_status status;
1094 unsigned long long psmid;
1095 char *reply;
1096 int rc, i;
1097
1098 reply = (void *) get_zeroed_page(GFP_KERNEL);
1099 if (!reply) {
1100 rc = -ENOMEM;
1101 goto out;
1102 }
1103
1104 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
Felix Becka6a5d732009-12-07 12:51:55 +01001105 msg, sizeof(msg), 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001106 if (status.response_code != AP_RESPONSE_NORMAL) {
1107 rc = -ENODEV;
1108 goto out_free;
1109 }
1110
1111 /* Wait for the test message to complete. */
1112 for (i = 0; i < 6; i++) {
1113 mdelay(300);
1114 status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
1115 if (status.response_code == AP_RESPONSE_NORMAL &&
1116 psmid == 0x0102030405060708ULL)
1117 break;
1118 }
1119 if (i < 6) {
1120 /* Got an answer. */
1121 if (reply[0] == 0x00 && reply[1] == 0x86)
1122 ap_dev->device_type = AP_DEVICE_TYPE_PCICC;
1123 else
1124 ap_dev->device_type = AP_DEVICE_TYPE_PCICA;
1125 rc = 0;
1126 } else
1127 rc = -ENODEV;
1128
1129out_free:
1130 free_page((unsigned long) reply);
1131out:
1132 return rc;
1133}
1134
Felix Beckcb17a632008-12-25 13:38:41 +01001135static void ap_interrupt_handler(void *unused1, void *unused2)
1136{
Holger Dengler62d146f2011-01-05 12:47:38 +01001137 kstat_cpu(smp_processor_id()).irqs[IOINT_APB]++;
Felix Beckcb17a632008-12-25 13:38:41 +01001138 tasklet_schedule(&ap_tasklet);
1139}
1140
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001141/**
Felix Beck1749a812008-04-17 07:46:28 +02001142 * __ap_scan_bus(): Scan the AP bus.
1143 * @dev: Pointer to device
1144 * @data: Pointer to data
1145 *
1146 * Scan the AP bus for new devices.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001147 */
1148static int __ap_scan_bus(struct device *dev, void *data)
1149{
1150 return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data;
1151}
1152
1153static void ap_device_release(struct device *dev)
1154{
1155 struct ap_device *ap_dev = to_ap_dev(dev);
1156
1157 kfree(ap_dev);
1158}
1159
Al Viro4927b3f2006-12-06 19:18:20 +00001160static void ap_scan_bus(struct work_struct *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001161{
1162 struct ap_device *ap_dev;
1163 struct device *dev;
1164 ap_qid_t qid;
1165 int queue_depth, device_type;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001166 unsigned int device_functions;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001167 int rc, i;
1168
1169 if (ap_select_domain() != 0)
1170 return;
1171 for (i = 0; i < AP_DEVICES; i++) {
1172 qid = AP_MKQID(i, ap_domain_index);
1173 dev = bus_find_device(&ap_bus_type, NULL,
1174 (void *)(unsigned long)qid,
1175 __ap_scan_bus);
Ralph Wuerthnerf3b017d2006-10-27 12:39:26 +02001176 rc = ap_query_queue(qid, &queue_depth, &device_type);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001177 if (dev) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001178 if (rc == -EBUSY) {
1179 set_current_state(TASK_UNINTERRUPTIBLE);
1180 schedule_timeout(AP_RESET_TIMEOUT);
1181 rc = ap_query_queue(qid, &queue_depth,
1182 &device_type);
1183 }
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001184 ap_dev = to_ap_dev(dev);
1185 spin_lock_bh(&ap_dev->lock);
1186 if (rc || ap_dev->unregistered) {
1187 spin_unlock_bh(&ap_dev->lock);
Felix Beck5314af62009-09-22 22:58:51 +02001188 if (ap_dev->unregistered)
1189 i--;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001190 device_unregister(dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001191 put_device(dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001192 continue;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001193 }
1194 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001195 put_device(dev);
1196 continue;
1197 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001198 if (rc)
1199 continue;
1200 rc = ap_init_queue(qid);
1201 if (rc)
1202 continue;
1203 ap_dev = kzalloc(sizeof(*ap_dev), GFP_KERNEL);
1204 if (!ap_dev)
1205 break;
1206 ap_dev->qid = qid;
1207 ap_dev->queue_depth = queue_depth;
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001208 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001209 spin_lock_init(&ap_dev->lock);
1210 INIT_LIST_HEAD(&ap_dev->pendingq);
1211 INIT_LIST_HEAD(&ap_dev->requestq);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001212 INIT_LIST_HEAD(&ap_dev->list);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001213 setup_timer(&ap_dev->timeout, ap_request_timeout,
1214 (unsigned long) ap_dev);
Holger Dengler6bed05b2011-07-24 10:48:25 +02001215 switch (device_type) {
1216 case 0:
Holger Denglercf2d0072011-05-23 10:24:30 +02001217 if (ap_probe_device_type(ap_dev)) {
1218 kfree(ap_dev);
1219 continue;
1220 }
Holger Dengler6bed05b2011-07-24 10:48:25 +02001221 break;
1222 case 10:
1223 if (ap_query_functions(qid, &device_functions)) {
1224 kfree(ap_dev);
1225 continue;
1226 }
1227 if (test_ap_facility(device_functions, 3))
1228 ap_dev->device_type = AP_DEVICE_TYPE_CEX3C;
1229 else if (test_ap_facility(device_functions, 4))
1230 ap_dev->device_type = AP_DEVICE_TYPE_CEX3A;
1231 else {
1232 kfree(ap_dev);
1233 continue;
1234 }
1235 break;
1236 default:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001237 ap_dev->device_type = device_type;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001238 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001239
1240 ap_dev->device.bus = &ap_bus_type;
1241 ap_dev->device.parent = ap_root_device;
Felix Beckedc44fa2009-09-11 10:28:52 +02001242 if (dev_set_name(&ap_dev->device, "card%02x",
1243 AP_QID_DEVICE(ap_dev->qid))) {
1244 kfree(ap_dev);
1245 continue;
1246 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001247 ap_dev->device.release = ap_device_release;
1248 rc = device_register(&ap_dev->device);
1249 if (rc) {
Sebastian Ottc6304932009-09-11 10:28:38 +02001250 put_device(&ap_dev->device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001251 continue;
1252 }
1253 /* Add device attributes. */
1254 rc = sysfs_create_group(&ap_dev->device.kobj,
1255 &ap_dev_attr_group);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001256 if (!rc) {
1257 spin_lock_bh(&ap_dev->lock);
1258 ap_dev->unregistered = 0;
1259 spin_unlock_bh(&ap_dev->lock);
1260 }
1261 else
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001262 device_unregister(&ap_dev->device);
1263 }
1264}
1265
1266static void
1267ap_config_timeout(unsigned long ptr)
1268{
1269 queue_work(ap_work_queue, &ap_config_work);
1270 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1271 add_timer(&ap_config_timer);
1272}
1273
1274/**
Holger Denglerbc615de2011-11-14 11:19:04 +01001275 * __ap_schedule_poll_timer(): Schedule poll timer.
Felix Beck1749a812008-04-17 07:46:28 +02001276 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001277 * Set up the timer to run the poll tasklet
1278 */
Holger Denglerbc615de2011-11-14 11:19:04 +01001279static inline void __ap_schedule_poll_timer(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001280{
Felix Beck8d406c62009-07-24 12:39:53 +02001281 ktime_t hr_time;
Felix Beck93521312009-12-07 12:52:00 +01001282
1283 spin_lock_bh(&ap_poll_timer_lock);
Holger Denglerbc615de2011-11-14 11:19:04 +01001284 if (hrtimer_is_queued(&ap_poll_timer) || ap_suspend_flag)
Felix Beck93521312009-12-07 12:52:00 +01001285 goto out;
Felix Beck8d406c62009-07-24 12:39:53 +02001286 if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
1287 hr_time = ktime_set(0, poll_timeout);
1288 hrtimer_forward_now(&ap_poll_timer, hr_time);
1289 hrtimer_restart(&ap_poll_timer);
1290 }
Felix Beck93521312009-12-07 12:52:00 +01001291out:
1292 spin_unlock_bh(&ap_poll_timer_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001293}
1294
1295/**
Holger Denglerbc615de2011-11-14 11:19:04 +01001296 * ap_schedule_poll_timer(): Schedule poll timer.
1297 *
1298 * Set up the timer to run the poll tasklet
1299 */
1300static inline void ap_schedule_poll_timer(void)
1301{
1302 if (ap_using_interrupts())
1303 return;
1304 __ap_schedule_poll_timer();
1305}
1306
1307/**
Felix Beck1749a812008-04-17 07:46:28 +02001308 * ap_poll_read(): Receive pending reply messages from an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001309 * @ap_dev: pointer to the AP device
1310 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1311 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001312 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001313 * Returns 0 if the device is still present, -ENODEV if not.
1314 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001315static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001316{
1317 struct ap_queue_status status;
1318 struct ap_message *ap_msg;
1319
1320 if (ap_dev->queue_count <= 0)
1321 return 0;
1322 status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
1323 ap_dev->reply->message, ap_dev->reply->length);
1324 switch (status.response_code) {
1325 case AP_RESPONSE_NORMAL:
1326 atomic_dec(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001327 ap_decrease_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001328 list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
1329 if (ap_msg->psmid != ap_dev->reply->psmid)
1330 continue;
1331 list_del_init(&ap_msg->list);
1332 ap_dev->pendingq_count--;
1333 ap_dev->drv->receive(ap_dev, ap_msg, ap_dev->reply);
1334 break;
1335 }
1336 if (ap_dev->queue_count > 0)
1337 *flags |= 1;
1338 break;
1339 case AP_RESPONSE_NO_PENDING_REPLY:
1340 if (status.queue_empty) {
1341 /* The card shouldn't forget requests but who knows. */
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +02001342 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001343 ap_dev->queue_count = 0;
1344 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1345 ap_dev->requestq_count += ap_dev->pendingq_count;
1346 ap_dev->pendingq_count = 0;
1347 } else
1348 *flags |= 2;
1349 break;
1350 default:
1351 return -ENODEV;
1352 }
1353 return 0;
1354}
1355
1356/**
Felix Beck1749a812008-04-17 07:46:28 +02001357 * ap_poll_write(): Send messages from the request queue to an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001358 * @ap_dev: pointer to the AP device
1359 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1360 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001361 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001362 * Returns 0 if the device is still present, -ENODEV if not.
1363 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001364static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001365{
1366 struct ap_queue_status status;
1367 struct ap_message *ap_msg;
1368
1369 if (ap_dev->requestq_count <= 0 ||
1370 ap_dev->queue_count >= ap_dev->queue_depth)
1371 return 0;
1372 /* Start the next request on the queue. */
1373 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
1374 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001375 ap_msg->message, ap_msg->length, ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001376 switch (status.response_code) {
1377 case AP_RESPONSE_NORMAL:
1378 atomic_inc(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001379 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001380 list_move_tail(&ap_msg->list, &ap_dev->pendingq);
1381 ap_dev->requestq_count--;
1382 ap_dev->pendingq_count++;
1383 if (ap_dev->queue_count < ap_dev->queue_depth &&
1384 ap_dev->requestq_count > 0)
1385 *flags |= 1;
1386 *flags |= 2;
1387 break;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001388 case AP_RESPONSE_RESET_IN_PROGRESS:
Holger Denglerbc615de2011-11-14 11:19:04 +01001389 __ap_schedule_poll_timer();
1390 case AP_RESPONSE_Q_FULL:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001391 *flags |= 2;
1392 break;
1393 case AP_RESPONSE_MESSAGE_TOO_BIG:
Felix Becka6a5d732009-12-07 12:51:55 +01001394 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001395 return -EINVAL;
1396 default:
1397 return -ENODEV;
1398 }
1399 return 0;
1400}
1401
1402/**
Felix Beck1749a812008-04-17 07:46:28 +02001403 * ap_poll_queue(): Poll AP device for pending replies and send new messages.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001404 * @ap_dev: pointer to the bus device
1405 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1406 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001407 *
1408 * Poll AP device for pending replies and send new messages. If either
1409 * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001410 * Returns 0.
1411 */
1412static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
1413{
1414 int rc;
1415
1416 rc = ap_poll_read(ap_dev, flags);
1417 if (rc)
1418 return rc;
1419 return ap_poll_write(ap_dev, flags);
1420}
1421
1422/**
Felix Beck1749a812008-04-17 07:46:28 +02001423 * __ap_queue_message(): Queue a message to a device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001424 * @ap_dev: pointer to the AP device
1425 * @ap_msg: the message to be queued
Felix Beck1749a812008-04-17 07:46:28 +02001426 *
1427 * Queue a message to a device. Returns 0 if successful.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001428 */
1429static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1430{
1431 struct ap_queue_status status;
1432
1433 if (list_empty(&ap_dev->requestq) &&
1434 ap_dev->queue_count < ap_dev->queue_depth) {
1435 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001436 ap_msg->message, ap_msg->length,
1437 ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001438 switch (status.response_code) {
1439 case AP_RESPONSE_NORMAL:
1440 list_add_tail(&ap_msg->list, &ap_dev->pendingq);
1441 atomic_inc(&ap_poll_requests);
1442 ap_dev->pendingq_count++;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001443 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001444 ap_dev->total_request_count++;
1445 break;
1446 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001447 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001448 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1449 ap_dev->requestq_count++;
1450 ap_dev->total_request_count++;
1451 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +01001452 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001453 case AP_RESPONSE_MESSAGE_TOO_BIG:
1454 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
1455 return -EINVAL;
1456 default: /* Device is gone. */
1457 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
1458 return -ENODEV;
1459 }
1460 } else {
1461 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1462 ap_dev->requestq_count++;
1463 ap_dev->total_request_count++;
1464 return -EBUSY;
1465 }
1466 ap_schedule_poll_timer();
1467 return 0;
1468}
1469
1470void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1471{
1472 unsigned long flags;
1473 int rc;
1474
1475 spin_lock_bh(&ap_dev->lock);
1476 if (!ap_dev->unregistered) {
1477 /* Make room on the queue by polling for finished requests. */
1478 rc = ap_poll_queue(ap_dev, &flags);
1479 if (!rc)
1480 rc = __ap_queue_message(ap_dev, ap_msg);
1481 if (!rc)
1482 wake_up(&ap_poll_wait);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001483 if (rc == -ENODEV)
1484 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001485 } else {
1486 ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001487 rc = -ENODEV;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001488 }
1489 spin_unlock_bh(&ap_dev->lock);
1490 if (rc == -ENODEV)
1491 device_unregister(&ap_dev->device);
1492}
1493EXPORT_SYMBOL(ap_queue_message);
1494
1495/**
Felix Beck1749a812008-04-17 07:46:28 +02001496 * ap_cancel_message(): Cancel a crypto request.
1497 * @ap_dev: The AP device that has the message queued
1498 * @ap_msg: The message that is to be removed
1499 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001500 * Cancel a crypto request. This is done by removing the request
Felix Beck1749a812008-04-17 07:46:28 +02001501 * from the device pending or request queue. Note that the
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001502 * request stays on the AP queue. When it finishes the message
1503 * reply will be discarded because the psmid can't be found.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001504 */
1505void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1506{
1507 struct ap_message *tmp;
1508
1509 spin_lock_bh(&ap_dev->lock);
1510 if (!list_empty(&ap_msg->list)) {
1511 list_for_each_entry(tmp, &ap_dev->pendingq, list)
1512 if (tmp->psmid == ap_msg->psmid) {
1513 ap_dev->pendingq_count--;
1514 goto found;
1515 }
1516 ap_dev->requestq_count--;
1517 found:
1518 list_del_init(&ap_msg->list);
1519 }
1520 spin_unlock_bh(&ap_dev->lock);
1521}
1522EXPORT_SYMBOL(ap_cancel_message);
1523
1524/**
Felix Beck1749a812008-04-17 07:46:28 +02001525 * ap_poll_timeout(): AP receive polling for finished AP requests.
Felix Beckfe137232008-07-14 09:59:08 +02001526 * @unused: Unused pointer.
Felix Beck1749a812008-04-17 07:46:28 +02001527 *
Felix Beckfe137232008-07-14 09:59:08 +02001528 * Schedules the AP tasklet using a high resolution timer.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001529 */
Felix Beckfe137232008-07-14 09:59:08 +02001530static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001531{
1532 tasklet_schedule(&ap_tasklet);
Felix Beckfe137232008-07-14 09:59:08 +02001533 return HRTIMER_NORESTART;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001534}
1535
1536/**
Felix Beck1749a812008-04-17 07:46:28 +02001537 * ap_reset(): Reset a not responding AP device.
1538 * @ap_dev: Pointer to the AP device
1539 *
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001540 * Reset a not responding AP device and move all requests from the
1541 * pending queue to the request queue.
1542 */
1543static void ap_reset(struct ap_device *ap_dev)
1544{
1545 int rc;
1546
1547 ap_dev->reset = AP_RESET_IGNORE;
1548 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
1549 ap_dev->queue_count = 0;
1550 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1551 ap_dev->requestq_count += ap_dev->pendingq_count;
1552 ap_dev->pendingq_count = 0;
1553 rc = ap_init_queue(ap_dev->qid);
1554 if (rc == -ENODEV)
1555 ap_dev->unregistered = 1;
Holger Dengler75464962011-12-01 13:32:23 +01001556 else
1557 __ap_schedule_poll_timer();
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001558}
1559
Christian Maaser43c207e62008-12-25 13:38:42 +01001560static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001561{
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001562 if (!ap_dev->unregistered) {
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001563 if (ap_poll_queue(ap_dev, flags))
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001564 ap_dev->unregistered = 1;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001565 if (ap_dev->reset == AP_RESET_DO)
1566 ap_reset(ap_dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001567 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001568 return 0;
1569}
1570
Felix Beck1749a812008-04-17 07:46:28 +02001571/**
1572 * ap_poll_all(): Poll all AP devices.
1573 * @dummy: Unused variable
1574 *
1575 * Poll all AP devices on the bus in a round robin fashion. Continue
1576 * polling until bit 2^0 of the control flags is not set. If bit 2^1
1577 * of the control flags has been set arm the poll timer.
1578 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001579static void ap_poll_all(unsigned long dummy)
1580{
1581 unsigned long flags;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001582 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001583
Felix Beckcb17a632008-12-25 13:38:41 +01001584 /* Reset the indicator if interrupts are used. Thus new interrupts can
1585 * be received. Doing it in the beginning of the tasklet is therefor
1586 * important that no requests on any AP get lost.
1587 */
1588 if (ap_using_interrupts())
1589 xchg((u8 *)ap_interrupt_indicator, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001590 do {
1591 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001592 spin_lock(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001593 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001594 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001595 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001596 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001597 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001598 spin_unlock(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001599 } while (flags & 1);
1600 if (flags & 2)
1601 ap_schedule_poll_timer();
1602}
1603
1604/**
Felix Beck1749a812008-04-17 07:46:28 +02001605 * ap_poll_thread(): Thread that polls for finished requests.
1606 * @data: Unused pointer
1607 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001608 * AP bus poll thread. The purpose of this thread is to poll for
1609 * finished requests in a loop if there is a "free" cpu - that is
1610 * a cpu that doesn't have anything better to do. The polling stops
1611 * as soon as there is another task or if all messages have been
1612 * delivered.
1613 */
1614static int ap_poll_thread(void *data)
1615{
1616 DECLARE_WAITQUEUE(wait, current);
1617 unsigned long flags;
1618 int requests;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001619 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001620
Christian Borntraegerd83682b2006-10-06 16:38:22 +02001621 set_user_nice(current, 19);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001622 while (1) {
Felix Beck772f5472009-06-22 12:08:16 +02001623 if (ap_suspend_flag)
1624 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001625 if (need_resched()) {
1626 schedule();
1627 continue;
1628 }
1629 add_wait_queue(&ap_poll_wait, &wait);
1630 set_current_state(TASK_INTERRUPTIBLE);
1631 if (kthread_should_stop())
1632 break;
1633 requests = atomic_read(&ap_poll_requests);
1634 if (requests <= 0)
1635 schedule();
1636 set_current_state(TASK_RUNNING);
1637 remove_wait_queue(&ap_poll_wait, &wait);
1638
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001639 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001640 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001641 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001642 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001643 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001644 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001645 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001646 spin_unlock_bh(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001647 }
1648 set_current_state(TASK_RUNNING);
1649 remove_wait_queue(&ap_poll_wait, &wait);
1650 return 0;
1651}
1652
1653static int ap_poll_thread_start(void)
1654{
1655 int rc;
1656
Felix Beck772f5472009-06-22 12:08:16 +02001657 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beckcb17a632008-12-25 13:38:41 +01001658 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001659 mutex_lock(&ap_poll_thread_mutex);
1660 if (!ap_poll_kthread) {
1661 ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
1662 rc = IS_ERR(ap_poll_kthread) ? PTR_ERR(ap_poll_kthread) : 0;
1663 if (rc)
1664 ap_poll_kthread = NULL;
1665 }
1666 else
1667 rc = 0;
1668 mutex_unlock(&ap_poll_thread_mutex);
1669 return rc;
1670}
1671
1672static void ap_poll_thread_stop(void)
1673{
1674 mutex_lock(&ap_poll_thread_mutex);
1675 if (ap_poll_kthread) {
1676 kthread_stop(ap_poll_kthread);
1677 ap_poll_kthread = NULL;
1678 }
1679 mutex_unlock(&ap_poll_thread_mutex);
1680}
1681
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001682/**
Felix Beck1749a812008-04-17 07:46:28 +02001683 * ap_request_timeout(): Handling of request timeouts
1684 * @data: Holds the AP device.
1685 *
1686 * Handles request timeouts.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001687 */
1688static void ap_request_timeout(unsigned long data)
1689{
1690 struct ap_device *ap_dev = (struct ap_device *) data;
1691
Felix Beckcb17a632008-12-25 13:38:41 +01001692 if (ap_dev->reset == AP_RESET_ARMED) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001693 ap_dev->reset = AP_RESET_DO;
Felix Beckcb17a632008-12-25 13:38:41 +01001694
1695 if (ap_using_interrupts())
1696 tasklet_schedule(&ap_tasklet);
1697 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001698}
1699
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001700static void ap_reset_domain(void)
1701{
1702 int i;
1703
Ralph Wuerthner39aa7cf2007-10-12 16:11:29 +02001704 if (ap_domain_index != -1)
1705 for (i = 0; i < AP_DEVICES; i++)
1706 ap_reset_queue(AP_MKQID(i, ap_domain_index));
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001707}
1708
1709static void ap_reset_all(void)
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001710{
1711 int i, j;
1712
1713 for (i = 0; i < AP_DOMAINS; i++)
1714 for (j = 0; j < AP_DEVICES; j++)
1715 ap_reset_queue(AP_MKQID(j, i));
1716}
1717
1718static struct reset_call ap_reset_call = {
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001719 .fn = ap_reset_all,
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001720};
1721
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001722/**
Felix Beck1749a812008-04-17 07:46:28 +02001723 * ap_module_init(): The module initialization code.
1724 *
1725 * Initializes the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001726 */
1727int __init ap_module_init(void)
1728{
1729 int rc, i;
1730
1731 if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001732 pr_warning("%d is not a valid cryptographic domain\n",
1733 ap_domain_index);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001734 return -EINVAL;
1735 }
Felix Beck5314af62009-09-22 22:58:51 +02001736 /* In resume callback we need to know if the user had set the domain.
1737 * If so, we can not just reset it.
1738 */
1739 if (ap_domain_index >= 0)
1740 user_set_domain = 1;
1741
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001742 if (ap_instructions_available() != 0) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001743 pr_warning("The hardware system does not support "
1744 "AP instructions\n");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001745 return -ENODEV;
1746 }
Felix Beckcb17a632008-12-25 13:38:41 +01001747 if (ap_interrupts_available()) {
1748 isc_register(AP_ISC);
1749 ap_interrupt_indicator = s390_register_adapter_interrupt(
1750 &ap_interrupt_handler, NULL, AP_ISC);
1751 if (IS_ERR(ap_interrupt_indicator)) {
1752 ap_interrupt_indicator = NULL;
1753 isc_unregister(AP_ISC);
1754 }
1755 }
1756
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001757 register_reset_call(&ap_reset_call);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001758
1759 /* Create /sys/bus/ap. */
1760 rc = bus_register(&ap_bus_type);
1761 if (rc)
1762 goto out;
1763 for (i = 0; ap_bus_attrs[i]; i++) {
1764 rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]);
1765 if (rc)
1766 goto out_bus;
1767 }
1768
1769 /* Create /sys/devices/ap. */
Mark McLoughlin035da162008-12-15 12:58:29 +00001770 ap_root_device = root_device_register("ap");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001771 rc = IS_ERR(ap_root_device) ? PTR_ERR(ap_root_device) : 0;
1772 if (rc)
1773 goto out_bus;
1774
1775 ap_work_queue = create_singlethread_workqueue("kapwork");
1776 if (!ap_work_queue) {
1777 rc = -ENOMEM;
1778 goto out_root;
1779 }
1780
1781 if (ap_select_domain() == 0)
1782 ap_scan_bus(NULL);
1783
Felix Beck1749a812008-04-17 07:46:28 +02001784 /* Setup the AP bus rescan timer. */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001785 init_timer(&ap_config_timer);
1786 ap_config_timer.function = ap_config_timeout;
1787 ap_config_timer.data = 0;
1788 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1789 add_timer(&ap_config_timer);
1790
Felix Beckfe137232008-07-14 09:59:08 +02001791 /* Setup the high resultion poll timer.
1792 * If we are running under z/VM adjust polling to z/VM polling rate.
1793 */
1794 if (MACHINE_IS_VM)
1795 poll_timeout = 1500000;
Felix Beck93521312009-12-07 12:52:00 +01001796 spin_lock_init(&ap_poll_timer_lock);
Felix Beckfe137232008-07-14 09:59:08 +02001797 hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1798 ap_poll_timer.function = ap_poll_timeout;
1799
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001800 /* Start the low priority AP bus poll thread. */
1801 if (ap_thread_flag) {
1802 rc = ap_poll_thread_start();
1803 if (rc)
1804 goto out_work;
1805 }
1806
1807 return 0;
1808
1809out_work:
1810 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001811 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001812 destroy_workqueue(ap_work_queue);
1813out_root:
Mark McLoughlin035da162008-12-15 12:58:29 +00001814 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001815out_bus:
1816 while (i--)
1817 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1818 bus_unregister(&ap_bus_type);
1819out:
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001820 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001821 if (ap_using_interrupts()) {
1822 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1823 isc_unregister(AP_ISC);
1824 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001825 return rc;
1826}
1827
1828static int __ap_match_all(struct device *dev, void *data)
1829{
1830 return 1;
1831}
1832
1833/**
Felix Beck1749a812008-04-17 07:46:28 +02001834 * ap_modules_exit(): The module termination code
1835 *
1836 * Terminates the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001837 */
1838void ap_module_exit(void)
1839{
1840 int i;
1841 struct device *dev;
1842
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001843 ap_reset_domain();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001844 ap_poll_thread_stop();
1845 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001846 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001847 destroy_workqueue(ap_work_queue);
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001848 tasklet_kill(&ap_tasklet);
Mark McLoughlin035da162008-12-15 12:58:29 +00001849 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001850 while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
1851 __ap_match_all)))
1852 {
1853 device_unregister(dev);
1854 put_device(dev);
1855 }
1856 for (i = 0; ap_bus_attrs[i]; i++)
1857 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1858 bus_unregister(&ap_bus_type);
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001859 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001860 if (ap_using_interrupts()) {
1861 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1862 isc_unregister(AP_ISC);
1863 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001864}
1865
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001866module_init(ap_module_init);
1867module_exit(ap_module_exit);