blob: cf5d9dc51c9492400c0818556f5026654ad72aeb [file] [log] [blame]
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001/*
Holger Dengler75014552012-08-28 16:41:50 +02002 * Copyright IBM Corp. 2006, 2012
Martin Schwidefsky1534c382006-09-20 15:58:25 +02003 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
4 * Martin Schwidefsky <schwidefsky@de.ibm.com>
5 * Ralph Wuerthner <rwuerthn@de.ibm.com>
Felix Beckcb17a632008-12-25 13:38:41 +01006 * Felix Beck <felix.beck@de.ibm.com>
Holger Dengler6bed05b2011-07-24 10:48:25 +02007 * Holger Dengler <hd@linux.vnet.ibm.com>
Martin Schwidefsky1534c382006-09-20 15:58:25 +02008 *
9 * Adjunct processor bus.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
Martin Schwidefsky136f7a12008-12-25 13:39:46 +010026#define KMSG_COMPONENT "ap"
27#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
28
Holger Dengler62d146f2011-01-05 12:47:38 +010029#include <linux/kernel_stat.h>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020030#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/delay.h>
33#include <linux/err.h>
34#include <linux/interrupt.h>
35#include <linux/workqueue.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090036#include <linux/slab.h>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020037#include <linux/notifier.h>
38#include <linux/kthread.h>
39#include <linux/mutex.h>
Ralph Wuerthner85eca852006-12-08 15:54:07 +010040#include <asm/reset.h>
Felix Beckcb17a632008-12-25 13:38:41 +010041#include <asm/airq.h>
Arun Sharma600634972011-07-26 16:09:06 -070042#include <linux/atomic.h>
Felix Beckcb17a632008-12-25 13:38:41 +010043#include <asm/isc.h>
Felix Beckfe137232008-07-14 09:59:08 +020044#include <linux/hrtimer.h>
45#include <linux/ktime.h>
David Howellsa0616cd2012-03-28 18:30:02 +010046#include <asm/facility.h>
Martin Schwidefsky1534c382006-09-20 15:58:25 +020047
48#include "ap_bus.h"
49
50/* Some prototypes. */
Al Viro4927b3f2006-12-06 19:18:20 +000051static void ap_scan_bus(struct work_struct *);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020052static void ap_poll_all(unsigned long);
Felix Beckfe137232008-07-14 09:59:08 +020053static enum hrtimer_restart ap_poll_timeout(struct hrtimer *);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020054static int ap_poll_thread_start(void);
55static void ap_poll_thread_stop(void);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +020056static void ap_request_timeout(unsigned long);
Felix Beckcb17a632008-12-25 13:38:41 +010057static inline void ap_schedule_poll_timer(void);
Felix Beck772f5472009-06-22 12:08:16 +020058static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags);
59static int ap_device_remove(struct device *dev);
60static int ap_device_probe(struct device *dev);
61static void ap_interrupt_handler(void *unused1, void *unused2);
62static void ap_reset(struct ap_device *ap_dev);
63static void ap_config_timeout(unsigned long ptr);
Felix Beck5314af62009-09-22 22:58:51 +020064static int ap_select_domain(void);
Holger Dengler75014552012-08-28 16:41:50 +020065static void ap_query_configuration(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");
Holger Dengler75014552012-08-28 16:41:50 +020071MODULE_DESCRIPTION("Adjunct Processor Bus driver, " \
72 "Copyright IBM Corp. 2006, 2012");
Martin Schwidefsky1534c382006-09-20 15:58:25 +020073MODULE_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;
Holger Dengler75014552012-08-28 16:41:50 +020088static struct ap_config_info *ap_configuration;
Christian Maaser43c207e62008-12-25 13:38:42 +010089static DEFINE_SPINLOCK(ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +010090static LIST_HEAD(ap_device_list);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020091
Felix Beck1749a812008-04-17 07:46:28 +020092/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020093 * Workqueue & timer for bus rescan.
94 */
95static struct workqueue_struct *ap_work_queue;
96static struct timer_list ap_config_timer;
97static int ap_config_time = AP_CONFIG_TIME;
Al Viro4927b3f2006-12-06 19:18:20 +000098static DECLARE_WORK(ap_config_work, ap_scan_bus);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020099
Felix Beck1749a812008-04-17 07:46:28 +0200100/*
Felix Beckcb17a632008-12-25 13:38:41 +0100101 * Tasklet & timer for AP request polling and interrupts
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200102 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200103static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0);
104static atomic_t ap_poll_requests = ATOMIC_INIT(0);
105static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
106static struct task_struct *ap_poll_kthread = NULL;
107static DEFINE_MUTEX(ap_poll_thread_mutex);
Felix Beck93521312009-12-07 12:52:00 +0100108static DEFINE_SPINLOCK(ap_poll_timer_lock);
Felix Beckcb17a632008-12-25 13:38:41 +0100109static void *ap_interrupt_indicator;
Felix Beckfe137232008-07-14 09:59:08 +0200110static struct hrtimer ap_poll_timer;
111/* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
112 * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
113static unsigned long long poll_timeout = 250000;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200114
Felix Beck772f5472009-06-22 12:08:16 +0200115/* Suspend flag */
116static int ap_suspend_flag;
Felix Beck5314af62009-09-22 22:58:51 +0200117/* Flag to check if domain was set through module parameter domain=. This is
118 * important when supsend and resume is done in a z/VM environment where the
119 * domain might change. */
120static int user_set_domain = 0;
Felix Beck772f5472009-06-22 12:08:16 +0200121static struct bus_type ap_bus_type;
122
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200123/**
Felix Beckcb17a632008-12-25 13:38:41 +0100124 * ap_using_interrupts() - Returns non-zero if interrupt support is
125 * available.
126 */
127static inline int ap_using_interrupts(void)
128{
129 return ap_interrupt_indicator != NULL;
130}
131
132/**
Felix Beck1749a812008-04-17 07:46:28 +0200133 * ap_intructions_available() - Test if AP instructions are available.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200134 *
Felix Beck1749a812008-04-17 07:46:28 +0200135 * Returns 0 if the AP instructions are installed.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200136 */
137static inline int ap_instructions_available(void)
138{
139 register unsigned long reg0 asm ("0") = AP_MKQID(0,0);
140 register unsigned long reg1 asm ("1") = -ENODEV;
141 register unsigned long reg2 asm ("2") = 0UL;
142
143 asm volatile(
144 " .long 0xb2af0000\n" /* PQAP(TAPQ) */
145 "0: la %1,0\n"
146 "1:\n"
147 EX_TABLE(0b, 1b)
148 : "+d" (reg0), "+d" (reg1), "+d" (reg2) : : "cc" );
149 return reg1;
150}
151
152/**
Felix Beckcb17a632008-12-25 13:38:41 +0100153 * ap_interrupts_available(): Test if AP interrupts are available.
154 *
155 * Returns 1 if AP interrupts are available.
156 */
157static int ap_interrupts_available(void)
158{
Felix Beck53ec24b12011-01-05 12:46:44 +0100159 return test_facility(2) && test_facility(65);
Felix Beckcb17a632008-12-25 13:38:41 +0100160}
161
162/**
Holger Dengler75014552012-08-28 16:41:50 +0200163 * ap_configuration_available(): Test if AP configuration
164 * information is available.
165 *
166 * Returns 1 if AP configuration information is available.
167 */
168static int ap_configuration_available(void)
169{
170 return test_facility(2) && test_facility(12);
171}
172
173/**
Felix Beck1749a812008-04-17 07:46:28 +0200174 * ap_test_queue(): Test adjunct processor queue.
175 * @qid: The AP queue number
176 * @queue_depth: Pointer to queue depth value
177 * @device_type: Pointer to device type value
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200178 *
Felix Beck1749a812008-04-17 07:46:28 +0200179 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200180 */
181static inline struct ap_queue_status
182ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
183{
184 register unsigned long reg0 asm ("0") = qid;
185 register struct ap_queue_status reg1 asm ("1");
186 register unsigned long reg2 asm ("2") = 0UL;
187
188 asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
189 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
190 *device_type = (int) (reg2 >> 24);
191 *queue_depth = (int) (reg2 & 0xff);
192 return reg1;
193}
194
195/**
Felix Beck1749a812008-04-17 07:46:28 +0200196 * ap_reset_queue(): Reset adjunct processor queue.
197 * @qid: The AP queue number
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200198 *
Felix Beck1749a812008-04-17 07:46:28 +0200199 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200200 */
201static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
202{
203 register unsigned long reg0 asm ("0") = qid | 0x01000000UL;
204 register struct ap_queue_status reg1 asm ("1");
205 register unsigned long reg2 asm ("2") = 0UL;
206
207 asm volatile(
208 ".long 0xb2af0000" /* PQAP(RAPQ) */
209 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
210 return reg1;
211}
212
Felix Beckcb17a632008-12-25 13:38:41 +0100213#ifdef CONFIG_64BIT
214/**
215 * ap_queue_interruption_control(): Enable interruption for a specific AP.
216 * @qid: The AP queue number
217 * @ind: The notification indicator byte
218 *
219 * Returns AP queue status.
220 */
221static inline struct ap_queue_status
222ap_queue_interruption_control(ap_qid_t qid, void *ind)
223{
224 register unsigned long reg0 asm ("0") = qid | 0x03000000UL;
225 register unsigned long reg1_in asm ("1") = 0x0000800000000000UL | AP_ISC;
226 register struct ap_queue_status reg1_out asm ("1");
227 register void *reg2 asm ("2") = ind;
228 asm volatile(
Holger Denglera7475af2012-05-16 14:10:26 +0200229 ".long 0xb2af0000" /* PQAP(AQIC) */
Felix Beckcb17a632008-12-25 13:38:41 +0100230 : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
231 :
232 : "cc" );
233 return reg1_out;
234}
235#endif
236
Holger Dengler6bed05b2011-07-24 10:48:25 +0200237#ifdef CONFIG_64BIT
238static inline struct ap_queue_status
239__ap_query_functions(ap_qid_t qid, unsigned int *functions)
Felix Beckb1f933d2011-01-05 12:47:44 +0100240{
241 register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
Holger Dengler6bed05b2011-07-24 10:48:25 +0200242 register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
243 register unsigned long reg2 asm ("2");
Felix Beckb1f933d2011-01-05 12:47:44 +0100244
245 asm volatile(
Holger Denglera7475af2012-05-16 14:10:26 +0200246 ".long 0xb2af0000\n" /* PQAP(TAPQ) */
Holger Dengler6bed05b2011-07-24 10:48:25 +0200247 "0:\n"
248 EX_TABLE(0b, 0b)
249 : "+d" (reg0), "+d" (reg1), "=d" (reg2)
Felix Beckb1f933d2011-01-05 12:47:44 +0100250 :
251 : "cc");
252
Holger Dengler6bed05b2011-07-24 10:48:25 +0200253 *functions = (unsigned int)(reg2 >> 32);
Felix Beckb1f933d2011-01-05 12:47:44 +0100254 return reg1;
255}
Holger Dengler6bed05b2011-07-24 10:48:25 +0200256#endif
257
Holger Dengler75014552012-08-28 16:41:50 +0200258#ifdef CONFIG_64BIT
259static inline int __ap_query_configuration(struct ap_config_info *config)
260{
261 register unsigned long reg0 asm ("0") = 0x04000000UL;
262 register unsigned long reg1 asm ("1") = -EINVAL;
263 register unsigned char *reg2 asm ("2") = (unsigned char *)config;
264
265 asm volatile(
266 ".long 0xb2af0000\n" /* PQAP(QCI) */
267 "0: la %1,0\n"
268 "1:\n"
269 EX_TABLE(0b, 1b)
270 : "+d" (reg0), "+d" (reg1), "+d" (reg2)
271 :
272 : "cc");
273
274 return reg1;
275}
276#endif
277
Holger Dengler6bed05b2011-07-24 10:48:25 +0200278/**
279 * ap_query_functions(): Query supported functions.
280 * @qid: The AP queue number
281 * @functions: Pointer to functions field.
282 *
283 * Returns
284 * 0 on success.
285 * -ENODEV if queue not valid.
286 * -EBUSY if device busy.
287 * -EINVAL if query function is not supported
288 */
289static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
290{
291#ifdef CONFIG_64BIT
292 struct ap_queue_status status;
293 int i;
294 status = __ap_query_functions(qid, functions);
295
296 for (i = 0; i < AP_MAX_RESET; i++) {
297 if (ap_queue_status_invalid_test(&status))
298 return -ENODEV;
299
300 switch (status.response_code) {
301 case AP_RESPONSE_NORMAL:
302 return 0;
303 case AP_RESPONSE_RESET_IN_PROGRESS:
304 case AP_RESPONSE_BUSY:
305 break;
306 case AP_RESPONSE_Q_NOT_AVAIL:
307 case AP_RESPONSE_DECONFIGURED:
308 case AP_RESPONSE_CHECKSTOPPED:
309 case AP_RESPONSE_INVALID_ADDRESS:
310 return -ENODEV;
311 case AP_RESPONSE_OTHERWISE_CHANGED:
312 break;
313 default:
314 break;
315 }
316 if (i < AP_MAX_RESET - 1) {
317 udelay(5);
318 status = __ap_query_functions(qid, functions);
319 }
320 }
321 return -EBUSY;
322#else
323 return -EINVAL;
324#endif
325}
Felix Beckb1f933d2011-01-05 12:47:44 +0100326
327/**
Felix Beckcb17a632008-12-25 13:38:41 +0100328 * ap_queue_enable_interruption(): Enable interruption on an AP.
329 * @qid: The AP queue number
330 * @ind: the notification indicator byte
331 *
332 * Enables interruption on AP queue via ap_queue_interruption_control(). Based
333 * on the return value it waits a while and tests the AP queue if interrupts
334 * have been switched on using ap_test_queue().
335 */
336static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
337{
338#ifdef CONFIG_64BIT
339 struct ap_queue_status status;
340 int t_depth, t_device_type, rc, i;
341
342 rc = -EBUSY;
343 status = ap_queue_interruption_control(qid, ind);
344
345 for (i = 0; i < AP_MAX_RESET; i++) {
346 switch (status.response_code) {
347 case AP_RESPONSE_NORMAL:
348 if (status.int_enabled)
349 return 0;
350 break;
351 case AP_RESPONSE_RESET_IN_PROGRESS:
352 case AP_RESPONSE_BUSY:
Holger Dengler8738e072012-07-02 12:39:59 +0200353 if (i < AP_MAX_RESET - 1) {
354 udelay(5);
355 status = ap_queue_interruption_control(qid,
356 ind);
357 continue;
358 }
Felix Beckcb17a632008-12-25 13:38:41 +0100359 break;
360 case AP_RESPONSE_Q_NOT_AVAIL:
361 case AP_RESPONSE_DECONFIGURED:
362 case AP_RESPONSE_CHECKSTOPPED:
363 case AP_RESPONSE_INVALID_ADDRESS:
364 return -ENODEV;
365 case AP_RESPONSE_OTHERWISE_CHANGED:
366 if (status.int_enabled)
367 return 0;
368 break;
369 default:
370 break;
371 }
372 if (i < AP_MAX_RESET - 1) {
373 udelay(5);
374 status = ap_test_queue(qid, &t_depth, &t_device_type);
375 }
376 }
377 return rc;
378#else
379 return -EINVAL;
380#endif
381}
382
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200383/**
Felix Beck1749a812008-04-17 07:46:28 +0200384 * __ap_send(): Send message to adjunct processor queue.
385 * @qid: The AP queue number
386 * @psmid: The program supplied message identifier
387 * @msg: The message text
388 * @length: The message length
Felix Becka6a5d732009-12-07 12:51:55 +0100389 * @special: Special Bit
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200390 *
Felix Beck1749a812008-04-17 07:46:28 +0200391 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200392 * Condition code 1 on NQAP can't happen because the L bit is 1.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200393 * Condition code 2 on NQAP also means the send is incomplete,
394 * because a segment boundary was reached. The NQAP is repeated.
395 */
396static inline struct ap_queue_status
Felix Becka6a5d732009-12-07 12:51:55 +0100397__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length,
398 unsigned int special)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200399{
400 typedef struct { char _[length]; } msgblock;
401 register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
402 register struct ap_queue_status reg1 asm ("1");
403 register unsigned long reg2 asm ("2") = (unsigned long) msg;
404 register unsigned long reg3 asm ("3") = (unsigned long) length;
405 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
406 register unsigned long reg5 asm ("5") = (unsigned int) psmid;
407
Felix Becka6a5d732009-12-07 12:51:55 +0100408 if (special == 1)
409 reg0 |= 0x400000UL;
410
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200411 asm volatile (
Holger Denglera7475af2012-05-16 14:10:26 +0200412 "0: .long 0xb2ad0042\n" /* NQAP */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200413 " brc 2,0b"
414 : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
415 : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg)
416 : "cc" );
417 return reg1;
418}
419
420int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
421{
422 struct ap_queue_status status;
423
Felix Becka6a5d732009-12-07 12:51:55 +0100424 status = __ap_send(qid, psmid, msg, length, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200425 switch (status.response_code) {
426 case AP_RESPONSE_NORMAL:
427 return 0;
428 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200429 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200430 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +0100431 case AP_RESPONSE_REQ_FAC_NOT_INST:
432 return -EINVAL;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200433 default: /* Device is gone. */
434 return -ENODEV;
435 }
436}
437EXPORT_SYMBOL(ap_send);
438
Felix Beck1749a812008-04-17 07:46:28 +0200439/**
440 * __ap_recv(): Receive message from adjunct processor queue.
441 * @qid: The AP queue number
442 * @psmid: Pointer to program supplied message identifier
443 * @msg: The message text
444 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200445 *
Felix Beck1749a812008-04-17 07:46:28 +0200446 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200447 * Condition code 1 on DQAP means the receive has taken place
448 * but only partially. The response is incomplete, hence the
449 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200450 * Condition code 2 on DQAP also means the receive is incomplete,
451 * this time because a segment boundary was reached. Again, the
452 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200453 * Note that gpr2 is used by the DQAP instruction to keep track of
454 * any 'residual' length, in case the instruction gets interrupted.
455 * Hence it gets zeroed before the instruction.
456 */
457static inline struct ap_queue_status
458__ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
459{
460 typedef struct { char _[length]; } msgblock;
461 register unsigned long reg0 asm("0") = qid | 0x80000000UL;
462 register struct ap_queue_status reg1 asm ("1");
463 register unsigned long reg2 asm("2") = 0UL;
464 register unsigned long reg4 asm("4") = (unsigned long) msg;
465 register unsigned long reg5 asm("5") = (unsigned long) length;
466 register unsigned long reg6 asm("6") = 0UL;
467 register unsigned long reg7 asm("7") = 0UL;
468
469
470 asm volatile(
Holger Denglera7475af2012-05-16 14:10:26 +0200471 "0: .long 0xb2ae0064\n" /* DQAP */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200472 " brc 6,0b\n"
473 : "+d" (reg0), "=d" (reg1), "+d" (reg2),
474 "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
475 "=m" (*(msgblock *) msg) : : "cc" );
476 *psmid = (((unsigned long long) reg6) << 32) + reg7;
477 return reg1;
478}
479
480int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
481{
482 struct ap_queue_status status;
483
484 status = __ap_recv(qid, psmid, msg, length);
485 switch (status.response_code) {
486 case AP_RESPONSE_NORMAL:
487 return 0;
488 case AP_RESPONSE_NO_PENDING_REPLY:
489 if (status.queue_empty)
490 return -ENOENT;
491 return -EBUSY;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200492 case AP_RESPONSE_RESET_IN_PROGRESS:
493 return -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200494 default:
495 return -ENODEV;
496 }
497}
498EXPORT_SYMBOL(ap_recv);
499
500/**
Felix Beck1749a812008-04-17 07:46:28 +0200501 * ap_query_queue(): Check if an AP queue is available.
502 * @qid: The AP queue number
503 * @queue_depth: Pointer to queue depth value
504 * @device_type: Pointer to device type value
505 *
506 * The test is repeated for AP_MAX_RESET times.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200507 */
508static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
509{
510 struct ap_queue_status status;
511 int t_depth, t_device_type, rc, i;
512
513 rc = -EBUSY;
514 for (i = 0; i < AP_MAX_RESET; i++) {
515 status = ap_test_queue(qid, &t_depth, &t_device_type);
516 switch (status.response_code) {
517 case AP_RESPONSE_NORMAL:
518 *queue_depth = t_depth + 1;
519 *device_type = t_device_type;
520 rc = 0;
521 break;
522 case AP_RESPONSE_Q_NOT_AVAIL:
523 rc = -ENODEV;
524 break;
525 case AP_RESPONSE_RESET_IN_PROGRESS:
526 break;
527 case AP_RESPONSE_DECONFIGURED:
528 rc = -ENODEV;
529 break;
530 case AP_RESPONSE_CHECKSTOPPED:
531 rc = -ENODEV;
532 break;
Felix Beckcb17a632008-12-25 13:38:41 +0100533 case AP_RESPONSE_INVALID_ADDRESS:
534 rc = -ENODEV;
535 break;
536 case AP_RESPONSE_OTHERWISE_CHANGED:
537 break;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200538 case AP_RESPONSE_BUSY:
539 break;
540 default:
541 BUG();
542 }
543 if (rc != -EBUSY)
544 break;
545 if (i < AP_MAX_RESET - 1)
546 udelay(5);
547 }
548 return rc;
549}
550
551/**
Felix Beck1749a812008-04-17 07:46:28 +0200552 * ap_init_queue(): Reset an AP queue.
553 * @qid: The AP queue number
554 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200555 * Reset an AP queue and wait for it to become available again.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200556 */
557static int ap_init_queue(ap_qid_t qid)
558{
559 struct ap_queue_status status;
560 int rc, dummy, i;
561
562 rc = -ENODEV;
563 status = ap_reset_queue(qid);
564 for (i = 0; i < AP_MAX_RESET; i++) {
565 switch (status.response_code) {
566 case AP_RESPONSE_NORMAL:
567 if (status.queue_empty)
568 rc = 0;
569 break;
570 case AP_RESPONSE_Q_NOT_AVAIL:
571 case AP_RESPONSE_DECONFIGURED:
572 case AP_RESPONSE_CHECKSTOPPED:
573 i = AP_MAX_RESET; /* return with -ENODEV */
574 break;
575 case AP_RESPONSE_RESET_IN_PROGRESS:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200576 rc = -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200577 case AP_RESPONSE_BUSY:
578 default:
579 break;
580 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200581 if (rc != -ENODEV && rc != -EBUSY)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200582 break;
583 if (i < AP_MAX_RESET - 1) {
584 udelay(5);
585 status = ap_test_queue(qid, &dummy, &dummy);
586 }
587 }
Felix Beckcb17a632008-12-25 13:38:41 +0100588 if (rc == 0 && ap_using_interrupts()) {
589 rc = ap_queue_enable_interruption(qid, ap_interrupt_indicator);
590 /* If interruption mode is supported by the machine,
591 * but an AP can not be enabled for interruption then
592 * the AP will be discarded. */
593 if (rc)
594 pr_err("Registering adapter interrupts for "
595 "AP %d failed\n", AP_QID_DEVICE(qid));
596 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200597 return rc;
598}
599
600/**
Felix Beck1749a812008-04-17 07:46:28 +0200601 * ap_increase_queue_count(): Arm request timeout.
602 * @ap_dev: Pointer to an AP device.
603 *
604 * Arm request timeout if an AP device was idle and a new request is submitted.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200605 */
606static void ap_increase_queue_count(struct ap_device *ap_dev)
607{
608 int timeout = ap_dev->drv->request_timeout;
609
610 ap_dev->queue_count++;
611 if (ap_dev->queue_count == 1) {
612 mod_timer(&ap_dev->timeout, jiffies + timeout);
613 ap_dev->reset = AP_RESET_ARMED;
614 }
615}
616
617/**
Felix Beck1749a812008-04-17 07:46:28 +0200618 * ap_decrease_queue_count(): Decrease queue count.
619 * @ap_dev: Pointer to an AP device.
620 *
621 * If AP device is still alive, re-schedule request timeout if there are still
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200622 * pending requests.
623 */
624static void ap_decrease_queue_count(struct ap_device *ap_dev)
625{
626 int timeout = ap_dev->drv->request_timeout;
627
628 ap_dev->queue_count--;
629 if (ap_dev->queue_count > 0)
630 mod_timer(&ap_dev->timeout, jiffies + timeout);
631 else
Felix Beck1749a812008-04-17 07:46:28 +0200632 /*
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200633 * The timeout timer should to be disabled now - since
634 * del_timer_sync() is very expensive, we just tell via the
635 * reset flag to ignore the pending timeout timer.
636 */
637 ap_dev->reset = AP_RESET_IGNORE;
638}
639
Felix Beck1749a812008-04-17 07:46:28 +0200640/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200641 * AP device related attributes.
642 */
643static ssize_t ap_hwtype_show(struct device *dev,
644 struct device_attribute *attr, char *buf)
645{
646 struct ap_device *ap_dev = to_ap_dev(dev);
647 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type);
648}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200649
Christian Maaser43c207e62008-12-25 13:38:42 +0100650static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200651static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr,
652 char *buf)
653{
654 struct ap_device *ap_dev = to_ap_dev(dev);
655 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth);
656}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200657
Christian Maaser43c207e62008-12-25 13:38:42 +0100658static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200659static ssize_t ap_request_count_show(struct device *dev,
660 struct device_attribute *attr,
661 char *buf)
662{
663 struct ap_device *ap_dev = to_ap_dev(dev);
664 int rc;
665
666 spin_lock_bh(&ap_dev->lock);
667 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->total_request_count);
668 spin_unlock_bh(&ap_dev->lock);
669 return rc;
670}
671
672static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL);
673
Holger Denglerb26bd942012-08-28 16:43:48 +0200674static ssize_t ap_requestq_count_show(struct device *dev,
675 struct device_attribute *attr, char *buf)
676{
677 struct ap_device *ap_dev = to_ap_dev(dev);
678 int rc;
679
680 spin_lock_bh(&ap_dev->lock);
681 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->requestq_count);
682 spin_unlock_bh(&ap_dev->lock);
683 return rc;
684}
685
686static DEVICE_ATTR(requestq_count, 0444, ap_requestq_count_show, NULL);
687
688static ssize_t ap_pendingq_count_show(struct device *dev,
689 struct device_attribute *attr, char *buf)
690{
691 struct ap_device *ap_dev = to_ap_dev(dev);
692 int rc;
693
694 spin_lock_bh(&ap_dev->lock);
695 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->pendingq_count);
696 spin_unlock_bh(&ap_dev->lock);
697 return rc;
698}
699
700static DEVICE_ATTR(pendingq_count, 0444, ap_pendingq_count_show, NULL);
701
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200702static ssize_t ap_modalias_show(struct device *dev,
703 struct device_attribute *attr, char *buf)
704{
705 return sprintf(buf, "ap:t%02X", to_ap_dev(dev)->device_type);
706}
707
708static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL);
709
Holger Denglerb26bd942012-08-28 16:43:48 +0200710static ssize_t ap_functions_show(struct device *dev,
711 struct device_attribute *attr, char *buf)
712{
713 struct ap_device *ap_dev = to_ap_dev(dev);
714 return snprintf(buf, PAGE_SIZE, "0x%08X\n", ap_dev->functions);
715}
716
717static DEVICE_ATTR(ap_functions, 0444, ap_functions_show, NULL);
718
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200719static struct attribute *ap_dev_attrs[] = {
720 &dev_attr_hwtype.attr,
721 &dev_attr_depth.attr,
722 &dev_attr_request_count.attr,
Holger Denglerb26bd942012-08-28 16:43:48 +0200723 &dev_attr_requestq_count.attr,
724 &dev_attr_pendingq_count.attr,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200725 &dev_attr_modalias.attr,
Holger Denglerb26bd942012-08-28 16:43:48 +0200726 &dev_attr_ap_functions.attr,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200727 NULL
728};
729static struct attribute_group ap_dev_attr_group = {
730 .attrs = ap_dev_attrs
731};
732
733/**
Felix Beck1749a812008-04-17 07:46:28 +0200734 * ap_bus_match()
735 * @dev: Pointer to device
736 * @drv: Pointer to device_driver
737 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200738 * AP bus driver registration/unregistration.
739 */
740static int ap_bus_match(struct device *dev, struct device_driver *drv)
741{
742 struct ap_device *ap_dev = to_ap_dev(dev);
743 struct ap_driver *ap_drv = to_ap_drv(drv);
744 struct ap_device_id *id;
745
Felix Beck1749a812008-04-17 07:46:28 +0200746 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200747 * Compare device type of the device with the list of
748 * supported types of the device_driver.
749 */
750 for (id = ap_drv->ids; id->match_flags; id++) {
751 if ((id->match_flags & AP_DEVICE_ID_MATCH_DEVICE_TYPE) &&
752 (id->dev_type != ap_dev->device_type))
753 continue;
754 return 1;
755 }
756 return 0;
757}
758
759/**
Felix Beck1749a812008-04-17 07:46:28 +0200760 * ap_uevent(): Uevent function for AP devices.
761 * @dev: Pointer to device
762 * @env: Pointer to kobj_uevent_env
763 *
764 * It sets up a single environment variable DEV_TYPE which contains the
765 * hardware device type.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200766 */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200767static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200768{
769 struct ap_device *ap_dev = to_ap_dev(dev);
Kay Sievers7eff2e72007-08-14 15:15:12 +0200770 int retval = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200771
772 if (!ap_dev)
773 return -ENODEV;
774
775 /* Set up DEV_TYPE environment variable. */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200776 retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700777 if (retval)
778 return retval;
779
Cornelia Huck66a4263b2006-12-04 15:40:10 +0100780 /* Add MODALIAS= */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200781 retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700782
Eric Rannaudbf624562007-03-30 22:23:12 -0700783 return retval;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200784}
785
Felix Beck772f5472009-06-22 12:08:16 +0200786static int ap_bus_suspend(struct device *dev, pm_message_t state)
787{
788 struct ap_device *ap_dev = to_ap_dev(dev);
789 unsigned long flags;
790
791 if (!ap_suspend_flag) {
792 ap_suspend_flag = 1;
793
794 /* Disable scanning for devices, thus we do not want to scan
795 * for them after removing.
796 */
797 del_timer_sync(&ap_config_timer);
798 if (ap_work_queue != NULL) {
799 destroy_workqueue(ap_work_queue);
800 ap_work_queue = NULL;
801 }
Felix Beck5314af62009-09-22 22:58:51 +0200802
Felix Beck772f5472009-06-22 12:08:16 +0200803 tasklet_disable(&ap_tasklet);
804 }
805 /* Poll on the device until all requests are finished. */
806 do {
807 flags = 0;
Felix Beck95f15562009-09-11 10:28:51 +0200808 spin_lock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200809 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +0200810 spin_unlock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200811 } while ((flags & 1) || (flags & 2));
812
Felix Beck5314af62009-09-22 22:58:51 +0200813 spin_lock_bh(&ap_dev->lock);
814 ap_dev->unregistered = 1;
815 spin_unlock_bh(&ap_dev->lock);
816
Felix Beck772f5472009-06-22 12:08:16 +0200817 return 0;
818}
819
820static int ap_bus_resume(struct device *dev)
821{
822 int rc = 0;
823 struct ap_device *ap_dev = to_ap_dev(dev);
824
825 if (ap_suspend_flag) {
826 ap_suspend_flag = 0;
827 if (!ap_interrupts_available())
828 ap_interrupt_indicator = NULL;
Holger Dengler75014552012-08-28 16:41:50 +0200829 ap_query_configuration();
Felix Beck5314af62009-09-22 22:58:51 +0200830 if (!user_set_domain) {
831 ap_domain_index = -1;
832 ap_select_domain();
833 }
Felix Beck772f5472009-06-22 12:08:16 +0200834 init_timer(&ap_config_timer);
835 ap_config_timer.function = ap_config_timeout;
836 ap_config_timer.data = 0;
837 ap_config_timer.expires = jiffies + ap_config_time * HZ;
838 add_timer(&ap_config_timer);
839 ap_work_queue = create_singlethread_workqueue("kapwork");
840 if (!ap_work_queue)
841 return -ENOMEM;
842 tasklet_enable(&ap_tasklet);
843 if (!ap_using_interrupts())
844 ap_schedule_poll_timer();
845 else
846 tasklet_schedule(&ap_tasklet);
847 if (ap_thread_flag)
848 rc = ap_poll_thread_start();
Felix Beck772f5472009-06-22 12:08:16 +0200849 }
Felix Beck5314af62009-09-22 22:58:51 +0200850 if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) {
851 spin_lock_bh(&ap_dev->lock);
852 ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid),
853 ap_domain_index);
854 spin_unlock_bh(&ap_dev->lock);
855 }
856 queue_work(ap_work_queue, &ap_config_work);
Felix Beck772f5472009-06-22 12:08:16 +0200857
858 return rc;
859}
860
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200861static struct bus_type ap_bus_type = {
862 .name = "ap",
863 .match = &ap_bus_match,
864 .uevent = &ap_uevent,
Felix Beck772f5472009-06-22 12:08:16 +0200865 .suspend = ap_bus_suspend,
866 .resume = ap_bus_resume
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200867};
868
869static int ap_device_probe(struct device *dev)
870{
871 struct ap_device *ap_dev = to_ap_dev(dev);
872 struct ap_driver *ap_drv = to_ap_drv(dev->driver);
873 int rc;
874
875 ap_dev->drv = ap_drv;
876 rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100877 if (!rc) {
Christian Maaser43c207e62008-12-25 13:38:42 +0100878 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100879 list_add(&ap_dev->list, &ap_device_list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100880 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100881 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200882 return rc;
883}
884
885/**
Felix Beck1749a812008-04-17 07:46:28 +0200886 * __ap_flush_queue(): Flush requests.
887 * @ap_dev: Pointer to the AP device
888 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200889 * Flush all requests from the request/pending queue of an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200890 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100891static void __ap_flush_queue(struct ap_device *ap_dev)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200892{
893 struct ap_message *ap_msg, *next;
894
895 list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
896 list_del_init(&ap_msg->list);
897 ap_dev->pendingq_count--;
Holger Dengler54a8f562012-05-16 14:08:22 +0200898 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200899 }
900 list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
901 list_del_init(&ap_msg->list);
902 ap_dev->requestq_count--;
Holger Dengler54a8f562012-05-16 14:08:22 +0200903 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200904 }
905}
906
907void ap_flush_queue(struct ap_device *ap_dev)
908{
909 spin_lock_bh(&ap_dev->lock);
910 __ap_flush_queue(ap_dev);
911 spin_unlock_bh(&ap_dev->lock);
912}
913EXPORT_SYMBOL(ap_flush_queue);
914
915static int ap_device_remove(struct device *dev)
916{
917 struct ap_device *ap_dev = to_ap_dev(dev);
918 struct ap_driver *ap_drv = ap_dev->drv;
919
Ralph Wuerthner4e562962006-10-04 20:02:05 +0200920 ap_flush_queue(ap_dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200921 del_timer_sync(&ap_dev->timeout);
Christian Maaser43c207e62008-12-25 13:38:42 +0100922 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +0100923 list_del_init(&ap_dev->list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100924 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100925 if (ap_drv->remove)
926 ap_drv->remove(ap_dev);
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +0200927 spin_lock_bh(&ap_dev->lock);
928 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
929 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200930 return 0;
931}
932
933int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
934 char *name)
935{
936 struct device_driver *drv = &ap_drv->driver;
937
938 drv->bus = &ap_bus_type;
939 drv->probe = ap_device_probe;
940 drv->remove = ap_device_remove;
941 drv->owner = owner;
942 drv->name = name;
943 return driver_register(drv);
944}
945EXPORT_SYMBOL(ap_driver_register);
946
947void ap_driver_unregister(struct ap_driver *ap_drv)
948{
949 driver_unregister(&ap_drv->driver);
950}
951EXPORT_SYMBOL(ap_driver_unregister);
952
Holger Denglerdabecb22012-09-10 21:34:26 +0200953void ap_bus_force_rescan(void)
954{
955 /* Delete the AP bus rescan timer. */
956 del_timer(&ap_config_timer);
957
958 /* processing a synchonuous bus rescan */
959 ap_scan_bus(NULL);
960
961 /* Setup the AP bus rescan timer again. */
962 ap_config_timer.expires = jiffies + ap_config_time * HZ;
963 add_timer(&ap_config_timer);
964}
965EXPORT_SYMBOL(ap_bus_force_rescan);
966
Felix Beck1749a812008-04-17 07:46:28 +0200967/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200968 * AP bus attributes.
969 */
970static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
971{
972 return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
973}
974
975static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
976
977static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
978{
979 return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
980}
981
Felix Beckcb17a632008-12-25 13:38:41 +0100982static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
983{
984 return snprintf(buf, PAGE_SIZE, "%d\n",
985 ap_using_interrupts() ? 1 : 0);
986}
987
988static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL);
989
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200990static ssize_t ap_config_time_store(struct bus_type *bus,
991 const char *buf, size_t count)
992{
993 int time;
994
995 if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120)
996 return -EINVAL;
997 ap_config_time = time;
998 if (!timer_pending(&ap_config_timer) ||
999 !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) {
1000 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1001 add_timer(&ap_config_timer);
1002 }
1003 return count;
1004}
1005
1006static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store);
1007
1008static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf)
1009{
1010 return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
1011}
1012
1013static ssize_t ap_poll_thread_store(struct bus_type *bus,
1014 const char *buf, size_t count)
1015{
1016 int flag, rc;
1017
1018 if (sscanf(buf, "%d\n", &flag) != 1)
1019 return -EINVAL;
1020 if (flag) {
1021 rc = ap_poll_thread_start();
1022 if (rc)
1023 return rc;
1024 }
1025 else
1026 ap_poll_thread_stop();
1027 return count;
1028}
1029
1030static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
1031
Felix Beckfe137232008-07-14 09:59:08 +02001032static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
1033{
1034 return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
1035}
1036
1037static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
1038 size_t count)
1039{
1040 unsigned long long time;
1041 ktime_t hr_time;
1042
1043 /* 120 seconds = maximum poll interval */
Felix Beckcb17a632008-12-25 13:38:41 +01001044 if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 ||
1045 time > 120000000000ULL)
Felix Beckfe137232008-07-14 09:59:08 +02001046 return -EINVAL;
1047 poll_timeout = time;
1048 hr_time = ktime_set(0, poll_timeout);
1049
1050 if (!hrtimer_is_queued(&ap_poll_timer) ||
Arjan van de Ven6c644ea2008-09-01 15:20:30 -07001051 !hrtimer_forward(&ap_poll_timer, hrtimer_get_expires(&ap_poll_timer), hr_time)) {
1052 hrtimer_set_expires(&ap_poll_timer, hr_time);
1053 hrtimer_start_expires(&ap_poll_timer, HRTIMER_MODE_ABS);
Felix Beckfe137232008-07-14 09:59:08 +02001054 }
1055 return count;
1056}
1057
1058static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
1059
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001060static struct bus_attribute *const ap_bus_attrs[] = {
1061 &bus_attr_ap_domain,
1062 &bus_attr_config_time,
1063 &bus_attr_poll_thread,
Felix Beckcb17a632008-12-25 13:38:41 +01001064 &bus_attr_ap_interrupts,
Felix Beckfe137232008-07-14 09:59:08 +02001065 &bus_attr_poll_timeout,
1066 NULL,
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001067};
1068
Holger Dengler75014552012-08-28 16:41:50 +02001069static inline int ap_test_config(unsigned int *field, unsigned int nr)
1070{
1071 if (nr > 0xFFu)
1072 return 0;
1073 return ap_test_bit((field + (nr >> 5)), (nr & 0x1f));
1074}
1075
1076/*
1077 * ap_test_config_card_id(): Test, whether an AP card ID is configured.
1078 * @id AP card ID
1079 *
1080 * Returns 0 if the card is not configured
1081 * 1 if the card is configured or
1082 * if the configuration information is not available
1083 */
1084static inline int ap_test_config_card_id(unsigned int id)
1085{
1086 if (!ap_configuration)
1087 return 1;
1088 return ap_test_config(ap_configuration->apm, id);
1089}
1090
1091/*
1092 * ap_test_config_domain(): Test, whether an AP usage domain is configured.
1093 * @domain AP usage domain ID
1094 *
1095 * Returns 0 if the usage domain is not configured
1096 * 1 if the usage domain is configured or
1097 * if the configuration information is not available
1098 */
1099static inline int ap_test_config_domain(unsigned int domain)
1100{
1101 if (!ap_configuration)
1102 return 1;
1103 return ap_test_config(ap_configuration->aqm, domain);
1104}
1105
1106/**
1107 * ap_query_configuration(): Query AP configuration information.
1108 *
1109 * Query information of installed cards and configured domains from AP.
1110 */
1111static void ap_query_configuration(void)
1112{
1113#ifdef CONFIG_64BIT
1114 if (ap_configuration_available()) {
1115 if (!ap_configuration)
1116 ap_configuration =
1117 kzalloc(sizeof(struct ap_config_info),
1118 GFP_KERNEL);
1119 if (ap_configuration)
1120 __ap_query_configuration(ap_configuration);
1121 } else
1122 ap_configuration = NULL;
1123#else
1124 ap_configuration = NULL;
1125#endif
1126}
1127
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001128/**
Felix Beck1749a812008-04-17 07:46:28 +02001129 * ap_select_domain(): Select an AP domain.
1130 *
1131 * Pick one of the 16 AP domains.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001132 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001133static int ap_select_domain(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001134{
1135 int queue_depth, device_type, count, max_count, best_domain;
Holger Dengler75014552012-08-28 16:41:50 +02001136 ap_qid_t qid;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001137 int rc, i, j;
1138
Felix Beck1749a812008-04-17 07:46:28 +02001139 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001140 * We want to use a single domain. Either the one specified with
1141 * the "domain=" parameter or the domain with the maximum number
1142 * of devices.
1143 */
1144 if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS)
1145 /* Domain has already been selected. */
1146 return 0;
1147 best_domain = -1;
1148 max_count = 0;
1149 for (i = 0; i < AP_DOMAINS; i++) {
Holger Dengler75014552012-08-28 16:41:50 +02001150 if (!ap_test_config_domain(i))
1151 continue;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001152 count = 0;
1153 for (j = 0; j < AP_DEVICES; j++) {
Holger Dengler75014552012-08-28 16:41:50 +02001154 if (!ap_test_config_card_id(j))
1155 continue;
1156 qid = AP_MKQID(j, i);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001157 rc = ap_query_queue(qid, &queue_depth, &device_type);
1158 if (rc)
1159 continue;
1160 count++;
1161 }
1162 if (count > max_count) {
1163 max_count = count;
1164 best_domain = i;
1165 }
1166 }
1167 if (best_domain >= 0){
1168 ap_domain_index = best_domain;
1169 return 0;
1170 }
1171 return -ENODEV;
1172}
1173
1174/**
Felix Beck1749a812008-04-17 07:46:28 +02001175 * ap_probe_device_type(): Find the device type of an AP.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001176 * @ap_dev: pointer to the AP device.
Felix Beck1749a812008-04-17 07:46:28 +02001177 *
1178 * Find the device type if query queue returned a device type of 0.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001179 */
1180static int ap_probe_device_type(struct ap_device *ap_dev)
1181{
1182 static unsigned char msg[] = {
1183 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
1184 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1185 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
1186 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1187 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50,
1188 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,
1189 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00,
1190 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,
1191 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1192 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,
1193 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1194 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,
1195 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00,
1196 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1197 0x00,0x00,0x00,0x00,0xb8,0x05,0x00,0x00,
1198 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1199 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1200 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1201 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1202 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1203 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1204 0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,
1205 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1206 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
1207 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20,
1208 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,
1209 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22,
1210 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1211 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
1212 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,
1213 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,
1214 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,
1215 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1216 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,
1217 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00,
1218 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,
1219 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01,
1220 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,
1221 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68,
1222 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,
1223 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0,
1224 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,
1225 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04,
1226 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,
1227 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d,
1228 };
1229 struct ap_queue_status status;
1230 unsigned long long psmid;
1231 char *reply;
1232 int rc, i;
1233
1234 reply = (void *) get_zeroed_page(GFP_KERNEL);
1235 if (!reply) {
1236 rc = -ENOMEM;
1237 goto out;
1238 }
1239
1240 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
Felix Becka6a5d732009-12-07 12:51:55 +01001241 msg, sizeof(msg), 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001242 if (status.response_code != AP_RESPONSE_NORMAL) {
1243 rc = -ENODEV;
1244 goto out_free;
1245 }
1246
1247 /* Wait for the test message to complete. */
1248 for (i = 0; i < 6; i++) {
1249 mdelay(300);
1250 status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
1251 if (status.response_code == AP_RESPONSE_NORMAL &&
1252 psmid == 0x0102030405060708ULL)
1253 break;
1254 }
1255 if (i < 6) {
1256 /* Got an answer. */
1257 if (reply[0] == 0x00 && reply[1] == 0x86)
1258 ap_dev->device_type = AP_DEVICE_TYPE_PCICC;
1259 else
1260 ap_dev->device_type = AP_DEVICE_TYPE_PCICA;
1261 rc = 0;
1262 } else
1263 rc = -ENODEV;
1264
1265out_free:
1266 free_page((unsigned long) reply);
1267out:
1268 return rc;
1269}
1270
Felix Beckcb17a632008-12-25 13:38:41 +01001271static void ap_interrupt_handler(void *unused1, void *unused2)
1272{
Holger Dengler62d146f2011-01-05 12:47:38 +01001273 kstat_cpu(smp_processor_id()).irqs[IOINT_APB]++;
Felix Beckcb17a632008-12-25 13:38:41 +01001274 tasklet_schedule(&ap_tasklet);
1275}
1276
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001277/**
Felix Beck1749a812008-04-17 07:46:28 +02001278 * __ap_scan_bus(): Scan the AP bus.
1279 * @dev: Pointer to device
1280 * @data: Pointer to data
1281 *
1282 * Scan the AP bus for new devices.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001283 */
1284static int __ap_scan_bus(struct device *dev, void *data)
1285{
1286 return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data;
1287}
1288
1289static void ap_device_release(struct device *dev)
1290{
1291 struct ap_device *ap_dev = to_ap_dev(dev);
1292
1293 kfree(ap_dev);
1294}
1295
Al Viro4927b3f2006-12-06 19:18:20 +00001296static void ap_scan_bus(struct work_struct *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001297{
1298 struct ap_device *ap_dev;
1299 struct device *dev;
1300 ap_qid_t qid;
1301 int queue_depth, device_type;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001302 unsigned int device_functions;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001303 int rc, i;
1304
Holger Dengler75014552012-08-28 16:41:50 +02001305 ap_query_configuration();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001306 if (ap_select_domain() != 0)
1307 return;
1308 for (i = 0; i < AP_DEVICES; i++) {
1309 qid = AP_MKQID(i, ap_domain_index);
1310 dev = bus_find_device(&ap_bus_type, NULL,
1311 (void *)(unsigned long)qid,
1312 __ap_scan_bus);
Holger Dengler75014552012-08-28 16:41:50 +02001313 if (ap_test_config_card_id(i))
1314 rc = ap_query_queue(qid, &queue_depth, &device_type);
1315 else
1316 rc = -ENODEV;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001317 if (dev) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001318 if (rc == -EBUSY) {
1319 set_current_state(TASK_UNINTERRUPTIBLE);
1320 schedule_timeout(AP_RESET_TIMEOUT);
1321 rc = ap_query_queue(qid, &queue_depth,
1322 &device_type);
1323 }
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001324 ap_dev = to_ap_dev(dev);
1325 spin_lock_bh(&ap_dev->lock);
1326 if (rc || ap_dev->unregistered) {
1327 spin_unlock_bh(&ap_dev->lock);
Felix Beck5314af62009-09-22 22:58:51 +02001328 if (ap_dev->unregistered)
1329 i--;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001330 device_unregister(dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001331 put_device(dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001332 continue;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001333 }
1334 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001335 put_device(dev);
1336 continue;
1337 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001338 if (rc)
1339 continue;
1340 rc = ap_init_queue(qid);
1341 if (rc)
1342 continue;
1343 ap_dev = kzalloc(sizeof(*ap_dev), GFP_KERNEL);
1344 if (!ap_dev)
1345 break;
1346 ap_dev->qid = qid;
1347 ap_dev->queue_depth = queue_depth;
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001348 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001349 spin_lock_init(&ap_dev->lock);
1350 INIT_LIST_HEAD(&ap_dev->pendingq);
1351 INIT_LIST_HEAD(&ap_dev->requestq);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001352 INIT_LIST_HEAD(&ap_dev->list);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001353 setup_timer(&ap_dev->timeout, ap_request_timeout,
1354 (unsigned long) ap_dev);
Holger Dengler6bed05b2011-07-24 10:48:25 +02001355 switch (device_type) {
1356 case 0:
Holger Dengler1e2076f2012-08-28 16:48:29 +02001357 /* device type probing for old cards */
Holger Denglercf2d0072011-05-23 10:24:30 +02001358 if (ap_probe_device_type(ap_dev)) {
1359 kfree(ap_dev);
1360 continue;
1361 }
Holger Dengler6bed05b2011-07-24 10:48:25 +02001362 break;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001363 default:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001364 ap_dev->device_type = device_type;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001365 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001366
Holger Dengler1e2076f2012-08-28 16:48:29 +02001367 rc = ap_query_functions(qid, &device_functions);
1368 if (!rc)
1369 ap_dev->functions = device_functions;
1370 else
1371 ap_dev->functions = 0u;
1372
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001373 ap_dev->device.bus = &ap_bus_type;
1374 ap_dev->device.parent = ap_root_device;
Felix Beckedc44fa2009-09-11 10:28:52 +02001375 if (dev_set_name(&ap_dev->device, "card%02x",
1376 AP_QID_DEVICE(ap_dev->qid))) {
1377 kfree(ap_dev);
1378 continue;
1379 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001380 ap_dev->device.release = ap_device_release;
1381 rc = device_register(&ap_dev->device);
1382 if (rc) {
Sebastian Ottc6304932009-09-11 10:28:38 +02001383 put_device(&ap_dev->device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001384 continue;
1385 }
1386 /* Add device attributes. */
1387 rc = sysfs_create_group(&ap_dev->device.kobj,
1388 &ap_dev_attr_group);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001389 if (!rc) {
1390 spin_lock_bh(&ap_dev->lock);
1391 ap_dev->unregistered = 0;
1392 spin_unlock_bh(&ap_dev->lock);
1393 }
1394 else
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001395 device_unregister(&ap_dev->device);
1396 }
1397}
1398
1399static void
1400ap_config_timeout(unsigned long ptr)
1401{
1402 queue_work(ap_work_queue, &ap_config_work);
1403 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1404 add_timer(&ap_config_timer);
1405}
1406
1407/**
Holger Denglerbc615de2011-11-14 11:19:04 +01001408 * __ap_schedule_poll_timer(): Schedule poll timer.
Felix Beck1749a812008-04-17 07:46:28 +02001409 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001410 * Set up the timer to run the poll tasklet
1411 */
Holger Denglerbc615de2011-11-14 11:19:04 +01001412static inline void __ap_schedule_poll_timer(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001413{
Felix Beck8d406c62009-07-24 12:39:53 +02001414 ktime_t hr_time;
Felix Beck93521312009-12-07 12:52:00 +01001415
1416 spin_lock_bh(&ap_poll_timer_lock);
Holger Denglerbc615de2011-11-14 11:19:04 +01001417 if (hrtimer_is_queued(&ap_poll_timer) || ap_suspend_flag)
Felix Beck93521312009-12-07 12:52:00 +01001418 goto out;
Felix Beck8d406c62009-07-24 12:39:53 +02001419 if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
1420 hr_time = ktime_set(0, poll_timeout);
1421 hrtimer_forward_now(&ap_poll_timer, hr_time);
1422 hrtimer_restart(&ap_poll_timer);
1423 }
Felix Beck93521312009-12-07 12:52:00 +01001424out:
1425 spin_unlock_bh(&ap_poll_timer_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001426}
1427
1428/**
Holger Denglerbc615de2011-11-14 11:19:04 +01001429 * ap_schedule_poll_timer(): Schedule poll timer.
1430 *
1431 * Set up the timer to run the poll tasklet
1432 */
1433static inline void ap_schedule_poll_timer(void)
1434{
1435 if (ap_using_interrupts())
1436 return;
1437 __ap_schedule_poll_timer();
1438}
1439
1440/**
Felix Beck1749a812008-04-17 07:46:28 +02001441 * ap_poll_read(): Receive pending reply messages from an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001442 * @ap_dev: pointer to the AP device
1443 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1444 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001445 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001446 * Returns 0 if the device is still present, -ENODEV if not.
1447 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001448static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001449{
1450 struct ap_queue_status status;
1451 struct ap_message *ap_msg;
1452
1453 if (ap_dev->queue_count <= 0)
1454 return 0;
1455 status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
1456 ap_dev->reply->message, ap_dev->reply->length);
1457 switch (status.response_code) {
1458 case AP_RESPONSE_NORMAL:
1459 atomic_dec(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001460 ap_decrease_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001461 list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
1462 if (ap_msg->psmid != ap_dev->reply->psmid)
1463 continue;
1464 list_del_init(&ap_msg->list);
1465 ap_dev->pendingq_count--;
Holger Dengler54a8f562012-05-16 14:08:22 +02001466 ap_msg->receive(ap_dev, ap_msg, ap_dev->reply);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001467 break;
1468 }
1469 if (ap_dev->queue_count > 0)
1470 *flags |= 1;
1471 break;
1472 case AP_RESPONSE_NO_PENDING_REPLY:
1473 if (status.queue_empty) {
1474 /* The card shouldn't forget requests but who knows. */
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +02001475 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001476 ap_dev->queue_count = 0;
1477 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1478 ap_dev->requestq_count += ap_dev->pendingq_count;
1479 ap_dev->pendingq_count = 0;
1480 } else
1481 *flags |= 2;
1482 break;
1483 default:
1484 return -ENODEV;
1485 }
1486 return 0;
1487}
1488
1489/**
Felix Beck1749a812008-04-17 07:46:28 +02001490 * ap_poll_write(): Send messages from the request queue to an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001491 * @ap_dev: pointer to the AP device
1492 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1493 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001494 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001495 * Returns 0 if the device is still present, -ENODEV if not.
1496 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001497static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001498{
1499 struct ap_queue_status status;
1500 struct ap_message *ap_msg;
1501
1502 if (ap_dev->requestq_count <= 0 ||
1503 ap_dev->queue_count >= ap_dev->queue_depth)
1504 return 0;
1505 /* Start the next request on the queue. */
1506 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
1507 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001508 ap_msg->message, ap_msg->length, ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001509 switch (status.response_code) {
1510 case AP_RESPONSE_NORMAL:
1511 atomic_inc(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001512 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001513 list_move_tail(&ap_msg->list, &ap_dev->pendingq);
1514 ap_dev->requestq_count--;
1515 ap_dev->pendingq_count++;
1516 if (ap_dev->queue_count < ap_dev->queue_depth &&
1517 ap_dev->requestq_count > 0)
1518 *flags |= 1;
1519 *flags |= 2;
1520 break;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001521 case AP_RESPONSE_RESET_IN_PROGRESS:
Holger Denglerbc615de2011-11-14 11:19:04 +01001522 __ap_schedule_poll_timer();
1523 case AP_RESPONSE_Q_FULL:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001524 *flags |= 2;
1525 break;
1526 case AP_RESPONSE_MESSAGE_TOO_BIG:
Felix Becka6a5d732009-12-07 12:51:55 +01001527 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001528 return -EINVAL;
1529 default:
1530 return -ENODEV;
1531 }
1532 return 0;
1533}
1534
1535/**
Felix Beck1749a812008-04-17 07:46:28 +02001536 * ap_poll_queue(): Poll AP device for pending replies and send new messages.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001537 * @ap_dev: pointer to the bus device
1538 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1539 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001540 *
1541 * Poll AP device for pending replies and send new messages. If either
1542 * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001543 * Returns 0.
1544 */
1545static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
1546{
1547 int rc;
1548
1549 rc = ap_poll_read(ap_dev, flags);
1550 if (rc)
1551 return rc;
1552 return ap_poll_write(ap_dev, flags);
1553}
1554
1555/**
Felix Beck1749a812008-04-17 07:46:28 +02001556 * __ap_queue_message(): Queue a message to a device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001557 * @ap_dev: pointer to the AP device
1558 * @ap_msg: the message to be queued
Felix Beck1749a812008-04-17 07:46:28 +02001559 *
1560 * Queue a message to a device. Returns 0 if successful.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001561 */
1562static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1563{
1564 struct ap_queue_status status;
1565
1566 if (list_empty(&ap_dev->requestq) &&
1567 ap_dev->queue_count < ap_dev->queue_depth) {
1568 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001569 ap_msg->message, ap_msg->length,
1570 ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001571 switch (status.response_code) {
1572 case AP_RESPONSE_NORMAL:
1573 list_add_tail(&ap_msg->list, &ap_dev->pendingq);
1574 atomic_inc(&ap_poll_requests);
1575 ap_dev->pendingq_count++;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001576 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001577 ap_dev->total_request_count++;
1578 break;
1579 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001580 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001581 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1582 ap_dev->requestq_count++;
1583 ap_dev->total_request_count++;
1584 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +01001585 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001586 case AP_RESPONSE_MESSAGE_TOO_BIG:
Holger Dengler54a8f562012-05-16 14:08:22 +02001587 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001588 return -EINVAL;
1589 default: /* Device is gone. */
Holger Dengler54a8f562012-05-16 14:08:22 +02001590 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001591 return -ENODEV;
1592 }
1593 } else {
1594 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1595 ap_dev->requestq_count++;
1596 ap_dev->total_request_count++;
1597 return -EBUSY;
1598 }
1599 ap_schedule_poll_timer();
1600 return 0;
1601}
1602
1603void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1604{
1605 unsigned long flags;
1606 int rc;
1607
Holger Dengler54a8f562012-05-16 14:08:22 +02001608 /* For asynchronous message handling a valid receive-callback
1609 * is required. */
1610 BUG_ON(!ap_msg->receive);
1611
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001612 spin_lock_bh(&ap_dev->lock);
1613 if (!ap_dev->unregistered) {
1614 /* Make room on the queue by polling for finished requests. */
1615 rc = ap_poll_queue(ap_dev, &flags);
1616 if (!rc)
1617 rc = __ap_queue_message(ap_dev, ap_msg);
1618 if (!rc)
1619 wake_up(&ap_poll_wait);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001620 if (rc == -ENODEV)
1621 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001622 } else {
Holger Dengler54a8f562012-05-16 14:08:22 +02001623 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001624 rc = -ENODEV;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001625 }
1626 spin_unlock_bh(&ap_dev->lock);
1627 if (rc == -ENODEV)
1628 device_unregister(&ap_dev->device);
1629}
1630EXPORT_SYMBOL(ap_queue_message);
1631
1632/**
Felix Beck1749a812008-04-17 07:46:28 +02001633 * ap_cancel_message(): Cancel a crypto request.
1634 * @ap_dev: The AP device that has the message queued
1635 * @ap_msg: The message that is to be removed
1636 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001637 * Cancel a crypto request. This is done by removing the request
Felix Beck1749a812008-04-17 07:46:28 +02001638 * from the device pending or request queue. Note that the
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001639 * request stays on the AP queue. When it finishes the message
1640 * reply will be discarded because the psmid can't be found.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001641 */
1642void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1643{
1644 struct ap_message *tmp;
1645
1646 spin_lock_bh(&ap_dev->lock);
1647 if (!list_empty(&ap_msg->list)) {
1648 list_for_each_entry(tmp, &ap_dev->pendingq, list)
1649 if (tmp->psmid == ap_msg->psmid) {
1650 ap_dev->pendingq_count--;
1651 goto found;
1652 }
1653 ap_dev->requestq_count--;
1654 found:
1655 list_del_init(&ap_msg->list);
1656 }
1657 spin_unlock_bh(&ap_dev->lock);
1658}
1659EXPORT_SYMBOL(ap_cancel_message);
1660
1661/**
Felix Beck1749a812008-04-17 07:46:28 +02001662 * ap_poll_timeout(): AP receive polling for finished AP requests.
Felix Beckfe137232008-07-14 09:59:08 +02001663 * @unused: Unused pointer.
Felix Beck1749a812008-04-17 07:46:28 +02001664 *
Felix Beckfe137232008-07-14 09:59:08 +02001665 * Schedules the AP tasklet using a high resolution timer.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001666 */
Felix Beckfe137232008-07-14 09:59:08 +02001667static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001668{
1669 tasklet_schedule(&ap_tasklet);
Felix Beckfe137232008-07-14 09:59:08 +02001670 return HRTIMER_NORESTART;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001671}
1672
1673/**
Felix Beck1749a812008-04-17 07:46:28 +02001674 * ap_reset(): Reset a not responding AP device.
1675 * @ap_dev: Pointer to the AP device
1676 *
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001677 * Reset a not responding AP device and move all requests from the
1678 * pending queue to the request queue.
1679 */
1680static void ap_reset(struct ap_device *ap_dev)
1681{
1682 int rc;
1683
1684 ap_dev->reset = AP_RESET_IGNORE;
1685 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
1686 ap_dev->queue_count = 0;
1687 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1688 ap_dev->requestq_count += ap_dev->pendingq_count;
1689 ap_dev->pendingq_count = 0;
1690 rc = ap_init_queue(ap_dev->qid);
1691 if (rc == -ENODEV)
1692 ap_dev->unregistered = 1;
Holger Dengler75464962011-12-01 13:32:23 +01001693 else
1694 __ap_schedule_poll_timer();
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001695}
1696
Christian Maaser43c207e62008-12-25 13:38:42 +01001697static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001698{
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001699 if (!ap_dev->unregistered) {
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001700 if (ap_poll_queue(ap_dev, flags))
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001701 ap_dev->unregistered = 1;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001702 if (ap_dev->reset == AP_RESET_DO)
1703 ap_reset(ap_dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001704 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001705 return 0;
1706}
1707
Felix Beck1749a812008-04-17 07:46:28 +02001708/**
1709 * ap_poll_all(): Poll all AP devices.
1710 * @dummy: Unused variable
1711 *
1712 * Poll all AP devices on the bus in a round robin fashion. Continue
1713 * polling until bit 2^0 of the control flags is not set. If bit 2^1
1714 * of the control flags has been set arm the poll timer.
1715 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001716static void ap_poll_all(unsigned long dummy)
1717{
1718 unsigned long flags;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001719 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001720
Felix Beckcb17a632008-12-25 13:38:41 +01001721 /* Reset the indicator if interrupts are used. Thus new interrupts can
1722 * be received. Doing it in the beginning of the tasklet is therefor
1723 * important that no requests on any AP get lost.
1724 */
1725 if (ap_using_interrupts())
1726 xchg((u8 *)ap_interrupt_indicator, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001727 do {
1728 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001729 spin_lock(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001730 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001731 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001732 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001733 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001734 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001735 spin_unlock(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001736 } while (flags & 1);
1737 if (flags & 2)
1738 ap_schedule_poll_timer();
1739}
1740
1741/**
Felix Beck1749a812008-04-17 07:46:28 +02001742 * ap_poll_thread(): Thread that polls for finished requests.
1743 * @data: Unused pointer
1744 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001745 * AP bus poll thread. The purpose of this thread is to poll for
1746 * finished requests in a loop if there is a "free" cpu - that is
1747 * a cpu that doesn't have anything better to do. The polling stops
1748 * as soon as there is another task or if all messages have been
1749 * delivered.
1750 */
1751static int ap_poll_thread(void *data)
1752{
1753 DECLARE_WAITQUEUE(wait, current);
1754 unsigned long flags;
1755 int requests;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001756 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001757
Christian Borntraegerd83682b2006-10-06 16:38:22 +02001758 set_user_nice(current, 19);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001759 while (1) {
Felix Beck772f5472009-06-22 12:08:16 +02001760 if (ap_suspend_flag)
1761 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001762 if (need_resched()) {
1763 schedule();
1764 continue;
1765 }
1766 add_wait_queue(&ap_poll_wait, &wait);
1767 set_current_state(TASK_INTERRUPTIBLE);
1768 if (kthread_should_stop())
1769 break;
1770 requests = atomic_read(&ap_poll_requests);
1771 if (requests <= 0)
1772 schedule();
1773 set_current_state(TASK_RUNNING);
1774 remove_wait_queue(&ap_poll_wait, &wait);
1775
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001776 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001777 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001778 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001779 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001780 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001781 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001782 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001783 spin_unlock_bh(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001784 }
1785 set_current_state(TASK_RUNNING);
1786 remove_wait_queue(&ap_poll_wait, &wait);
1787 return 0;
1788}
1789
1790static int ap_poll_thread_start(void)
1791{
1792 int rc;
1793
Felix Beck772f5472009-06-22 12:08:16 +02001794 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beckcb17a632008-12-25 13:38:41 +01001795 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001796 mutex_lock(&ap_poll_thread_mutex);
1797 if (!ap_poll_kthread) {
1798 ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
1799 rc = IS_ERR(ap_poll_kthread) ? PTR_ERR(ap_poll_kthread) : 0;
1800 if (rc)
1801 ap_poll_kthread = NULL;
1802 }
1803 else
1804 rc = 0;
1805 mutex_unlock(&ap_poll_thread_mutex);
1806 return rc;
1807}
1808
1809static void ap_poll_thread_stop(void)
1810{
1811 mutex_lock(&ap_poll_thread_mutex);
1812 if (ap_poll_kthread) {
1813 kthread_stop(ap_poll_kthread);
1814 ap_poll_kthread = NULL;
1815 }
1816 mutex_unlock(&ap_poll_thread_mutex);
1817}
1818
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001819/**
Felix Beck1749a812008-04-17 07:46:28 +02001820 * ap_request_timeout(): Handling of request timeouts
1821 * @data: Holds the AP device.
1822 *
1823 * Handles request timeouts.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001824 */
1825static void ap_request_timeout(unsigned long data)
1826{
1827 struct ap_device *ap_dev = (struct ap_device *) data;
1828
Felix Beckcb17a632008-12-25 13:38:41 +01001829 if (ap_dev->reset == AP_RESET_ARMED) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001830 ap_dev->reset = AP_RESET_DO;
Felix Beckcb17a632008-12-25 13:38:41 +01001831
1832 if (ap_using_interrupts())
1833 tasklet_schedule(&ap_tasklet);
1834 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001835}
1836
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001837static void ap_reset_domain(void)
1838{
1839 int i;
1840
Ralph Wuerthner39aa7cf2007-10-12 16:11:29 +02001841 if (ap_domain_index != -1)
1842 for (i = 0; i < AP_DEVICES; i++)
1843 ap_reset_queue(AP_MKQID(i, ap_domain_index));
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001844}
1845
1846static void ap_reset_all(void)
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001847{
1848 int i, j;
1849
1850 for (i = 0; i < AP_DOMAINS; i++)
1851 for (j = 0; j < AP_DEVICES; j++)
1852 ap_reset_queue(AP_MKQID(j, i));
1853}
1854
1855static struct reset_call ap_reset_call = {
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001856 .fn = ap_reset_all,
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001857};
1858
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001859/**
Felix Beck1749a812008-04-17 07:46:28 +02001860 * ap_module_init(): The module initialization code.
1861 *
1862 * Initializes the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001863 */
1864int __init ap_module_init(void)
1865{
1866 int rc, i;
1867
1868 if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001869 pr_warning("%d is not a valid cryptographic domain\n",
1870 ap_domain_index);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001871 return -EINVAL;
1872 }
Felix Beck5314af62009-09-22 22:58:51 +02001873 /* In resume callback we need to know if the user had set the domain.
1874 * If so, we can not just reset it.
1875 */
1876 if (ap_domain_index >= 0)
1877 user_set_domain = 1;
1878
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001879 if (ap_instructions_available() != 0) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001880 pr_warning("The hardware system does not support "
1881 "AP instructions\n");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001882 return -ENODEV;
1883 }
Felix Beckcb17a632008-12-25 13:38:41 +01001884 if (ap_interrupts_available()) {
1885 isc_register(AP_ISC);
1886 ap_interrupt_indicator = s390_register_adapter_interrupt(
1887 &ap_interrupt_handler, NULL, AP_ISC);
1888 if (IS_ERR(ap_interrupt_indicator)) {
1889 ap_interrupt_indicator = NULL;
1890 isc_unregister(AP_ISC);
1891 }
1892 }
1893
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001894 register_reset_call(&ap_reset_call);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001895
1896 /* Create /sys/bus/ap. */
1897 rc = bus_register(&ap_bus_type);
1898 if (rc)
1899 goto out;
1900 for (i = 0; ap_bus_attrs[i]; i++) {
1901 rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]);
1902 if (rc)
1903 goto out_bus;
1904 }
1905
1906 /* Create /sys/devices/ap. */
Mark McLoughlin035da162008-12-15 12:58:29 +00001907 ap_root_device = root_device_register("ap");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001908 rc = IS_ERR(ap_root_device) ? PTR_ERR(ap_root_device) : 0;
1909 if (rc)
1910 goto out_bus;
1911
1912 ap_work_queue = create_singlethread_workqueue("kapwork");
1913 if (!ap_work_queue) {
1914 rc = -ENOMEM;
1915 goto out_root;
1916 }
1917
Holger Dengler75014552012-08-28 16:41:50 +02001918 ap_query_configuration();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001919 if (ap_select_domain() == 0)
1920 ap_scan_bus(NULL);
1921
Felix Beck1749a812008-04-17 07:46:28 +02001922 /* Setup the AP bus rescan timer. */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001923 init_timer(&ap_config_timer);
1924 ap_config_timer.function = ap_config_timeout;
1925 ap_config_timer.data = 0;
1926 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1927 add_timer(&ap_config_timer);
1928
Felix Beckfe137232008-07-14 09:59:08 +02001929 /* Setup the high resultion poll timer.
1930 * If we are running under z/VM adjust polling to z/VM polling rate.
1931 */
1932 if (MACHINE_IS_VM)
1933 poll_timeout = 1500000;
Felix Beck93521312009-12-07 12:52:00 +01001934 spin_lock_init(&ap_poll_timer_lock);
Felix Beckfe137232008-07-14 09:59:08 +02001935 hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1936 ap_poll_timer.function = ap_poll_timeout;
1937
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001938 /* Start the low priority AP bus poll thread. */
1939 if (ap_thread_flag) {
1940 rc = ap_poll_thread_start();
1941 if (rc)
1942 goto out_work;
1943 }
1944
1945 return 0;
1946
1947out_work:
1948 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001949 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001950 destroy_workqueue(ap_work_queue);
1951out_root:
Mark McLoughlin035da162008-12-15 12:58:29 +00001952 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001953out_bus:
1954 while (i--)
1955 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1956 bus_unregister(&ap_bus_type);
1957out:
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001958 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001959 if (ap_using_interrupts()) {
1960 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1961 isc_unregister(AP_ISC);
1962 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001963 return rc;
1964}
1965
1966static int __ap_match_all(struct device *dev, void *data)
1967{
1968 return 1;
1969}
1970
1971/**
Felix Beck1749a812008-04-17 07:46:28 +02001972 * ap_modules_exit(): The module termination code
1973 *
1974 * Terminates the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001975 */
1976void ap_module_exit(void)
1977{
1978 int i;
1979 struct device *dev;
1980
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001981 ap_reset_domain();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001982 ap_poll_thread_stop();
1983 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001984 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001985 destroy_workqueue(ap_work_queue);
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001986 tasklet_kill(&ap_tasklet);
Mark McLoughlin035da162008-12-15 12:58:29 +00001987 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001988 while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
1989 __ap_match_all)))
1990 {
1991 device_unregister(dev);
1992 put_device(dev);
1993 }
1994 for (i = 0; ap_bus_attrs[i]; i++)
1995 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1996 bus_unregister(&ap_bus_type);
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001997 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001998 if (ap_using_interrupts()) {
1999 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
2000 isc_unregister(AP_ISC);
2001 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02002002}
2003
Martin Schwidefsky1534c382006-09-20 15:58:25 +02002004module_init(ap_module_init);
2005module_exit(ap_module_exit);