blob: 7b865a7300e6a7da366762bf7b3882986fc462b3 [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{
957 /* Delete the AP bus rescan timer. */
958 del_timer(&ap_config_timer);
959
960 /* processing a synchonuous bus rescan */
961 ap_scan_bus(NULL);
962
963 /* Setup the AP bus rescan timer again. */
964 ap_config_timer.expires = jiffies + ap_config_time * HZ;
965 add_timer(&ap_config_timer);
966}
967EXPORT_SYMBOL(ap_bus_force_rescan);
968
Felix Beck1749a812008-04-17 07:46:28 +0200969/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200970 * AP bus attributes.
971 */
972static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
973{
974 return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
975}
976
977static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
978
979static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
980{
981 return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
982}
983
Felix Beckcb17a632008-12-25 13:38:41 +0100984static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
985{
986 return snprintf(buf, PAGE_SIZE, "%d\n",
987 ap_using_interrupts() ? 1 : 0);
988}
989
990static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL);
991
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200992static ssize_t ap_config_time_store(struct bus_type *bus,
993 const char *buf, size_t count)
994{
995 int time;
996
997 if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120)
998 return -EINVAL;
999 ap_config_time = time;
1000 if (!timer_pending(&ap_config_timer) ||
1001 !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) {
1002 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1003 add_timer(&ap_config_timer);
1004 }
1005 return count;
1006}
1007
1008static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store);
1009
1010static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf)
1011{
1012 return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
1013}
1014
1015static ssize_t ap_poll_thread_store(struct bus_type *bus,
1016 const char *buf, size_t count)
1017{
1018 int flag, rc;
1019
1020 if (sscanf(buf, "%d\n", &flag) != 1)
1021 return -EINVAL;
1022 if (flag) {
1023 rc = ap_poll_thread_start();
1024 if (rc)
1025 return rc;
1026 }
1027 else
1028 ap_poll_thread_stop();
1029 return count;
1030}
1031
1032static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
1033
Felix Beckfe137232008-07-14 09:59:08 +02001034static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
1035{
1036 return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
1037}
1038
1039static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
1040 size_t count)
1041{
1042 unsigned long long time;
1043 ktime_t hr_time;
1044
1045 /* 120 seconds = maximum poll interval */
Felix Beckcb17a632008-12-25 13:38:41 +01001046 if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 ||
1047 time > 120000000000ULL)
Felix Beckfe137232008-07-14 09:59:08 +02001048 return -EINVAL;
1049 poll_timeout = time;
1050 hr_time = ktime_set(0, poll_timeout);
1051
1052 if (!hrtimer_is_queued(&ap_poll_timer) ||
Arjan van de Ven6c644ea2008-09-01 15:20:30 -07001053 !hrtimer_forward(&ap_poll_timer, hrtimer_get_expires(&ap_poll_timer), hr_time)) {
1054 hrtimer_set_expires(&ap_poll_timer, hr_time);
1055 hrtimer_start_expires(&ap_poll_timer, HRTIMER_MODE_ABS);
Felix Beckfe137232008-07-14 09:59:08 +02001056 }
1057 return count;
1058}
1059
1060static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
1061
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001062static struct bus_attribute *const ap_bus_attrs[] = {
1063 &bus_attr_ap_domain,
1064 &bus_attr_config_time,
1065 &bus_attr_poll_thread,
Felix Beckcb17a632008-12-25 13:38:41 +01001066 &bus_attr_ap_interrupts,
Felix Beckfe137232008-07-14 09:59:08 +02001067 &bus_attr_poll_timeout,
1068 NULL,
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001069};
1070
Holger Dengler75014552012-08-28 16:41:50 +02001071static inline int ap_test_config(unsigned int *field, unsigned int nr)
1072{
1073 if (nr > 0xFFu)
1074 return 0;
1075 return ap_test_bit((field + (nr >> 5)), (nr & 0x1f));
1076}
1077
1078/*
1079 * ap_test_config_card_id(): Test, whether an AP card ID is configured.
1080 * @id AP card ID
1081 *
1082 * Returns 0 if the card is not configured
1083 * 1 if the card is configured or
1084 * if the configuration information is not available
1085 */
1086static inline int ap_test_config_card_id(unsigned int id)
1087{
1088 if (!ap_configuration)
1089 return 1;
1090 return ap_test_config(ap_configuration->apm, id);
1091}
1092
1093/*
1094 * ap_test_config_domain(): Test, whether an AP usage domain is configured.
1095 * @domain AP usage domain ID
1096 *
1097 * Returns 0 if the usage domain is not configured
1098 * 1 if the usage domain is configured or
1099 * if the configuration information is not available
1100 */
1101static inline int ap_test_config_domain(unsigned int domain)
1102{
1103 if (!ap_configuration)
1104 return 1;
1105 return ap_test_config(ap_configuration->aqm, domain);
1106}
1107
1108/**
1109 * ap_query_configuration(): Query AP configuration information.
1110 *
1111 * Query information of installed cards and configured domains from AP.
1112 */
1113static void ap_query_configuration(void)
1114{
1115#ifdef CONFIG_64BIT
1116 if (ap_configuration_available()) {
1117 if (!ap_configuration)
1118 ap_configuration =
1119 kzalloc(sizeof(struct ap_config_info),
1120 GFP_KERNEL);
1121 if (ap_configuration)
1122 __ap_query_configuration(ap_configuration);
1123 } else
1124 ap_configuration = NULL;
1125#else
1126 ap_configuration = NULL;
1127#endif
1128}
1129
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001130/**
Felix Beck1749a812008-04-17 07:46:28 +02001131 * ap_select_domain(): Select an AP domain.
1132 *
1133 * Pick one of the 16 AP domains.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001134 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001135static int ap_select_domain(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001136{
1137 int queue_depth, device_type, count, max_count, best_domain;
Holger Dengler75014552012-08-28 16:41:50 +02001138 ap_qid_t qid;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001139 int rc, i, j;
1140
Felix Beck1749a812008-04-17 07:46:28 +02001141 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001142 * We want to use a single domain. Either the one specified with
1143 * the "domain=" parameter or the domain with the maximum number
1144 * of devices.
1145 */
1146 if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS)
1147 /* Domain has already been selected. */
1148 return 0;
1149 best_domain = -1;
1150 max_count = 0;
1151 for (i = 0; i < AP_DOMAINS; i++) {
Holger Dengler75014552012-08-28 16:41:50 +02001152 if (!ap_test_config_domain(i))
1153 continue;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001154 count = 0;
1155 for (j = 0; j < AP_DEVICES; j++) {
Holger Dengler75014552012-08-28 16:41:50 +02001156 if (!ap_test_config_card_id(j))
1157 continue;
1158 qid = AP_MKQID(j, i);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001159 rc = ap_query_queue(qid, &queue_depth, &device_type);
1160 if (rc)
1161 continue;
1162 count++;
1163 }
1164 if (count > max_count) {
1165 max_count = count;
1166 best_domain = i;
1167 }
1168 }
1169 if (best_domain >= 0){
1170 ap_domain_index = best_domain;
1171 return 0;
1172 }
1173 return -ENODEV;
1174}
1175
1176/**
Felix Beck1749a812008-04-17 07:46:28 +02001177 * ap_probe_device_type(): Find the device type of an AP.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001178 * @ap_dev: pointer to the AP device.
Felix Beck1749a812008-04-17 07:46:28 +02001179 *
1180 * Find the device type if query queue returned a device type of 0.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001181 */
1182static int ap_probe_device_type(struct ap_device *ap_dev)
1183{
1184 static unsigned char msg[] = {
1185 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
1186 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1187 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
1188 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1189 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50,
1190 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,
1191 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00,
1192 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,
1193 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1194 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,
1195 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1196 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,
1197 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00,
1198 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1199 0x00,0x00,0x00,0x00,0xb8,0x05,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,0x00,0x00,0x00,0x00,0x00,0x00,
1205 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1206 0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,
1207 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1208 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
1209 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20,
1210 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,
1211 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22,
1212 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1213 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
1214 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,
1215 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,
1216 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,
1217 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1218 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,
1219 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00,
1220 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,
1221 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01,
1222 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,
1223 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68,
1224 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,
1225 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0,
1226 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,
1227 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04,
1228 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,
1229 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d,
1230 };
1231 struct ap_queue_status status;
1232 unsigned long long psmid;
1233 char *reply;
1234 int rc, i;
1235
1236 reply = (void *) get_zeroed_page(GFP_KERNEL);
1237 if (!reply) {
1238 rc = -ENOMEM;
1239 goto out;
1240 }
1241
1242 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
Felix Becka6a5d732009-12-07 12:51:55 +01001243 msg, sizeof(msg), 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001244 if (status.response_code != AP_RESPONSE_NORMAL) {
1245 rc = -ENODEV;
1246 goto out_free;
1247 }
1248
1249 /* Wait for the test message to complete. */
1250 for (i = 0; i < 6; i++) {
1251 mdelay(300);
1252 status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
1253 if (status.response_code == AP_RESPONSE_NORMAL &&
1254 psmid == 0x0102030405060708ULL)
1255 break;
1256 }
1257 if (i < 6) {
1258 /* Got an answer. */
1259 if (reply[0] == 0x00 && reply[1] == 0x86)
1260 ap_dev->device_type = AP_DEVICE_TYPE_PCICC;
1261 else
1262 ap_dev->device_type = AP_DEVICE_TYPE_PCICA;
1263 rc = 0;
1264 } else
1265 rc = -ENODEV;
1266
1267out_free:
1268 free_page((unsigned long) reply);
1269out:
1270 return rc;
1271}
1272
Felix Beckcb17a632008-12-25 13:38:41 +01001273static void ap_interrupt_handler(void *unused1, void *unused2)
1274{
Holger Dengler62d146f2011-01-05 12:47:38 +01001275 kstat_cpu(smp_processor_id()).irqs[IOINT_APB]++;
Felix Beckcb17a632008-12-25 13:38:41 +01001276 tasklet_schedule(&ap_tasklet);
1277}
1278
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001279/**
Felix Beck1749a812008-04-17 07:46:28 +02001280 * __ap_scan_bus(): Scan the AP bus.
1281 * @dev: Pointer to device
1282 * @data: Pointer to data
1283 *
1284 * Scan the AP bus for new devices.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001285 */
1286static int __ap_scan_bus(struct device *dev, void *data)
1287{
1288 return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data;
1289}
1290
1291static void ap_device_release(struct device *dev)
1292{
1293 struct ap_device *ap_dev = to_ap_dev(dev);
1294
1295 kfree(ap_dev);
1296}
1297
Al Viro4927b3f2006-12-06 19:18:20 +00001298static void ap_scan_bus(struct work_struct *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001299{
1300 struct ap_device *ap_dev;
1301 struct device *dev;
1302 ap_qid_t qid;
1303 int queue_depth, device_type;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001304 unsigned int device_functions;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001305 int rc, i;
1306
Holger Dengler75014552012-08-28 16:41:50 +02001307 ap_query_configuration();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001308 if (ap_select_domain() != 0)
1309 return;
1310 for (i = 0; i < AP_DEVICES; i++) {
1311 qid = AP_MKQID(i, ap_domain_index);
1312 dev = bus_find_device(&ap_bus_type, NULL,
1313 (void *)(unsigned long)qid,
1314 __ap_scan_bus);
Holger Dengler75014552012-08-28 16:41:50 +02001315 if (ap_test_config_card_id(i))
1316 rc = ap_query_queue(qid, &queue_depth, &device_type);
1317 else
1318 rc = -ENODEV;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001319 if (dev) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001320 if (rc == -EBUSY) {
1321 set_current_state(TASK_UNINTERRUPTIBLE);
1322 schedule_timeout(AP_RESET_TIMEOUT);
1323 rc = ap_query_queue(qid, &queue_depth,
1324 &device_type);
1325 }
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001326 ap_dev = to_ap_dev(dev);
1327 spin_lock_bh(&ap_dev->lock);
1328 if (rc || ap_dev->unregistered) {
1329 spin_unlock_bh(&ap_dev->lock);
Felix Beck5314af62009-09-22 22:58:51 +02001330 if (ap_dev->unregistered)
1331 i--;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001332 device_unregister(dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001333 put_device(dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001334 continue;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001335 }
1336 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001337 put_device(dev);
1338 continue;
1339 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001340 if (rc)
1341 continue;
1342 rc = ap_init_queue(qid);
1343 if (rc)
1344 continue;
1345 ap_dev = kzalloc(sizeof(*ap_dev), GFP_KERNEL);
1346 if (!ap_dev)
1347 break;
1348 ap_dev->qid = qid;
1349 ap_dev->queue_depth = queue_depth;
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001350 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001351 spin_lock_init(&ap_dev->lock);
1352 INIT_LIST_HEAD(&ap_dev->pendingq);
1353 INIT_LIST_HEAD(&ap_dev->requestq);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001354 INIT_LIST_HEAD(&ap_dev->list);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001355 setup_timer(&ap_dev->timeout, ap_request_timeout,
1356 (unsigned long) ap_dev);
Holger Dengler6bed05b2011-07-24 10:48:25 +02001357 switch (device_type) {
1358 case 0:
Holger Dengler1e2076f2012-08-28 16:48:29 +02001359 /* device type probing for old cards */
Holger Denglercf2d0072011-05-23 10:24:30 +02001360 if (ap_probe_device_type(ap_dev)) {
1361 kfree(ap_dev);
1362 continue;
1363 }
Holger Dengler6bed05b2011-07-24 10:48:25 +02001364 break;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001365 default:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001366 ap_dev->device_type = device_type;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001367 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001368
Holger Dengler1e2076f2012-08-28 16:48:29 +02001369 rc = ap_query_functions(qid, &device_functions);
1370 if (!rc)
1371 ap_dev->functions = device_functions;
1372 else
1373 ap_dev->functions = 0u;
1374
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001375 ap_dev->device.bus = &ap_bus_type;
1376 ap_dev->device.parent = ap_root_device;
Felix Beckedc44fa2009-09-11 10:28:52 +02001377 if (dev_set_name(&ap_dev->device, "card%02x",
1378 AP_QID_DEVICE(ap_dev->qid))) {
1379 kfree(ap_dev);
1380 continue;
1381 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001382 ap_dev->device.release = ap_device_release;
1383 rc = device_register(&ap_dev->device);
1384 if (rc) {
Sebastian Ottc6304932009-09-11 10:28:38 +02001385 put_device(&ap_dev->device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001386 continue;
1387 }
1388 /* Add device attributes. */
1389 rc = sysfs_create_group(&ap_dev->device.kobj,
1390 &ap_dev_attr_group);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001391 if (!rc) {
1392 spin_lock_bh(&ap_dev->lock);
1393 ap_dev->unregistered = 0;
1394 spin_unlock_bh(&ap_dev->lock);
1395 }
1396 else
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001397 device_unregister(&ap_dev->device);
1398 }
1399}
1400
1401static void
1402ap_config_timeout(unsigned long ptr)
1403{
1404 queue_work(ap_work_queue, &ap_config_work);
1405 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1406 add_timer(&ap_config_timer);
1407}
1408
1409/**
Holger Denglerbc615de2011-11-14 11:19:04 +01001410 * __ap_schedule_poll_timer(): Schedule poll timer.
Felix Beck1749a812008-04-17 07:46:28 +02001411 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001412 * Set up the timer to run the poll tasklet
1413 */
Holger Denglerbc615de2011-11-14 11:19:04 +01001414static inline void __ap_schedule_poll_timer(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001415{
Felix Beck8d406c62009-07-24 12:39:53 +02001416 ktime_t hr_time;
Felix Beck93521312009-12-07 12:52:00 +01001417
1418 spin_lock_bh(&ap_poll_timer_lock);
Holger Denglerbc615de2011-11-14 11:19:04 +01001419 if (hrtimer_is_queued(&ap_poll_timer) || ap_suspend_flag)
Felix Beck93521312009-12-07 12:52:00 +01001420 goto out;
Felix Beck8d406c62009-07-24 12:39:53 +02001421 if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
1422 hr_time = ktime_set(0, poll_timeout);
1423 hrtimer_forward_now(&ap_poll_timer, hr_time);
1424 hrtimer_restart(&ap_poll_timer);
1425 }
Felix Beck93521312009-12-07 12:52:00 +01001426out:
1427 spin_unlock_bh(&ap_poll_timer_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001428}
1429
1430/**
Holger Denglerbc615de2011-11-14 11:19:04 +01001431 * ap_schedule_poll_timer(): Schedule poll timer.
1432 *
1433 * Set up the timer to run the poll tasklet
1434 */
1435static inline void ap_schedule_poll_timer(void)
1436{
1437 if (ap_using_interrupts())
1438 return;
1439 __ap_schedule_poll_timer();
1440}
1441
1442/**
Felix Beck1749a812008-04-17 07:46:28 +02001443 * ap_poll_read(): Receive pending reply messages from an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001444 * @ap_dev: pointer to the AP device
1445 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1446 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001447 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001448 * Returns 0 if the device is still present, -ENODEV if not.
1449 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001450static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001451{
1452 struct ap_queue_status status;
1453 struct ap_message *ap_msg;
1454
1455 if (ap_dev->queue_count <= 0)
1456 return 0;
1457 status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
1458 ap_dev->reply->message, ap_dev->reply->length);
1459 switch (status.response_code) {
1460 case AP_RESPONSE_NORMAL:
1461 atomic_dec(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001462 ap_decrease_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001463 list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
1464 if (ap_msg->psmid != ap_dev->reply->psmid)
1465 continue;
1466 list_del_init(&ap_msg->list);
1467 ap_dev->pendingq_count--;
Holger Dengler54a8f562012-05-16 14:08:22 +02001468 ap_msg->receive(ap_dev, ap_msg, ap_dev->reply);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001469 break;
1470 }
1471 if (ap_dev->queue_count > 0)
1472 *flags |= 1;
1473 break;
1474 case AP_RESPONSE_NO_PENDING_REPLY:
1475 if (status.queue_empty) {
1476 /* The card shouldn't forget requests but who knows. */
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +02001477 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001478 ap_dev->queue_count = 0;
1479 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1480 ap_dev->requestq_count += ap_dev->pendingq_count;
1481 ap_dev->pendingq_count = 0;
1482 } else
1483 *flags |= 2;
1484 break;
1485 default:
1486 return -ENODEV;
1487 }
1488 return 0;
1489}
1490
1491/**
Felix Beck1749a812008-04-17 07:46:28 +02001492 * ap_poll_write(): Send messages from the request queue to an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001493 * @ap_dev: pointer to the AP device
1494 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1495 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001496 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001497 * Returns 0 if the device is still present, -ENODEV if not.
1498 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001499static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001500{
1501 struct ap_queue_status status;
1502 struct ap_message *ap_msg;
1503
1504 if (ap_dev->requestq_count <= 0 ||
1505 ap_dev->queue_count >= ap_dev->queue_depth)
1506 return 0;
1507 /* Start the next request on the queue. */
1508 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
1509 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001510 ap_msg->message, ap_msg->length, ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001511 switch (status.response_code) {
1512 case AP_RESPONSE_NORMAL:
1513 atomic_inc(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001514 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001515 list_move_tail(&ap_msg->list, &ap_dev->pendingq);
1516 ap_dev->requestq_count--;
1517 ap_dev->pendingq_count++;
1518 if (ap_dev->queue_count < ap_dev->queue_depth &&
1519 ap_dev->requestq_count > 0)
1520 *flags |= 1;
1521 *flags |= 2;
1522 break;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001523 case AP_RESPONSE_RESET_IN_PROGRESS:
Holger Denglerbc615de2011-11-14 11:19:04 +01001524 __ap_schedule_poll_timer();
1525 case AP_RESPONSE_Q_FULL:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001526 *flags |= 2;
1527 break;
1528 case AP_RESPONSE_MESSAGE_TOO_BIG:
Felix Becka6a5d732009-12-07 12:51:55 +01001529 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001530 return -EINVAL;
1531 default:
1532 return -ENODEV;
1533 }
1534 return 0;
1535}
1536
1537/**
Felix Beck1749a812008-04-17 07:46:28 +02001538 * ap_poll_queue(): Poll AP device for pending replies and send new messages.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001539 * @ap_dev: pointer to the bus device
1540 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1541 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001542 *
1543 * Poll AP device for pending replies and send new messages. If either
1544 * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001545 * Returns 0.
1546 */
1547static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
1548{
1549 int rc;
1550
1551 rc = ap_poll_read(ap_dev, flags);
1552 if (rc)
1553 return rc;
1554 return ap_poll_write(ap_dev, flags);
1555}
1556
1557/**
Felix Beck1749a812008-04-17 07:46:28 +02001558 * __ap_queue_message(): Queue a message to a device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001559 * @ap_dev: pointer to the AP device
1560 * @ap_msg: the message to be queued
Felix Beck1749a812008-04-17 07:46:28 +02001561 *
1562 * Queue a message to a device. Returns 0 if successful.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001563 */
1564static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1565{
1566 struct ap_queue_status status;
1567
1568 if (list_empty(&ap_dev->requestq) &&
1569 ap_dev->queue_count < ap_dev->queue_depth) {
1570 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001571 ap_msg->message, ap_msg->length,
1572 ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001573 switch (status.response_code) {
1574 case AP_RESPONSE_NORMAL:
1575 list_add_tail(&ap_msg->list, &ap_dev->pendingq);
1576 atomic_inc(&ap_poll_requests);
1577 ap_dev->pendingq_count++;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001578 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001579 ap_dev->total_request_count++;
1580 break;
1581 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001582 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001583 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1584 ap_dev->requestq_count++;
1585 ap_dev->total_request_count++;
1586 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +01001587 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001588 case AP_RESPONSE_MESSAGE_TOO_BIG:
Holger Dengler54a8f562012-05-16 14:08:22 +02001589 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001590 return -EINVAL;
1591 default: /* Device is gone. */
Holger Dengler54a8f562012-05-16 14:08:22 +02001592 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001593 return -ENODEV;
1594 }
1595 } else {
1596 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1597 ap_dev->requestq_count++;
1598 ap_dev->total_request_count++;
1599 return -EBUSY;
1600 }
1601 ap_schedule_poll_timer();
1602 return 0;
1603}
1604
1605void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1606{
1607 unsigned long flags;
1608 int rc;
1609
Holger Dengler54a8f562012-05-16 14:08:22 +02001610 /* For asynchronous message handling a valid receive-callback
1611 * is required. */
1612 BUG_ON(!ap_msg->receive);
1613
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001614 spin_lock_bh(&ap_dev->lock);
1615 if (!ap_dev->unregistered) {
1616 /* Make room on the queue by polling for finished requests. */
1617 rc = ap_poll_queue(ap_dev, &flags);
1618 if (!rc)
1619 rc = __ap_queue_message(ap_dev, ap_msg);
1620 if (!rc)
1621 wake_up(&ap_poll_wait);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001622 if (rc == -ENODEV)
1623 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001624 } else {
Holger Dengler54a8f562012-05-16 14:08:22 +02001625 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001626 rc = -ENODEV;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001627 }
1628 spin_unlock_bh(&ap_dev->lock);
1629 if (rc == -ENODEV)
1630 device_unregister(&ap_dev->device);
1631}
1632EXPORT_SYMBOL(ap_queue_message);
1633
1634/**
Felix Beck1749a812008-04-17 07:46:28 +02001635 * ap_cancel_message(): Cancel a crypto request.
1636 * @ap_dev: The AP device that has the message queued
1637 * @ap_msg: The message that is to be removed
1638 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001639 * Cancel a crypto request. This is done by removing the request
Felix Beck1749a812008-04-17 07:46:28 +02001640 * from the device pending or request queue. Note that the
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001641 * request stays on the AP queue. When it finishes the message
1642 * reply will be discarded because the psmid can't be found.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001643 */
1644void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1645{
1646 struct ap_message *tmp;
1647
1648 spin_lock_bh(&ap_dev->lock);
1649 if (!list_empty(&ap_msg->list)) {
1650 list_for_each_entry(tmp, &ap_dev->pendingq, list)
1651 if (tmp->psmid == ap_msg->psmid) {
1652 ap_dev->pendingq_count--;
1653 goto found;
1654 }
1655 ap_dev->requestq_count--;
1656 found:
1657 list_del_init(&ap_msg->list);
1658 }
1659 spin_unlock_bh(&ap_dev->lock);
1660}
1661EXPORT_SYMBOL(ap_cancel_message);
1662
1663/**
Felix Beck1749a812008-04-17 07:46:28 +02001664 * ap_poll_timeout(): AP receive polling for finished AP requests.
Felix Beckfe137232008-07-14 09:59:08 +02001665 * @unused: Unused pointer.
Felix Beck1749a812008-04-17 07:46:28 +02001666 *
Felix Beckfe137232008-07-14 09:59:08 +02001667 * Schedules the AP tasklet using a high resolution timer.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001668 */
Felix Beckfe137232008-07-14 09:59:08 +02001669static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001670{
1671 tasklet_schedule(&ap_tasklet);
Felix Beckfe137232008-07-14 09:59:08 +02001672 return HRTIMER_NORESTART;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001673}
1674
1675/**
Felix Beck1749a812008-04-17 07:46:28 +02001676 * ap_reset(): Reset a not responding AP device.
1677 * @ap_dev: Pointer to the AP device
1678 *
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001679 * Reset a not responding AP device and move all requests from the
1680 * pending queue to the request queue.
1681 */
1682static void ap_reset(struct ap_device *ap_dev)
1683{
1684 int rc;
1685
1686 ap_dev->reset = AP_RESET_IGNORE;
1687 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
1688 ap_dev->queue_count = 0;
1689 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1690 ap_dev->requestq_count += ap_dev->pendingq_count;
1691 ap_dev->pendingq_count = 0;
1692 rc = ap_init_queue(ap_dev->qid);
1693 if (rc == -ENODEV)
1694 ap_dev->unregistered = 1;
Holger Dengler75464962011-12-01 13:32:23 +01001695 else
1696 __ap_schedule_poll_timer();
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001697}
1698
Christian Maaser43c207e62008-12-25 13:38:42 +01001699static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001700{
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001701 if (!ap_dev->unregistered) {
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001702 if (ap_poll_queue(ap_dev, flags))
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001703 ap_dev->unregistered = 1;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001704 if (ap_dev->reset == AP_RESET_DO)
1705 ap_reset(ap_dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001706 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001707 return 0;
1708}
1709
Felix Beck1749a812008-04-17 07:46:28 +02001710/**
1711 * ap_poll_all(): Poll all AP devices.
1712 * @dummy: Unused variable
1713 *
1714 * Poll all AP devices on the bus in a round robin fashion. Continue
1715 * polling until bit 2^0 of the control flags is not set. If bit 2^1
1716 * of the control flags has been set arm the poll timer.
1717 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001718static void ap_poll_all(unsigned long dummy)
1719{
1720 unsigned long flags;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001721 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001722
Felix Beckcb17a632008-12-25 13:38:41 +01001723 /* Reset the indicator if interrupts are used. Thus new interrupts can
1724 * be received. Doing it in the beginning of the tasklet is therefor
1725 * important that no requests on any AP get lost.
1726 */
1727 if (ap_using_interrupts())
1728 xchg((u8 *)ap_interrupt_indicator, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001729 do {
1730 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001731 spin_lock(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001732 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001733 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001734 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001735 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001736 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001737 spin_unlock(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001738 } while (flags & 1);
1739 if (flags & 2)
1740 ap_schedule_poll_timer();
1741}
1742
1743/**
Felix Beck1749a812008-04-17 07:46:28 +02001744 * ap_poll_thread(): Thread that polls for finished requests.
1745 * @data: Unused pointer
1746 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001747 * AP bus poll thread. The purpose of this thread is to poll for
1748 * finished requests in a loop if there is a "free" cpu - that is
1749 * a cpu that doesn't have anything better to do. The polling stops
1750 * as soon as there is another task or if all messages have been
1751 * delivered.
1752 */
1753static int ap_poll_thread(void *data)
1754{
1755 DECLARE_WAITQUEUE(wait, current);
1756 unsigned long flags;
1757 int requests;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001758 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001759
Christian Borntraegerd83682b2006-10-06 16:38:22 +02001760 set_user_nice(current, 19);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001761 while (1) {
Felix Beck772f5472009-06-22 12:08:16 +02001762 if (ap_suspend_flag)
1763 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001764 if (need_resched()) {
1765 schedule();
1766 continue;
1767 }
1768 add_wait_queue(&ap_poll_wait, &wait);
1769 set_current_state(TASK_INTERRUPTIBLE);
1770 if (kthread_should_stop())
1771 break;
1772 requests = atomic_read(&ap_poll_requests);
1773 if (requests <= 0)
1774 schedule();
1775 set_current_state(TASK_RUNNING);
1776 remove_wait_queue(&ap_poll_wait, &wait);
1777
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001778 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001779 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001780 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001781 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001782 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001783 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001784 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001785 spin_unlock_bh(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001786 }
1787 set_current_state(TASK_RUNNING);
1788 remove_wait_queue(&ap_poll_wait, &wait);
1789 return 0;
1790}
1791
1792static int ap_poll_thread_start(void)
1793{
1794 int rc;
1795
Felix Beck772f5472009-06-22 12:08:16 +02001796 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beckcb17a632008-12-25 13:38:41 +01001797 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001798 mutex_lock(&ap_poll_thread_mutex);
1799 if (!ap_poll_kthread) {
1800 ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
1801 rc = IS_ERR(ap_poll_kthread) ? PTR_ERR(ap_poll_kthread) : 0;
1802 if (rc)
1803 ap_poll_kthread = NULL;
1804 }
1805 else
1806 rc = 0;
1807 mutex_unlock(&ap_poll_thread_mutex);
1808 return rc;
1809}
1810
1811static void ap_poll_thread_stop(void)
1812{
1813 mutex_lock(&ap_poll_thread_mutex);
1814 if (ap_poll_kthread) {
1815 kthread_stop(ap_poll_kthread);
1816 ap_poll_kthread = NULL;
1817 }
1818 mutex_unlock(&ap_poll_thread_mutex);
1819}
1820
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001821/**
Felix Beck1749a812008-04-17 07:46:28 +02001822 * ap_request_timeout(): Handling of request timeouts
1823 * @data: Holds the AP device.
1824 *
1825 * Handles request timeouts.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001826 */
1827static void ap_request_timeout(unsigned long data)
1828{
1829 struct ap_device *ap_dev = (struct ap_device *) data;
1830
Felix Beckcb17a632008-12-25 13:38:41 +01001831 if (ap_dev->reset == AP_RESET_ARMED) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001832 ap_dev->reset = AP_RESET_DO;
Felix Beckcb17a632008-12-25 13:38:41 +01001833
1834 if (ap_using_interrupts())
1835 tasklet_schedule(&ap_tasklet);
1836 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001837}
1838
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001839static void ap_reset_domain(void)
1840{
1841 int i;
1842
Ralph Wuerthner39aa7cf2007-10-12 16:11:29 +02001843 if (ap_domain_index != -1)
1844 for (i = 0; i < AP_DEVICES; i++)
1845 ap_reset_queue(AP_MKQID(i, ap_domain_index));
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001846}
1847
1848static void ap_reset_all(void)
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001849{
1850 int i, j;
1851
1852 for (i = 0; i < AP_DOMAINS; i++)
1853 for (j = 0; j < AP_DEVICES; j++)
1854 ap_reset_queue(AP_MKQID(j, i));
1855}
1856
1857static struct reset_call ap_reset_call = {
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001858 .fn = ap_reset_all,
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001859};
1860
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001861/**
Felix Beck1749a812008-04-17 07:46:28 +02001862 * ap_module_init(): The module initialization code.
1863 *
1864 * Initializes the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001865 */
1866int __init ap_module_init(void)
1867{
1868 int rc, i;
1869
1870 if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001871 pr_warning("%d is not a valid cryptographic domain\n",
1872 ap_domain_index);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001873 return -EINVAL;
1874 }
Felix Beck5314af62009-09-22 22:58:51 +02001875 /* In resume callback we need to know if the user had set the domain.
1876 * If so, we can not just reset it.
1877 */
1878 if (ap_domain_index >= 0)
1879 user_set_domain = 1;
1880
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001881 if (ap_instructions_available() != 0) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001882 pr_warning("The hardware system does not support "
1883 "AP instructions\n");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001884 return -ENODEV;
1885 }
Felix Beckcb17a632008-12-25 13:38:41 +01001886 if (ap_interrupts_available()) {
1887 isc_register(AP_ISC);
1888 ap_interrupt_indicator = s390_register_adapter_interrupt(
1889 &ap_interrupt_handler, NULL, AP_ISC);
1890 if (IS_ERR(ap_interrupt_indicator)) {
1891 ap_interrupt_indicator = NULL;
1892 isc_unregister(AP_ISC);
1893 }
1894 }
1895
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001896 register_reset_call(&ap_reset_call);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001897
1898 /* Create /sys/bus/ap. */
1899 rc = bus_register(&ap_bus_type);
1900 if (rc)
1901 goto out;
1902 for (i = 0; ap_bus_attrs[i]; i++) {
1903 rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]);
1904 if (rc)
1905 goto out_bus;
1906 }
1907
1908 /* Create /sys/devices/ap. */
Mark McLoughlin035da162008-12-15 12:58:29 +00001909 ap_root_device = root_device_register("ap");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001910 rc = IS_ERR(ap_root_device) ? PTR_ERR(ap_root_device) : 0;
1911 if (rc)
1912 goto out_bus;
1913
1914 ap_work_queue = create_singlethread_workqueue("kapwork");
1915 if (!ap_work_queue) {
1916 rc = -ENOMEM;
1917 goto out_root;
1918 }
1919
Holger Dengler75014552012-08-28 16:41:50 +02001920 ap_query_configuration();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001921 if (ap_select_domain() == 0)
1922 ap_scan_bus(NULL);
1923
Felix Beck1749a812008-04-17 07:46:28 +02001924 /* Setup the AP bus rescan timer. */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001925 init_timer(&ap_config_timer);
1926 ap_config_timer.function = ap_config_timeout;
1927 ap_config_timer.data = 0;
1928 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1929 add_timer(&ap_config_timer);
1930
Felix Beckfe137232008-07-14 09:59:08 +02001931 /* Setup the high resultion poll timer.
1932 * If we are running under z/VM adjust polling to z/VM polling rate.
1933 */
1934 if (MACHINE_IS_VM)
1935 poll_timeout = 1500000;
Felix Beck93521312009-12-07 12:52:00 +01001936 spin_lock_init(&ap_poll_timer_lock);
Felix Beckfe137232008-07-14 09:59:08 +02001937 hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1938 ap_poll_timer.function = ap_poll_timeout;
1939
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001940 /* Start the low priority AP bus poll thread. */
1941 if (ap_thread_flag) {
1942 rc = ap_poll_thread_start();
1943 if (rc)
1944 goto out_work;
1945 }
1946
1947 return 0;
1948
1949out_work:
1950 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001951 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001952 destroy_workqueue(ap_work_queue);
1953out_root:
Mark McLoughlin035da162008-12-15 12:58:29 +00001954 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001955out_bus:
1956 while (i--)
1957 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1958 bus_unregister(&ap_bus_type);
1959out:
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001960 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001961 if (ap_using_interrupts()) {
1962 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1963 isc_unregister(AP_ISC);
1964 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001965 return rc;
1966}
1967
1968static int __ap_match_all(struct device *dev, void *data)
1969{
1970 return 1;
1971}
1972
1973/**
Felix Beck1749a812008-04-17 07:46:28 +02001974 * ap_modules_exit(): The module termination code
1975 *
1976 * Terminates the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001977 */
1978void ap_module_exit(void)
1979{
1980 int i;
1981 struct device *dev;
1982
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001983 ap_reset_domain();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001984 ap_poll_thread_stop();
1985 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001986 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001987 destroy_workqueue(ap_work_queue);
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001988 tasklet_kill(&ap_tasklet);
Mark McLoughlin035da162008-12-15 12:58:29 +00001989 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001990 while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
1991 __ap_match_all)))
1992 {
1993 device_unregister(dev);
1994 put_device(dev);
1995 }
1996 for (i = 0; ap_bus_attrs[i]; i++)
1997 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1998 bus_unregister(&ap_bus_type);
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001999 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01002000 if (ap_using_interrupts()) {
2001 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
2002 isc_unregister(AP_ISC);
2003 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02002004}
2005
Martin Schwidefsky1534c382006-09-20 15:58:25 +02002006module_init(ap_module_init);
2007module_exit(ap_module_exit);