blob: 0b116a49ee53a17818f9abf050b5c9691d3497e9 [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 */
Heiko Carstensc80773e2012-09-14 11:21:17 +0200168#ifdef CONFIG_64BIT
Holger Dengler75014552012-08-28 16:41:50 +0200169static int ap_configuration_available(void)
170{
171 return test_facility(2) && test_facility(12);
172}
Heiko Carstensc80773e2012-09-14 11:21:17 +0200173#endif
Holger Dengler75014552012-08-28 16:41:50 +0200174
175/**
Felix Beck1749a812008-04-17 07:46:28 +0200176 * ap_test_queue(): Test adjunct processor queue.
177 * @qid: The AP queue number
178 * @queue_depth: Pointer to queue depth value
179 * @device_type: Pointer to device type value
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200180 *
Felix Beck1749a812008-04-17 07:46:28 +0200181 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200182 */
183static inline struct ap_queue_status
184ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
185{
186 register unsigned long reg0 asm ("0") = qid;
187 register struct ap_queue_status reg1 asm ("1");
188 register unsigned long reg2 asm ("2") = 0UL;
189
190 asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
191 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
192 *device_type = (int) (reg2 >> 24);
193 *queue_depth = (int) (reg2 & 0xff);
194 return reg1;
195}
196
197/**
Felix Beck1749a812008-04-17 07:46:28 +0200198 * ap_reset_queue(): Reset adjunct processor queue.
199 * @qid: The AP queue number
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200200 *
Felix Beck1749a812008-04-17 07:46:28 +0200201 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200202 */
203static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
204{
205 register unsigned long reg0 asm ("0") = qid | 0x01000000UL;
206 register struct ap_queue_status reg1 asm ("1");
207 register unsigned long reg2 asm ("2") = 0UL;
208
209 asm volatile(
210 ".long 0xb2af0000" /* PQAP(RAPQ) */
211 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
212 return reg1;
213}
214
Felix Beckcb17a632008-12-25 13:38:41 +0100215#ifdef CONFIG_64BIT
216/**
217 * ap_queue_interruption_control(): Enable interruption for a specific AP.
218 * @qid: The AP queue number
219 * @ind: The notification indicator byte
220 *
221 * Returns AP queue status.
222 */
223static inline struct ap_queue_status
224ap_queue_interruption_control(ap_qid_t qid, void *ind)
225{
226 register unsigned long reg0 asm ("0") = qid | 0x03000000UL;
227 register unsigned long reg1_in asm ("1") = 0x0000800000000000UL | AP_ISC;
228 register struct ap_queue_status reg1_out asm ("1");
229 register void *reg2 asm ("2") = ind;
230 asm volatile(
Holger Denglera7475af2012-05-16 14:10:26 +0200231 ".long 0xb2af0000" /* PQAP(AQIC) */
Felix Beckcb17a632008-12-25 13:38:41 +0100232 : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
233 :
234 : "cc" );
235 return reg1_out;
236}
237#endif
238
Holger Dengler6bed05b2011-07-24 10:48:25 +0200239#ifdef CONFIG_64BIT
240static inline struct ap_queue_status
241__ap_query_functions(ap_qid_t qid, unsigned int *functions)
Felix Beckb1f933d2011-01-05 12:47:44 +0100242{
243 register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
Holger Dengler6bed05b2011-07-24 10:48:25 +0200244 register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
245 register unsigned long reg2 asm ("2");
Felix Beckb1f933d2011-01-05 12:47:44 +0100246
247 asm volatile(
Holger Denglera7475af2012-05-16 14:10:26 +0200248 ".long 0xb2af0000\n" /* PQAP(TAPQ) */
Holger Dengler6bed05b2011-07-24 10:48:25 +0200249 "0:\n"
250 EX_TABLE(0b, 0b)
251 : "+d" (reg0), "+d" (reg1), "=d" (reg2)
Felix Beckb1f933d2011-01-05 12:47:44 +0100252 :
253 : "cc");
254
Holger Dengler6bed05b2011-07-24 10:48:25 +0200255 *functions = (unsigned int)(reg2 >> 32);
Felix Beckb1f933d2011-01-05 12:47:44 +0100256 return reg1;
257}
Holger Dengler6bed05b2011-07-24 10:48:25 +0200258#endif
259
Holger Dengler75014552012-08-28 16:41:50 +0200260#ifdef CONFIG_64BIT
261static inline int __ap_query_configuration(struct ap_config_info *config)
262{
263 register unsigned long reg0 asm ("0") = 0x04000000UL;
264 register unsigned long reg1 asm ("1") = -EINVAL;
265 register unsigned char *reg2 asm ("2") = (unsigned char *)config;
266
267 asm volatile(
268 ".long 0xb2af0000\n" /* PQAP(QCI) */
269 "0: la %1,0\n"
270 "1:\n"
271 EX_TABLE(0b, 1b)
272 : "+d" (reg0), "+d" (reg1), "+d" (reg2)
273 :
274 : "cc");
275
276 return reg1;
277}
278#endif
279
Holger Dengler6bed05b2011-07-24 10:48:25 +0200280/**
281 * ap_query_functions(): Query supported functions.
282 * @qid: The AP queue number
283 * @functions: Pointer to functions field.
284 *
285 * Returns
286 * 0 on success.
287 * -ENODEV if queue not valid.
288 * -EBUSY if device busy.
289 * -EINVAL if query function is not supported
290 */
291static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
292{
293#ifdef CONFIG_64BIT
294 struct ap_queue_status status;
295 int i;
296 status = __ap_query_functions(qid, functions);
297
298 for (i = 0; i < AP_MAX_RESET; i++) {
299 if (ap_queue_status_invalid_test(&status))
300 return -ENODEV;
301
302 switch (status.response_code) {
303 case AP_RESPONSE_NORMAL:
304 return 0;
305 case AP_RESPONSE_RESET_IN_PROGRESS:
306 case AP_RESPONSE_BUSY:
307 break;
308 case AP_RESPONSE_Q_NOT_AVAIL:
309 case AP_RESPONSE_DECONFIGURED:
310 case AP_RESPONSE_CHECKSTOPPED:
311 case AP_RESPONSE_INVALID_ADDRESS:
312 return -ENODEV;
313 case AP_RESPONSE_OTHERWISE_CHANGED:
314 break;
315 default:
316 break;
317 }
318 if (i < AP_MAX_RESET - 1) {
319 udelay(5);
320 status = __ap_query_functions(qid, functions);
321 }
322 }
323 return -EBUSY;
324#else
325 return -EINVAL;
326#endif
327}
Felix Beckb1f933d2011-01-05 12:47:44 +0100328
329/**
Felix Beckcb17a632008-12-25 13:38:41 +0100330 * ap_queue_enable_interruption(): Enable interruption on an AP.
331 * @qid: The AP queue number
332 * @ind: the notification indicator byte
333 *
334 * Enables interruption on AP queue via ap_queue_interruption_control(). Based
335 * on the return value it waits a while and tests the AP queue if interrupts
336 * have been switched on using ap_test_queue().
337 */
338static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
339{
340#ifdef CONFIG_64BIT
341 struct ap_queue_status status;
342 int t_depth, t_device_type, rc, i;
343
344 rc = -EBUSY;
345 status = ap_queue_interruption_control(qid, ind);
346
347 for (i = 0; i < AP_MAX_RESET; i++) {
348 switch (status.response_code) {
349 case AP_RESPONSE_NORMAL:
350 if (status.int_enabled)
351 return 0;
352 break;
353 case AP_RESPONSE_RESET_IN_PROGRESS:
354 case AP_RESPONSE_BUSY:
Holger Dengler8738e072012-07-02 12:39:59 +0200355 if (i < AP_MAX_RESET - 1) {
356 udelay(5);
357 status = ap_queue_interruption_control(qid,
358 ind);
359 continue;
360 }
Felix Beckcb17a632008-12-25 13:38:41 +0100361 break;
362 case AP_RESPONSE_Q_NOT_AVAIL:
363 case AP_RESPONSE_DECONFIGURED:
364 case AP_RESPONSE_CHECKSTOPPED:
365 case AP_RESPONSE_INVALID_ADDRESS:
366 return -ENODEV;
367 case AP_RESPONSE_OTHERWISE_CHANGED:
368 if (status.int_enabled)
369 return 0;
370 break;
371 default:
372 break;
373 }
374 if (i < AP_MAX_RESET - 1) {
375 udelay(5);
376 status = ap_test_queue(qid, &t_depth, &t_device_type);
377 }
378 }
379 return rc;
380#else
381 return -EINVAL;
382#endif
383}
384
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200385/**
Felix Beck1749a812008-04-17 07:46:28 +0200386 * __ap_send(): Send message to adjunct processor queue.
387 * @qid: The AP queue number
388 * @psmid: The program supplied message identifier
389 * @msg: The message text
390 * @length: The message length
Felix Becka6a5d732009-12-07 12:51:55 +0100391 * @special: Special Bit
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200392 *
Felix Beck1749a812008-04-17 07:46:28 +0200393 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200394 * Condition code 1 on NQAP can't happen because the L bit is 1.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200395 * Condition code 2 on NQAP also means the send is incomplete,
396 * because a segment boundary was reached. The NQAP is repeated.
397 */
398static inline struct ap_queue_status
Felix Becka6a5d732009-12-07 12:51:55 +0100399__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length,
400 unsigned int special)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200401{
402 typedef struct { char _[length]; } msgblock;
403 register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
404 register struct ap_queue_status reg1 asm ("1");
405 register unsigned long reg2 asm ("2") = (unsigned long) msg;
406 register unsigned long reg3 asm ("3") = (unsigned long) length;
407 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
408 register unsigned long reg5 asm ("5") = (unsigned int) psmid;
409
Felix Becka6a5d732009-12-07 12:51:55 +0100410 if (special == 1)
411 reg0 |= 0x400000UL;
412
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200413 asm volatile (
Holger Denglera7475af2012-05-16 14:10:26 +0200414 "0: .long 0xb2ad0042\n" /* NQAP */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200415 " brc 2,0b"
416 : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
417 : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg)
418 : "cc" );
419 return reg1;
420}
421
422int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
423{
424 struct ap_queue_status status;
425
Felix Becka6a5d732009-12-07 12:51:55 +0100426 status = __ap_send(qid, psmid, msg, length, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200427 switch (status.response_code) {
428 case AP_RESPONSE_NORMAL:
429 return 0;
430 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200431 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200432 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +0100433 case AP_RESPONSE_REQ_FAC_NOT_INST:
434 return -EINVAL;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200435 default: /* Device is gone. */
436 return -ENODEV;
437 }
438}
439EXPORT_SYMBOL(ap_send);
440
Felix Beck1749a812008-04-17 07:46:28 +0200441/**
442 * __ap_recv(): Receive message from adjunct processor queue.
443 * @qid: The AP queue number
444 * @psmid: Pointer to program supplied message identifier
445 * @msg: The message text
446 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200447 *
Felix Beck1749a812008-04-17 07:46:28 +0200448 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200449 * Condition code 1 on DQAP means the receive has taken place
450 * but only partially. The response is incomplete, hence the
451 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200452 * Condition code 2 on DQAP also means the receive is incomplete,
453 * this time because a segment boundary was reached. Again, the
454 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200455 * Note that gpr2 is used by the DQAP instruction to keep track of
456 * any 'residual' length, in case the instruction gets interrupted.
457 * Hence it gets zeroed before the instruction.
458 */
459static inline struct ap_queue_status
460__ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
461{
462 typedef struct { char _[length]; } msgblock;
463 register unsigned long reg0 asm("0") = qid | 0x80000000UL;
464 register struct ap_queue_status reg1 asm ("1");
465 register unsigned long reg2 asm("2") = 0UL;
466 register unsigned long reg4 asm("4") = (unsigned long) msg;
467 register unsigned long reg5 asm("5") = (unsigned long) length;
468 register unsigned long reg6 asm("6") = 0UL;
469 register unsigned long reg7 asm("7") = 0UL;
470
471
472 asm volatile(
Holger Denglera7475af2012-05-16 14:10:26 +0200473 "0: .long 0xb2ae0064\n" /* DQAP */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200474 " brc 6,0b\n"
475 : "+d" (reg0), "=d" (reg1), "+d" (reg2),
476 "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
477 "=m" (*(msgblock *) msg) : : "cc" );
478 *psmid = (((unsigned long long) reg6) << 32) + reg7;
479 return reg1;
480}
481
482int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
483{
484 struct ap_queue_status status;
485
486 status = __ap_recv(qid, psmid, msg, length);
487 switch (status.response_code) {
488 case AP_RESPONSE_NORMAL:
489 return 0;
490 case AP_RESPONSE_NO_PENDING_REPLY:
491 if (status.queue_empty)
492 return -ENOENT;
493 return -EBUSY;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200494 case AP_RESPONSE_RESET_IN_PROGRESS:
495 return -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200496 default:
497 return -ENODEV;
498 }
499}
500EXPORT_SYMBOL(ap_recv);
501
502/**
Felix Beck1749a812008-04-17 07:46:28 +0200503 * ap_query_queue(): Check if an AP queue is available.
504 * @qid: The AP queue number
505 * @queue_depth: Pointer to queue depth value
506 * @device_type: Pointer to device type value
507 *
508 * The test is repeated for AP_MAX_RESET times.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200509 */
510static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
511{
512 struct ap_queue_status status;
513 int t_depth, t_device_type, rc, i;
514
515 rc = -EBUSY;
516 for (i = 0; i < AP_MAX_RESET; i++) {
517 status = ap_test_queue(qid, &t_depth, &t_device_type);
518 switch (status.response_code) {
519 case AP_RESPONSE_NORMAL:
520 *queue_depth = t_depth + 1;
521 *device_type = t_device_type;
522 rc = 0;
523 break;
524 case AP_RESPONSE_Q_NOT_AVAIL:
525 rc = -ENODEV;
526 break;
527 case AP_RESPONSE_RESET_IN_PROGRESS:
528 break;
529 case AP_RESPONSE_DECONFIGURED:
530 rc = -ENODEV;
531 break;
532 case AP_RESPONSE_CHECKSTOPPED:
533 rc = -ENODEV;
534 break;
Felix Beckcb17a632008-12-25 13:38:41 +0100535 case AP_RESPONSE_INVALID_ADDRESS:
536 rc = -ENODEV;
537 break;
538 case AP_RESPONSE_OTHERWISE_CHANGED:
539 break;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200540 case AP_RESPONSE_BUSY:
541 break;
542 default:
543 BUG();
544 }
545 if (rc != -EBUSY)
546 break;
547 if (i < AP_MAX_RESET - 1)
548 udelay(5);
549 }
550 return rc;
551}
552
553/**
Felix Beck1749a812008-04-17 07:46:28 +0200554 * ap_init_queue(): Reset an AP queue.
555 * @qid: The AP queue number
556 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200557 * Reset an AP queue and wait for it to become available again.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200558 */
559static int ap_init_queue(ap_qid_t qid)
560{
561 struct ap_queue_status status;
562 int rc, dummy, i;
563
564 rc = -ENODEV;
565 status = ap_reset_queue(qid);
566 for (i = 0; i < AP_MAX_RESET; i++) {
567 switch (status.response_code) {
568 case AP_RESPONSE_NORMAL:
569 if (status.queue_empty)
570 rc = 0;
571 break;
572 case AP_RESPONSE_Q_NOT_AVAIL:
573 case AP_RESPONSE_DECONFIGURED:
574 case AP_RESPONSE_CHECKSTOPPED:
575 i = AP_MAX_RESET; /* return with -ENODEV */
576 break;
577 case AP_RESPONSE_RESET_IN_PROGRESS:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200578 rc = -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200579 case AP_RESPONSE_BUSY:
580 default:
581 break;
582 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200583 if (rc != -ENODEV && rc != -EBUSY)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200584 break;
585 if (i < AP_MAX_RESET - 1) {
586 udelay(5);
587 status = ap_test_queue(qid, &dummy, &dummy);
588 }
589 }
Felix Beckcb17a632008-12-25 13:38:41 +0100590 if (rc == 0 && ap_using_interrupts()) {
591 rc = ap_queue_enable_interruption(qid, ap_interrupt_indicator);
592 /* If interruption mode is supported by the machine,
593 * but an AP can not be enabled for interruption then
594 * the AP will be discarded. */
595 if (rc)
596 pr_err("Registering adapter interrupts for "
597 "AP %d failed\n", AP_QID_DEVICE(qid));
598 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200599 return rc;
600}
601
602/**
Felix Beck1749a812008-04-17 07:46:28 +0200603 * ap_increase_queue_count(): Arm request timeout.
604 * @ap_dev: Pointer to an AP device.
605 *
606 * Arm request timeout if an AP device was idle and a new request is submitted.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200607 */
608static void ap_increase_queue_count(struct ap_device *ap_dev)
609{
610 int timeout = ap_dev->drv->request_timeout;
611
612 ap_dev->queue_count++;
613 if (ap_dev->queue_count == 1) {
614 mod_timer(&ap_dev->timeout, jiffies + timeout);
615 ap_dev->reset = AP_RESET_ARMED;
616 }
617}
618
619/**
Felix Beck1749a812008-04-17 07:46:28 +0200620 * ap_decrease_queue_count(): Decrease queue count.
621 * @ap_dev: Pointer to an AP device.
622 *
623 * If AP device is still alive, re-schedule request timeout if there are still
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200624 * pending requests.
625 */
626static void ap_decrease_queue_count(struct ap_device *ap_dev)
627{
628 int timeout = ap_dev->drv->request_timeout;
629
630 ap_dev->queue_count--;
631 if (ap_dev->queue_count > 0)
632 mod_timer(&ap_dev->timeout, jiffies + timeout);
633 else
Felix Beck1749a812008-04-17 07:46:28 +0200634 /*
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200635 * The timeout timer should to be disabled now - since
636 * del_timer_sync() is very expensive, we just tell via the
637 * reset flag to ignore the pending timeout timer.
638 */
639 ap_dev->reset = AP_RESET_IGNORE;
640}
641
Felix Beck1749a812008-04-17 07:46:28 +0200642/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200643 * AP device related attributes.
644 */
645static ssize_t ap_hwtype_show(struct device *dev,
646 struct device_attribute *attr, char *buf)
647{
648 struct ap_device *ap_dev = to_ap_dev(dev);
649 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type);
650}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200651
Christian Maaser43c207e62008-12-25 13:38:42 +0100652static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200653static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr,
654 char *buf)
655{
656 struct ap_device *ap_dev = to_ap_dev(dev);
657 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth);
658}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200659
Christian Maaser43c207e62008-12-25 13:38:42 +0100660static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200661static ssize_t ap_request_count_show(struct device *dev,
662 struct device_attribute *attr,
663 char *buf)
664{
665 struct ap_device *ap_dev = to_ap_dev(dev);
666 int rc;
667
668 spin_lock_bh(&ap_dev->lock);
669 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->total_request_count);
670 spin_unlock_bh(&ap_dev->lock);
671 return rc;
672}
673
674static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL);
675
Holger Denglerb26bd942012-08-28 16:43:48 +0200676static ssize_t ap_requestq_count_show(struct device *dev,
677 struct device_attribute *attr, char *buf)
678{
679 struct ap_device *ap_dev = to_ap_dev(dev);
680 int rc;
681
682 spin_lock_bh(&ap_dev->lock);
683 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->requestq_count);
684 spin_unlock_bh(&ap_dev->lock);
685 return rc;
686}
687
688static DEVICE_ATTR(requestq_count, 0444, ap_requestq_count_show, NULL);
689
690static ssize_t ap_pendingq_count_show(struct device *dev,
691 struct device_attribute *attr, char *buf)
692{
693 struct ap_device *ap_dev = to_ap_dev(dev);
694 int rc;
695
696 spin_lock_bh(&ap_dev->lock);
697 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->pendingq_count);
698 spin_unlock_bh(&ap_dev->lock);
699 return rc;
700}
701
702static DEVICE_ATTR(pendingq_count, 0444, ap_pendingq_count_show, NULL);
703
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200704static ssize_t ap_modalias_show(struct device *dev,
705 struct device_attribute *attr, char *buf)
706{
707 return sprintf(buf, "ap:t%02X", to_ap_dev(dev)->device_type);
708}
709
710static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL);
711
Holger Denglerb26bd942012-08-28 16:43:48 +0200712static ssize_t ap_functions_show(struct device *dev,
713 struct device_attribute *attr, char *buf)
714{
715 struct ap_device *ap_dev = to_ap_dev(dev);
716 return snprintf(buf, PAGE_SIZE, "0x%08X\n", ap_dev->functions);
717}
718
719static DEVICE_ATTR(ap_functions, 0444, ap_functions_show, NULL);
720
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200721static struct attribute *ap_dev_attrs[] = {
722 &dev_attr_hwtype.attr,
723 &dev_attr_depth.attr,
724 &dev_attr_request_count.attr,
Holger Denglerb26bd942012-08-28 16:43:48 +0200725 &dev_attr_requestq_count.attr,
726 &dev_attr_pendingq_count.attr,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200727 &dev_attr_modalias.attr,
Holger Denglerb26bd942012-08-28 16:43:48 +0200728 &dev_attr_ap_functions.attr,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200729 NULL
730};
731static struct attribute_group ap_dev_attr_group = {
732 .attrs = ap_dev_attrs
733};
734
735/**
Felix Beck1749a812008-04-17 07:46:28 +0200736 * ap_bus_match()
737 * @dev: Pointer to device
738 * @drv: Pointer to device_driver
739 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200740 * AP bus driver registration/unregistration.
741 */
742static int ap_bus_match(struct device *dev, struct device_driver *drv)
743{
744 struct ap_device *ap_dev = to_ap_dev(dev);
745 struct ap_driver *ap_drv = to_ap_drv(drv);
746 struct ap_device_id *id;
747
Felix Beck1749a812008-04-17 07:46:28 +0200748 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200749 * Compare device type of the device with the list of
750 * supported types of the device_driver.
751 */
752 for (id = ap_drv->ids; id->match_flags; id++) {
753 if ((id->match_flags & AP_DEVICE_ID_MATCH_DEVICE_TYPE) &&
754 (id->dev_type != ap_dev->device_type))
755 continue;
756 return 1;
757 }
758 return 0;
759}
760
761/**
Felix Beck1749a812008-04-17 07:46:28 +0200762 * ap_uevent(): Uevent function for AP devices.
763 * @dev: Pointer to device
764 * @env: Pointer to kobj_uevent_env
765 *
766 * It sets up a single environment variable DEV_TYPE which contains the
767 * hardware device type.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200768 */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200769static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200770{
771 struct ap_device *ap_dev = to_ap_dev(dev);
Kay Sievers7eff2e72007-08-14 15:15:12 +0200772 int retval = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200773
774 if (!ap_dev)
775 return -ENODEV;
776
777 /* Set up DEV_TYPE environment variable. */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200778 retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700779 if (retval)
780 return retval;
781
Cornelia Huck66a4263b2006-12-04 15:40:10 +0100782 /* Add MODALIAS= */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200783 retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700784
Eric Rannaudbf624562007-03-30 22:23:12 -0700785 return retval;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200786}
787
Felix Beck772f5472009-06-22 12:08:16 +0200788static int ap_bus_suspend(struct device *dev, pm_message_t state)
789{
790 struct ap_device *ap_dev = to_ap_dev(dev);
791 unsigned long flags;
792
793 if (!ap_suspend_flag) {
794 ap_suspend_flag = 1;
795
796 /* Disable scanning for devices, thus we do not want to scan
797 * for them after removing.
798 */
799 del_timer_sync(&ap_config_timer);
800 if (ap_work_queue != NULL) {
801 destroy_workqueue(ap_work_queue);
802 ap_work_queue = NULL;
803 }
Felix Beck5314af62009-09-22 22:58:51 +0200804
Felix Beck772f5472009-06-22 12:08:16 +0200805 tasklet_disable(&ap_tasklet);
806 }
807 /* Poll on the device until all requests are finished. */
808 do {
809 flags = 0;
Felix Beck95f15562009-09-11 10:28:51 +0200810 spin_lock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200811 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +0200812 spin_unlock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200813 } while ((flags & 1) || (flags & 2));
814
Felix Beck5314af62009-09-22 22:58:51 +0200815 spin_lock_bh(&ap_dev->lock);
816 ap_dev->unregistered = 1;
817 spin_unlock_bh(&ap_dev->lock);
818
Felix Beck772f5472009-06-22 12:08:16 +0200819 return 0;
820}
821
822static int ap_bus_resume(struct device *dev)
823{
824 int rc = 0;
825 struct ap_device *ap_dev = to_ap_dev(dev);
826
827 if (ap_suspend_flag) {
828 ap_suspend_flag = 0;
829 if (!ap_interrupts_available())
830 ap_interrupt_indicator = NULL;
Holger Dengler75014552012-08-28 16:41:50 +0200831 ap_query_configuration();
Felix Beck5314af62009-09-22 22:58:51 +0200832 if (!user_set_domain) {
833 ap_domain_index = -1;
834 ap_select_domain();
835 }
Felix Beck772f5472009-06-22 12:08:16 +0200836 init_timer(&ap_config_timer);
837 ap_config_timer.function = ap_config_timeout;
838 ap_config_timer.data = 0;
839 ap_config_timer.expires = jiffies + ap_config_time * HZ;
840 add_timer(&ap_config_timer);
841 ap_work_queue = create_singlethread_workqueue("kapwork");
842 if (!ap_work_queue)
843 return -ENOMEM;
844 tasklet_enable(&ap_tasklet);
845 if (!ap_using_interrupts())
846 ap_schedule_poll_timer();
847 else
848 tasklet_schedule(&ap_tasklet);
849 if (ap_thread_flag)
850 rc = ap_poll_thread_start();
Felix Beck772f5472009-06-22 12:08:16 +0200851 }
Felix Beck5314af62009-09-22 22:58:51 +0200852 if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) {
853 spin_lock_bh(&ap_dev->lock);
854 ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid),
855 ap_domain_index);
856 spin_unlock_bh(&ap_dev->lock);
857 }
858 queue_work(ap_work_queue, &ap_config_work);
Felix Beck772f5472009-06-22 12:08:16 +0200859
860 return rc;
861}
862
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200863static struct bus_type ap_bus_type = {
864 .name = "ap",
865 .match = &ap_bus_match,
866 .uevent = &ap_uevent,
Felix Beck772f5472009-06-22 12:08:16 +0200867 .suspend = ap_bus_suspend,
868 .resume = ap_bus_resume
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200869};
870
871static int ap_device_probe(struct device *dev)
872{
873 struct ap_device *ap_dev = to_ap_dev(dev);
874 struct ap_driver *ap_drv = to_ap_drv(dev->driver);
875 int rc;
876
877 ap_dev->drv = ap_drv;
878 rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100879 if (!rc) {
Christian Maaser43c207e62008-12-25 13:38:42 +0100880 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100881 list_add(&ap_dev->list, &ap_device_list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100882 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100883 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200884 return rc;
885}
886
887/**
Felix Beck1749a812008-04-17 07:46:28 +0200888 * __ap_flush_queue(): Flush requests.
889 * @ap_dev: Pointer to the AP device
890 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200891 * Flush all requests from the request/pending queue of an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200892 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100893static void __ap_flush_queue(struct ap_device *ap_dev)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200894{
895 struct ap_message *ap_msg, *next;
896
897 list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
898 list_del_init(&ap_msg->list);
899 ap_dev->pendingq_count--;
Holger Dengler54a8f562012-05-16 14:08:22 +0200900 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200901 }
902 list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
903 list_del_init(&ap_msg->list);
904 ap_dev->requestq_count--;
Holger Dengler54a8f562012-05-16 14:08:22 +0200905 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200906 }
907}
908
909void ap_flush_queue(struct ap_device *ap_dev)
910{
911 spin_lock_bh(&ap_dev->lock);
912 __ap_flush_queue(ap_dev);
913 spin_unlock_bh(&ap_dev->lock);
914}
915EXPORT_SYMBOL(ap_flush_queue);
916
917static int ap_device_remove(struct device *dev)
918{
919 struct ap_device *ap_dev = to_ap_dev(dev);
920 struct ap_driver *ap_drv = ap_dev->drv;
921
Ralph Wuerthner4e562962006-10-04 20:02:05 +0200922 ap_flush_queue(ap_dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200923 del_timer_sync(&ap_dev->timeout);
Christian Maaser43c207e62008-12-25 13:38:42 +0100924 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +0100925 list_del_init(&ap_dev->list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100926 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100927 if (ap_drv->remove)
928 ap_drv->remove(ap_dev);
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +0200929 spin_lock_bh(&ap_dev->lock);
930 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
931 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200932 return 0;
933}
934
935int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
936 char *name)
937{
938 struct device_driver *drv = &ap_drv->driver;
939
940 drv->bus = &ap_bus_type;
941 drv->probe = ap_device_probe;
942 drv->remove = ap_device_remove;
943 drv->owner = owner;
944 drv->name = name;
945 return driver_register(drv);
946}
947EXPORT_SYMBOL(ap_driver_register);
948
949void ap_driver_unregister(struct ap_driver *ap_drv)
950{
951 driver_unregister(&ap_drv->driver);
952}
953EXPORT_SYMBOL(ap_driver_unregister);
954
Holger Denglerdabecb22012-09-10 21:34:26 +0200955void ap_bus_force_rescan(void)
956{
Ingo Tuchscherer56bbe682013-04-12 17:52:08 +0200957 /* reconfigure the AP bus rescan timer. */
958 mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ);
959 /* processing a asynchronous bus rescan */
960 queue_work(ap_work_queue, &ap_config_work);
961 flush_work(&ap_config_work);
Holger Denglerdabecb22012-09-10 21:34:26 +0200962}
963EXPORT_SYMBOL(ap_bus_force_rescan);
964
Felix Beck1749a812008-04-17 07:46:28 +0200965/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200966 * AP bus attributes.
967 */
968static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
969{
970 return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
971}
972
973static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
974
975static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
976{
977 return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
978}
979
Felix Beckcb17a632008-12-25 13:38:41 +0100980static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
981{
982 return snprintf(buf, PAGE_SIZE, "%d\n",
983 ap_using_interrupts() ? 1 : 0);
984}
985
986static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL);
987
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200988static ssize_t ap_config_time_store(struct bus_type *bus,
989 const char *buf, size_t count)
990{
991 int time;
992
993 if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120)
994 return -EINVAL;
995 ap_config_time = time;
996 if (!timer_pending(&ap_config_timer) ||
997 !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) {
998 ap_config_timer.expires = jiffies + ap_config_time * HZ;
999 add_timer(&ap_config_timer);
1000 }
1001 return count;
1002}
1003
1004static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store);
1005
1006static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf)
1007{
1008 return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
1009}
1010
1011static ssize_t ap_poll_thread_store(struct bus_type *bus,
1012 const char *buf, size_t count)
1013{
1014 int flag, rc;
1015
1016 if (sscanf(buf, "%d\n", &flag) != 1)
1017 return -EINVAL;
1018 if (flag) {
1019 rc = ap_poll_thread_start();
1020 if (rc)
1021 return rc;
1022 }
1023 else
1024 ap_poll_thread_stop();
1025 return count;
1026}
1027
1028static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
1029
Felix Beckfe137232008-07-14 09:59:08 +02001030static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
1031{
1032 return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
1033}
1034
1035static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
1036 size_t count)
1037{
1038 unsigned long long time;
1039 ktime_t hr_time;
1040
1041 /* 120 seconds = maximum poll interval */
Felix Beckcb17a632008-12-25 13:38:41 +01001042 if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 ||
1043 time > 120000000000ULL)
Felix Beckfe137232008-07-14 09:59:08 +02001044 return -EINVAL;
1045 poll_timeout = time;
1046 hr_time = ktime_set(0, poll_timeout);
1047
1048 if (!hrtimer_is_queued(&ap_poll_timer) ||
Arjan van de Ven6c644ea2008-09-01 15:20:30 -07001049 !hrtimer_forward(&ap_poll_timer, hrtimer_get_expires(&ap_poll_timer), hr_time)) {
1050 hrtimer_set_expires(&ap_poll_timer, hr_time);
1051 hrtimer_start_expires(&ap_poll_timer, HRTIMER_MODE_ABS);
Felix Beckfe137232008-07-14 09:59:08 +02001052 }
1053 return count;
1054}
1055
1056static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
1057
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001058static struct bus_attribute *const ap_bus_attrs[] = {
1059 &bus_attr_ap_domain,
1060 &bus_attr_config_time,
1061 &bus_attr_poll_thread,
Felix Beckcb17a632008-12-25 13:38:41 +01001062 &bus_attr_ap_interrupts,
Felix Beckfe137232008-07-14 09:59:08 +02001063 &bus_attr_poll_timeout,
1064 NULL,
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001065};
1066
Holger Dengler75014552012-08-28 16:41:50 +02001067static inline int ap_test_config(unsigned int *field, unsigned int nr)
1068{
1069 if (nr > 0xFFu)
1070 return 0;
1071 return ap_test_bit((field + (nr >> 5)), (nr & 0x1f));
1072}
1073
1074/*
1075 * ap_test_config_card_id(): Test, whether an AP card ID is configured.
1076 * @id AP card ID
1077 *
1078 * Returns 0 if the card is not configured
1079 * 1 if the card is configured or
1080 * if the configuration information is not available
1081 */
1082static inline int ap_test_config_card_id(unsigned int id)
1083{
1084 if (!ap_configuration)
1085 return 1;
1086 return ap_test_config(ap_configuration->apm, id);
1087}
1088
1089/*
1090 * ap_test_config_domain(): Test, whether an AP usage domain is configured.
1091 * @domain AP usage domain ID
1092 *
1093 * Returns 0 if the usage domain is not configured
1094 * 1 if the usage domain is configured or
1095 * if the configuration information is not available
1096 */
1097static inline int ap_test_config_domain(unsigned int domain)
1098{
1099 if (!ap_configuration)
1100 return 1;
1101 return ap_test_config(ap_configuration->aqm, domain);
1102}
1103
1104/**
1105 * ap_query_configuration(): Query AP configuration information.
1106 *
1107 * Query information of installed cards and configured domains from AP.
1108 */
1109static void ap_query_configuration(void)
1110{
1111#ifdef CONFIG_64BIT
1112 if (ap_configuration_available()) {
1113 if (!ap_configuration)
1114 ap_configuration =
1115 kzalloc(sizeof(struct ap_config_info),
1116 GFP_KERNEL);
1117 if (ap_configuration)
1118 __ap_query_configuration(ap_configuration);
1119 } else
1120 ap_configuration = NULL;
1121#else
1122 ap_configuration = NULL;
1123#endif
1124}
1125
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001126/**
Felix Beck1749a812008-04-17 07:46:28 +02001127 * ap_select_domain(): Select an AP domain.
1128 *
1129 * Pick one of the 16 AP domains.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001130 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001131static int ap_select_domain(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001132{
1133 int queue_depth, device_type, count, max_count, best_domain;
Holger Dengler75014552012-08-28 16:41:50 +02001134 ap_qid_t qid;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001135 int rc, i, j;
1136
Felix Beck1749a812008-04-17 07:46:28 +02001137 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001138 * We want to use a single domain. Either the one specified with
1139 * the "domain=" parameter or the domain with the maximum number
1140 * of devices.
1141 */
1142 if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS)
1143 /* Domain has already been selected. */
1144 return 0;
1145 best_domain = -1;
1146 max_count = 0;
1147 for (i = 0; i < AP_DOMAINS; i++) {
Holger Dengler75014552012-08-28 16:41:50 +02001148 if (!ap_test_config_domain(i))
1149 continue;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001150 count = 0;
1151 for (j = 0; j < AP_DEVICES; j++) {
Holger Dengler75014552012-08-28 16:41:50 +02001152 if (!ap_test_config_card_id(j))
1153 continue;
1154 qid = AP_MKQID(j, i);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001155 rc = ap_query_queue(qid, &queue_depth, &device_type);
1156 if (rc)
1157 continue;
1158 count++;
1159 }
1160 if (count > max_count) {
1161 max_count = count;
1162 best_domain = i;
1163 }
1164 }
1165 if (best_domain >= 0){
1166 ap_domain_index = best_domain;
1167 return 0;
1168 }
1169 return -ENODEV;
1170}
1171
1172/**
Felix Beck1749a812008-04-17 07:46:28 +02001173 * ap_probe_device_type(): Find the device type of an AP.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001174 * @ap_dev: pointer to the AP device.
Felix Beck1749a812008-04-17 07:46:28 +02001175 *
1176 * Find the device type if query queue returned a device type of 0.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001177 */
1178static int ap_probe_device_type(struct ap_device *ap_dev)
1179{
1180 static unsigned char msg[] = {
1181 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
1182 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1183 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
1184 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1185 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50,
1186 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,
1187 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00,
1188 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,
1189 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1190 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,
1191 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1192 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,
1193 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00,
1194 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1195 0x00,0x00,0x00,0x00,0xb8,0x05,0x00,0x00,
1196 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1197 0x00,0x00,0x00,0x00,0x00,0x00,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,0x0a,0x00,0x00,0x00,0x00,0x00,
1203 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1204 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
1205 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20,
1206 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,
1207 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22,
1208 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1209 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
1210 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,
1211 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,
1212 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,
1213 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1214 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,
1215 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00,
1216 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,
1217 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01,
1218 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,
1219 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68,
1220 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,
1221 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0,
1222 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,
1223 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04,
1224 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,
1225 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d,
1226 };
1227 struct ap_queue_status status;
1228 unsigned long long psmid;
1229 char *reply;
1230 int rc, i;
1231
1232 reply = (void *) get_zeroed_page(GFP_KERNEL);
1233 if (!reply) {
1234 rc = -ENOMEM;
1235 goto out;
1236 }
1237
1238 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
Felix Becka6a5d732009-12-07 12:51:55 +01001239 msg, sizeof(msg), 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001240 if (status.response_code != AP_RESPONSE_NORMAL) {
1241 rc = -ENODEV;
1242 goto out_free;
1243 }
1244
1245 /* Wait for the test message to complete. */
1246 for (i = 0; i < 6; i++) {
1247 mdelay(300);
1248 status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
1249 if (status.response_code == AP_RESPONSE_NORMAL &&
1250 psmid == 0x0102030405060708ULL)
1251 break;
1252 }
1253 if (i < 6) {
1254 /* Got an answer. */
1255 if (reply[0] == 0x00 && reply[1] == 0x86)
1256 ap_dev->device_type = AP_DEVICE_TYPE_PCICC;
1257 else
1258 ap_dev->device_type = AP_DEVICE_TYPE_PCICA;
1259 rc = 0;
1260 } else
1261 rc = -ENODEV;
1262
1263out_free:
1264 free_page((unsigned long) reply);
1265out:
1266 return rc;
1267}
1268
Felix Beckcb17a632008-12-25 13:38:41 +01001269static void ap_interrupt_handler(void *unused1, void *unused2)
1270{
Heiko Carstens420f42e2013-01-02 15:18:18 +01001271 inc_irq_stat(IRQIO_APB);
Felix Beckcb17a632008-12-25 13:38:41 +01001272 tasklet_schedule(&ap_tasklet);
1273}
1274
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001275/**
Felix Beck1749a812008-04-17 07:46:28 +02001276 * __ap_scan_bus(): Scan the AP bus.
1277 * @dev: Pointer to device
1278 * @data: Pointer to data
1279 *
1280 * Scan the AP bus for new devices.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001281 */
1282static int __ap_scan_bus(struct device *dev, void *data)
1283{
1284 return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data;
1285}
1286
1287static void ap_device_release(struct device *dev)
1288{
1289 struct ap_device *ap_dev = to_ap_dev(dev);
1290
1291 kfree(ap_dev);
1292}
1293
Al Viro4927b3f2006-12-06 19:18:20 +00001294static void ap_scan_bus(struct work_struct *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001295{
1296 struct ap_device *ap_dev;
1297 struct device *dev;
1298 ap_qid_t qid;
1299 int queue_depth, device_type;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001300 unsigned int device_functions;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001301 int rc, i;
1302
Holger Dengler75014552012-08-28 16:41:50 +02001303 ap_query_configuration();
Ingo Tuchscherer56bbe682013-04-12 17:52:08 +02001304 if (ap_select_domain() != 0) {
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001305 return;
Ingo Tuchscherer56bbe682013-04-12 17:52:08 +02001306 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001307 for (i = 0; i < AP_DEVICES; i++) {
1308 qid = AP_MKQID(i, ap_domain_index);
1309 dev = bus_find_device(&ap_bus_type, NULL,
1310 (void *)(unsigned long)qid,
1311 __ap_scan_bus);
Holger Dengler75014552012-08-28 16:41:50 +02001312 if (ap_test_config_card_id(i))
1313 rc = ap_query_queue(qid, &queue_depth, &device_type);
1314 else
1315 rc = -ENODEV;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001316 if (dev) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001317 if (rc == -EBUSY) {
1318 set_current_state(TASK_UNINTERRUPTIBLE);
1319 schedule_timeout(AP_RESET_TIMEOUT);
1320 rc = ap_query_queue(qid, &queue_depth,
1321 &device_type);
1322 }
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001323 ap_dev = to_ap_dev(dev);
1324 spin_lock_bh(&ap_dev->lock);
1325 if (rc || ap_dev->unregistered) {
1326 spin_unlock_bh(&ap_dev->lock);
Felix Beck5314af62009-09-22 22:58:51 +02001327 if (ap_dev->unregistered)
1328 i--;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001329 device_unregister(dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001330 put_device(dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001331 continue;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001332 }
1333 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001334 put_device(dev);
1335 continue;
1336 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001337 if (rc)
1338 continue;
1339 rc = ap_init_queue(qid);
1340 if (rc)
1341 continue;
1342 ap_dev = kzalloc(sizeof(*ap_dev), GFP_KERNEL);
1343 if (!ap_dev)
1344 break;
1345 ap_dev->qid = qid;
1346 ap_dev->queue_depth = queue_depth;
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001347 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001348 spin_lock_init(&ap_dev->lock);
1349 INIT_LIST_HEAD(&ap_dev->pendingq);
1350 INIT_LIST_HEAD(&ap_dev->requestq);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001351 INIT_LIST_HEAD(&ap_dev->list);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001352 setup_timer(&ap_dev->timeout, ap_request_timeout,
1353 (unsigned long) ap_dev);
Holger Dengler6bed05b2011-07-24 10:48:25 +02001354 switch (device_type) {
1355 case 0:
Holger Dengler1e2076f2012-08-28 16:48:29 +02001356 /* device type probing for old cards */
Holger Denglercf2d0072011-05-23 10:24:30 +02001357 if (ap_probe_device_type(ap_dev)) {
1358 kfree(ap_dev);
1359 continue;
1360 }
Holger Dengler6bed05b2011-07-24 10:48:25 +02001361 break;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001362 default:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001363 ap_dev->device_type = device_type;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001364 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001365
Holger Dengler1e2076f2012-08-28 16:48:29 +02001366 rc = ap_query_functions(qid, &device_functions);
1367 if (!rc)
1368 ap_dev->functions = device_functions;
1369 else
1370 ap_dev->functions = 0u;
1371
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001372 ap_dev->device.bus = &ap_bus_type;
1373 ap_dev->device.parent = ap_root_device;
Felix Beckedc44fa2009-09-11 10:28:52 +02001374 if (dev_set_name(&ap_dev->device, "card%02x",
1375 AP_QID_DEVICE(ap_dev->qid))) {
1376 kfree(ap_dev);
1377 continue;
1378 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001379 ap_dev->device.release = ap_device_release;
1380 rc = device_register(&ap_dev->device);
1381 if (rc) {
Sebastian Ottc6304932009-09-11 10:28:38 +02001382 put_device(&ap_dev->device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001383 continue;
1384 }
1385 /* Add device attributes. */
1386 rc = sysfs_create_group(&ap_dev->device.kobj,
1387 &ap_dev_attr_group);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001388 if (!rc) {
1389 spin_lock_bh(&ap_dev->lock);
1390 ap_dev->unregistered = 0;
1391 spin_unlock_bh(&ap_dev->lock);
1392 }
1393 else
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001394 device_unregister(&ap_dev->device);
1395 }
1396}
1397
1398static void
1399ap_config_timeout(unsigned long ptr)
1400{
1401 queue_work(ap_work_queue, &ap_config_work);
1402 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1403 add_timer(&ap_config_timer);
1404}
1405
1406/**
Holger Denglerbc615de2011-11-14 11:19:04 +01001407 * __ap_schedule_poll_timer(): Schedule poll timer.
Felix Beck1749a812008-04-17 07:46:28 +02001408 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001409 * Set up the timer to run the poll tasklet
1410 */
Holger Denglerbc615de2011-11-14 11:19:04 +01001411static inline void __ap_schedule_poll_timer(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001412{
Felix Beck8d406c62009-07-24 12:39:53 +02001413 ktime_t hr_time;
Felix Beck93521312009-12-07 12:52:00 +01001414
1415 spin_lock_bh(&ap_poll_timer_lock);
Holger Denglerbc615de2011-11-14 11:19:04 +01001416 if (hrtimer_is_queued(&ap_poll_timer) || ap_suspend_flag)
Felix Beck93521312009-12-07 12:52:00 +01001417 goto out;
Felix Beck8d406c62009-07-24 12:39:53 +02001418 if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
1419 hr_time = ktime_set(0, poll_timeout);
1420 hrtimer_forward_now(&ap_poll_timer, hr_time);
1421 hrtimer_restart(&ap_poll_timer);
1422 }
Felix Beck93521312009-12-07 12:52:00 +01001423out:
1424 spin_unlock_bh(&ap_poll_timer_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001425}
1426
1427/**
Holger Denglerbc615de2011-11-14 11:19:04 +01001428 * ap_schedule_poll_timer(): Schedule poll timer.
1429 *
1430 * Set up the timer to run the poll tasklet
1431 */
1432static inline void ap_schedule_poll_timer(void)
1433{
1434 if (ap_using_interrupts())
1435 return;
1436 __ap_schedule_poll_timer();
1437}
1438
1439/**
Felix Beck1749a812008-04-17 07:46:28 +02001440 * ap_poll_read(): Receive pending reply messages from an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001441 * @ap_dev: pointer to the AP device
1442 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1443 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001444 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001445 * Returns 0 if the device is still present, -ENODEV if not.
1446 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001447static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001448{
1449 struct ap_queue_status status;
1450 struct ap_message *ap_msg;
1451
1452 if (ap_dev->queue_count <= 0)
1453 return 0;
1454 status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
1455 ap_dev->reply->message, ap_dev->reply->length);
1456 switch (status.response_code) {
1457 case AP_RESPONSE_NORMAL:
1458 atomic_dec(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001459 ap_decrease_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001460 list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
1461 if (ap_msg->psmid != ap_dev->reply->psmid)
1462 continue;
1463 list_del_init(&ap_msg->list);
1464 ap_dev->pendingq_count--;
Holger Dengler54a8f562012-05-16 14:08:22 +02001465 ap_msg->receive(ap_dev, ap_msg, ap_dev->reply);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001466 break;
1467 }
1468 if (ap_dev->queue_count > 0)
1469 *flags |= 1;
1470 break;
1471 case AP_RESPONSE_NO_PENDING_REPLY:
1472 if (status.queue_empty) {
1473 /* The card shouldn't forget requests but who knows. */
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +02001474 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001475 ap_dev->queue_count = 0;
1476 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1477 ap_dev->requestq_count += ap_dev->pendingq_count;
1478 ap_dev->pendingq_count = 0;
1479 } else
1480 *flags |= 2;
1481 break;
1482 default:
1483 return -ENODEV;
1484 }
1485 return 0;
1486}
1487
1488/**
Felix Beck1749a812008-04-17 07:46:28 +02001489 * ap_poll_write(): Send messages from the request queue to an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001490 * @ap_dev: pointer to the AP device
1491 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1492 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001493 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001494 * Returns 0 if the device is still present, -ENODEV if not.
1495 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001496static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001497{
1498 struct ap_queue_status status;
1499 struct ap_message *ap_msg;
1500
1501 if (ap_dev->requestq_count <= 0 ||
1502 ap_dev->queue_count >= ap_dev->queue_depth)
1503 return 0;
1504 /* Start the next request on the queue. */
1505 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
1506 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001507 ap_msg->message, ap_msg->length, ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001508 switch (status.response_code) {
1509 case AP_RESPONSE_NORMAL:
1510 atomic_inc(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001511 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001512 list_move_tail(&ap_msg->list, &ap_dev->pendingq);
1513 ap_dev->requestq_count--;
1514 ap_dev->pendingq_count++;
1515 if (ap_dev->queue_count < ap_dev->queue_depth &&
1516 ap_dev->requestq_count > 0)
1517 *flags |= 1;
1518 *flags |= 2;
1519 break;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001520 case AP_RESPONSE_RESET_IN_PROGRESS:
Holger Denglerbc615de2011-11-14 11:19:04 +01001521 __ap_schedule_poll_timer();
1522 case AP_RESPONSE_Q_FULL:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001523 *flags |= 2;
1524 break;
1525 case AP_RESPONSE_MESSAGE_TOO_BIG:
Felix Becka6a5d732009-12-07 12:51:55 +01001526 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001527 return -EINVAL;
1528 default:
1529 return -ENODEV;
1530 }
1531 return 0;
1532}
1533
1534/**
Felix Beck1749a812008-04-17 07:46:28 +02001535 * ap_poll_queue(): Poll AP device for pending replies and send new messages.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001536 * @ap_dev: pointer to the bus device
1537 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1538 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001539 *
1540 * Poll AP device for pending replies and send new messages. If either
1541 * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001542 * Returns 0.
1543 */
1544static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
1545{
1546 int rc;
1547
1548 rc = ap_poll_read(ap_dev, flags);
1549 if (rc)
1550 return rc;
1551 return ap_poll_write(ap_dev, flags);
1552}
1553
1554/**
Felix Beck1749a812008-04-17 07:46:28 +02001555 * __ap_queue_message(): Queue a message to a device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001556 * @ap_dev: pointer to the AP device
1557 * @ap_msg: the message to be queued
Felix Beck1749a812008-04-17 07:46:28 +02001558 *
1559 * Queue a message to a device. Returns 0 if successful.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001560 */
1561static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1562{
1563 struct ap_queue_status status;
1564
1565 if (list_empty(&ap_dev->requestq) &&
1566 ap_dev->queue_count < ap_dev->queue_depth) {
1567 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001568 ap_msg->message, ap_msg->length,
1569 ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001570 switch (status.response_code) {
1571 case AP_RESPONSE_NORMAL:
1572 list_add_tail(&ap_msg->list, &ap_dev->pendingq);
1573 atomic_inc(&ap_poll_requests);
1574 ap_dev->pendingq_count++;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001575 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001576 ap_dev->total_request_count++;
1577 break;
1578 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001579 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001580 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1581 ap_dev->requestq_count++;
1582 ap_dev->total_request_count++;
1583 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +01001584 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001585 case AP_RESPONSE_MESSAGE_TOO_BIG:
Holger Dengler54a8f562012-05-16 14:08:22 +02001586 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001587 return -EINVAL;
1588 default: /* Device is gone. */
Holger Dengler54a8f562012-05-16 14:08:22 +02001589 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001590 return -ENODEV;
1591 }
1592 } else {
1593 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1594 ap_dev->requestq_count++;
1595 ap_dev->total_request_count++;
1596 return -EBUSY;
1597 }
1598 ap_schedule_poll_timer();
1599 return 0;
1600}
1601
1602void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1603{
1604 unsigned long flags;
1605 int rc;
1606
Holger Dengler54a8f562012-05-16 14:08:22 +02001607 /* For asynchronous message handling a valid receive-callback
1608 * is required. */
1609 BUG_ON(!ap_msg->receive);
1610
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001611 spin_lock_bh(&ap_dev->lock);
1612 if (!ap_dev->unregistered) {
1613 /* Make room on the queue by polling for finished requests. */
1614 rc = ap_poll_queue(ap_dev, &flags);
1615 if (!rc)
1616 rc = __ap_queue_message(ap_dev, ap_msg);
1617 if (!rc)
1618 wake_up(&ap_poll_wait);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001619 if (rc == -ENODEV)
1620 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001621 } else {
Holger Dengler54a8f562012-05-16 14:08:22 +02001622 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001623 rc = -ENODEV;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001624 }
1625 spin_unlock_bh(&ap_dev->lock);
1626 if (rc == -ENODEV)
1627 device_unregister(&ap_dev->device);
1628}
1629EXPORT_SYMBOL(ap_queue_message);
1630
1631/**
Felix Beck1749a812008-04-17 07:46:28 +02001632 * ap_cancel_message(): Cancel a crypto request.
1633 * @ap_dev: The AP device that has the message queued
1634 * @ap_msg: The message that is to be removed
1635 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001636 * Cancel a crypto request. This is done by removing the request
Felix Beck1749a812008-04-17 07:46:28 +02001637 * from the device pending or request queue. Note that the
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001638 * request stays on the AP queue. When it finishes the message
1639 * reply will be discarded because the psmid can't be found.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001640 */
1641void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1642{
1643 struct ap_message *tmp;
1644
1645 spin_lock_bh(&ap_dev->lock);
1646 if (!list_empty(&ap_msg->list)) {
1647 list_for_each_entry(tmp, &ap_dev->pendingq, list)
1648 if (tmp->psmid == ap_msg->psmid) {
1649 ap_dev->pendingq_count--;
1650 goto found;
1651 }
1652 ap_dev->requestq_count--;
1653 found:
1654 list_del_init(&ap_msg->list);
1655 }
1656 spin_unlock_bh(&ap_dev->lock);
1657}
1658EXPORT_SYMBOL(ap_cancel_message);
1659
1660/**
Felix Beck1749a812008-04-17 07:46:28 +02001661 * ap_poll_timeout(): AP receive polling for finished AP requests.
Felix Beckfe137232008-07-14 09:59:08 +02001662 * @unused: Unused pointer.
Felix Beck1749a812008-04-17 07:46:28 +02001663 *
Felix Beckfe137232008-07-14 09:59:08 +02001664 * Schedules the AP tasklet using a high resolution timer.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001665 */
Felix Beckfe137232008-07-14 09:59:08 +02001666static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001667{
1668 tasklet_schedule(&ap_tasklet);
Felix Beckfe137232008-07-14 09:59:08 +02001669 return HRTIMER_NORESTART;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001670}
1671
1672/**
Felix Beck1749a812008-04-17 07:46:28 +02001673 * ap_reset(): Reset a not responding AP device.
1674 * @ap_dev: Pointer to the AP device
1675 *
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001676 * Reset a not responding AP device and move all requests from the
1677 * pending queue to the request queue.
1678 */
1679static void ap_reset(struct ap_device *ap_dev)
1680{
1681 int rc;
1682
1683 ap_dev->reset = AP_RESET_IGNORE;
1684 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
1685 ap_dev->queue_count = 0;
1686 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1687 ap_dev->requestq_count += ap_dev->pendingq_count;
1688 ap_dev->pendingq_count = 0;
1689 rc = ap_init_queue(ap_dev->qid);
1690 if (rc == -ENODEV)
1691 ap_dev->unregistered = 1;
Holger Dengler75464962011-12-01 13:32:23 +01001692 else
1693 __ap_schedule_poll_timer();
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001694}
1695
Christian Maaser43c207e62008-12-25 13:38:42 +01001696static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001697{
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001698 if (!ap_dev->unregistered) {
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001699 if (ap_poll_queue(ap_dev, flags))
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001700 ap_dev->unregistered = 1;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001701 if (ap_dev->reset == AP_RESET_DO)
1702 ap_reset(ap_dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001703 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001704 return 0;
1705}
1706
Felix Beck1749a812008-04-17 07:46:28 +02001707/**
1708 * ap_poll_all(): Poll all AP devices.
1709 * @dummy: Unused variable
1710 *
1711 * Poll all AP devices on the bus in a round robin fashion. Continue
1712 * polling until bit 2^0 of the control flags is not set. If bit 2^1
1713 * of the control flags has been set arm the poll timer.
1714 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001715static void ap_poll_all(unsigned long dummy)
1716{
1717 unsigned long flags;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001718 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001719
Felix Beckcb17a632008-12-25 13:38:41 +01001720 /* Reset the indicator if interrupts are used. Thus new interrupts can
1721 * be received. Doing it in the beginning of the tasklet is therefor
1722 * important that no requests on any AP get lost.
1723 */
1724 if (ap_using_interrupts())
1725 xchg((u8 *)ap_interrupt_indicator, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001726 do {
1727 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001728 spin_lock(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001729 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001730 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001731 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001732 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001733 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001734 spin_unlock(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001735 } while (flags & 1);
1736 if (flags & 2)
1737 ap_schedule_poll_timer();
1738}
1739
1740/**
Felix Beck1749a812008-04-17 07:46:28 +02001741 * ap_poll_thread(): Thread that polls for finished requests.
1742 * @data: Unused pointer
1743 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001744 * AP bus poll thread. The purpose of this thread is to poll for
1745 * finished requests in a loop if there is a "free" cpu - that is
1746 * a cpu that doesn't have anything better to do. The polling stops
1747 * as soon as there is another task or if all messages have been
1748 * delivered.
1749 */
1750static int ap_poll_thread(void *data)
1751{
1752 DECLARE_WAITQUEUE(wait, current);
1753 unsigned long flags;
1754 int requests;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001755 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001756
Christian Borntraegerd83682b2006-10-06 16:38:22 +02001757 set_user_nice(current, 19);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001758 while (1) {
Felix Beck772f5472009-06-22 12:08:16 +02001759 if (ap_suspend_flag)
1760 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001761 if (need_resched()) {
1762 schedule();
1763 continue;
1764 }
1765 add_wait_queue(&ap_poll_wait, &wait);
1766 set_current_state(TASK_INTERRUPTIBLE);
1767 if (kthread_should_stop())
1768 break;
1769 requests = atomic_read(&ap_poll_requests);
1770 if (requests <= 0)
1771 schedule();
1772 set_current_state(TASK_RUNNING);
1773 remove_wait_queue(&ap_poll_wait, &wait);
1774
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001775 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001776 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001777 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001778 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001779 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001780 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001781 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001782 spin_unlock_bh(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001783 }
1784 set_current_state(TASK_RUNNING);
1785 remove_wait_queue(&ap_poll_wait, &wait);
1786 return 0;
1787}
1788
1789static int ap_poll_thread_start(void)
1790{
1791 int rc;
1792
Felix Beck772f5472009-06-22 12:08:16 +02001793 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beckcb17a632008-12-25 13:38:41 +01001794 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001795 mutex_lock(&ap_poll_thread_mutex);
1796 if (!ap_poll_kthread) {
1797 ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
Thomas Meyerba8da212013-06-01 11:51:13 +02001798 rc = PTR_RET(ap_poll_kthread);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001799 if (rc)
1800 ap_poll_kthread = NULL;
1801 }
1802 else
1803 rc = 0;
1804 mutex_unlock(&ap_poll_thread_mutex);
1805 return rc;
1806}
1807
1808static void ap_poll_thread_stop(void)
1809{
1810 mutex_lock(&ap_poll_thread_mutex);
1811 if (ap_poll_kthread) {
1812 kthread_stop(ap_poll_kthread);
1813 ap_poll_kthread = NULL;
1814 }
1815 mutex_unlock(&ap_poll_thread_mutex);
1816}
1817
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001818/**
Felix Beck1749a812008-04-17 07:46:28 +02001819 * ap_request_timeout(): Handling of request timeouts
1820 * @data: Holds the AP device.
1821 *
1822 * Handles request timeouts.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001823 */
1824static void ap_request_timeout(unsigned long data)
1825{
1826 struct ap_device *ap_dev = (struct ap_device *) data;
1827
Felix Beckcb17a632008-12-25 13:38:41 +01001828 if (ap_dev->reset == AP_RESET_ARMED) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001829 ap_dev->reset = AP_RESET_DO;
Felix Beckcb17a632008-12-25 13:38:41 +01001830
1831 if (ap_using_interrupts())
1832 tasklet_schedule(&ap_tasklet);
1833 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001834}
1835
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001836static void ap_reset_domain(void)
1837{
1838 int i;
1839
Ralph Wuerthner39aa7cf2007-10-12 16:11:29 +02001840 if (ap_domain_index != -1)
1841 for (i = 0; i < AP_DEVICES; i++)
1842 ap_reset_queue(AP_MKQID(i, ap_domain_index));
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001843}
1844
1845static void ap_reset_all(void)
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001846{
1847 int i, j;
1848
1849 for (i = 0; i < AP_DOMAINS; i++)
1850 for (j = 0; j < AP_DEVICES; j++)
1851 ap_reset_queue(AP_MKQID(j, i));
1852}
1853
1854static struct reset_call ap_reset_call = {
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001855 .fn = ap_reset_all,
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001856};
1857
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001858/**
Felix Beck1749a812008-04-17 07:46:28 +02001859 * ap_module_init(): The module initialization code.
1860 *
1861 * Initializes the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001862 */
1863int __init ap_module_init(void)
1864{
1865 int rc, i;
1866
1867 if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001868 pr_warning("%d is not a valid cryptographic domain\n",
1869 ap_domain_index);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001870 return -EINVAL;
1871 }
Felix Beck5314af62009-09-22 22:58:51 +02001872 /* In resume callback we need to know if the user had set the domain.
1873 * If so, we can not just reset it.
1874 */
1875 if (ap_domain_index >= 0)
1876 user_set_domain = 1;
1877
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001878 if (ap_instructions_available() != 0) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001879 pr_warning("The hardware system does not support "
1880 "AP instructions\n");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001881 return -ENODEV;
1882 }
Felix Beckcb17a632008-12-25 13:38:41 +01001883 if (ap_interrupts_available()) {
1884 isc_register(AP_ISC);
1885 ap_interrupt_indicator = s390_register_adapter_interrupt(
1886 &ap_interrupt_handler, NULL, AP_ISC);
1887 if (IS_ERR(ap_interrupt_indicator)) {
1888 ap_interrupt_indicator = NULL;
1889 isc_unregister(AP_ISC);
1890 }
1891 }
1892
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001893 register_reset_call(&ap_reset_call);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001894
1895 /* Create /sys/bus/ap. */
1896 rc = bus_register(&ap_bus_type);
1897 if (rc)
1898 goto out;
1899 for (i = 0; ap_bus_attrs[i]; i++) {
1900 rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]);
1901 if (rc)
1902 goto out_bus;
1903 }
1904
1905 /* Create /sys/devices/ap. */
Mark McLoughlin035da162008-12-15 12:58:29 +00001906 ap_root_device = root_device_register("ap");
Thomas Meyerba8da212013-06-01 11:51:13 +02001907 rc = PTR_RET(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001908 if (rc)
1909 goto out_bus;
1910
1911 ap_work_queue = create_singlethread_workqueue("kapwork");
1912 if (!ap_work_queue) {
1913 rc = -ENOMEM;
1914 goto out_root;
1915 }
1916
Holger Dengler75014552012-08-28 16:41:50 +02001917 ap_query_configuration();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001918 if (ap_select_domain() == 0)
1919 ap_scan_bus(NULL);
1920
Felix Beck1749a812008-04-17 07:46:28 +02001921 /* Setup the AP bus rescan timer. */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001922 init_timer(&ap_config_timer);
1923 ap_config_timer.function = ap_config_timeout;
1924 ap_config_timer.data = 0;
1925 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1926 add_timer(&ap_config_timer);
1927
Felix Beckfe137232008-07-14 09:59:08 +02001928 /* Setup the high resultion poll timer.
1929 * If we are running under z/VM adjust polling to z/VM polling rate.
1930 */
1931 if (MACHINE_IS_VM)
1932 poll_timeout = 1500000;
Felix Beck93521312009-12-07 12:52:00 +01001933 spin_lock_init(&ap_poll_timer_lock);
Felix Beckfe137232008-07-14 09:59:08 +02001934 hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1935 ap_poll_timer.function = ap_poll_timeout;
1936
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001937 /* Start the low priority AP bus poll thread. */
1938 if (ap_thread_flag) {
1939 rc = ap_poll_thread_start();
1940 if (rc)
1941 goto out_work;
1942 }
1943
1944 return 0;
1945
1946out_work:
1947 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001948 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001949 destroy_workqueue(ap_work_queue);
1950out_root:
Mark McLoughlin035da162008-12-15 12:58:29 +00001951 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001952out_bus:
1953 while (i--)
1954 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1955 bus_unregister(&ap_bus_type);
1956out:
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001957 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001958 if (ap_using_interrupts()) {
1959 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1960 isc_unregister(AP_ISC);
1961 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001962 return rc;
1963}
1964
1965static int __ap_match_all(struct device *dev, void *data)
1966{
1967 return 1;
1968}
1969
1970/**
Felix Beck1749a812008-04-17 07:46:28 +02001971 * ap_modules_exit(): The module termination code
1972 *
1973 * Terminates the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001974 */
1975void ap_module_exit(void)
1976{
1977 int i;
1978 struct device *dev;
1979
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001980 ap_reset_domain();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001981 ap_poll_thread_stop();
1982 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001983 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001984 destroy_workqueue(ap_work_queue);
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001985 tasklet_kill(&ap_tasklet);
Mark McLoughlin035da162008-12-15 12:58:29 +00001986 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001987 while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
1988 __ap_match_all)))
1989 {
1990 device_unregister(dev);
1991 put_device(dev);
1992 }
1993 for (i = 0; ap_bus_attrs[i]; i++)
1994 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1995 bus_unregister(&ap_bus_type);
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001996 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001997 if (ap_using_interrupts()) {
1998 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1999 isc_unregister(AP_ISC);
2000 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02002001}
2002
Martin Schwidefsky1534c382006-09-20 15:58:25 +02002003module_init(ap_module_init);
2004module_exit(ap_module_exit);