blob: f446a7705c3b9fb9a2856b8fc79b82730e897f2b [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);
Martin Schwidefskyf4eae942013-06-24 10:30:41 +020061static void ap_interrupt_handler(struct airq_struct *airq);
Felix Beck772f5472009-06-22 12:08:16 +020062static 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 Beckfe137232008-07-14 09:59:08 +0200109static struct hrtimer ap_poll_timer;
110/* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
111 * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
112static unsigned long long poll_timeout = 250000;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200113
Felix Beck772f5472009-06-22 12:08:16 +0200114/* Suspend flag */
115static int ap_suspend_flag;
Felix Beck5314af62009-09-22 22:58:51 +0200116/* Flag to check if domain was set through module parameter domain=. This is
117 * important when supsend and resume is done in a z/VM environment where the
118 * domain might change. */
119static int user_set_domain = 0;
Felix Beck772f5472009-06-22 12:08:16 +0200120static struct bus_type ap_bus_type;
121
Martin Schwidefskyf4eae942013-06-24 10:30:41 +0200122/* Adapter interrupt definitions */
123static int ap_airq_flag;
124
125static struct airq_struct ap_airq = {
126 .handler = ap_interrupt_handler,
127 .isc = AP_ISC,
128};
129
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200130/**
Felix Beckcb17a632008-12-25 13:38:41 +0100131 * ap_using_interrupts() - Returns non-zero if interrupt support is
132 * available.
133 */
134static inline int ap_using_interrupts(void)
135{
Martin Schwidefskyf4eae942013-06-24 10:30:41 +0200136 return ap_airq_flag;
Felix Beckcb17a632008-12-25 13:38:41 +0100137}
138
139/**
Felix Beck1749a812008-04-17 07:46:28 +0200140 * ap_intructions_available() - Test if AP instructions are available.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200141 *
Felix Beck1749a812008-04-17 07:46:28 +0200142 * Returns 0 if the AP instructions are installed.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200143 */
144static inline int ap_instructions_available(void)
145{
146 register unsigned long reg0 asm ("0") = AP_MKQID(0,0);
147 register unsigned long reg1 asm ("1") = -ENODEV;
148 register unsigned long reg2 asm ("2") = 0UL;
149
150 asm volatile(
151 " .long 0xb2af0000\n" /* PQAP(TAPQ) */
152 "0: la %1,0\n"
153 "1:\n"
154 EX_TABLE(0b, 1b)
155 : "+d" (reg0), "+d" (reg1), "+d" (reg2) : : "cc" );
156 return reg1;
157}
158
159/**
Felix Beckcb17a632008-12-25 13:38:41 +0100160 * ap_interrupts_available(): Test if AP interrupts are available.
161 *
162 * Returns 1 if AP interrupts are available.
163 */
164static int ap_interrupts_available(void)
165{
Felix Beck53ec24b12011-01-05 12:46:44 +0100166 return test_facility(2) && test_facility(65);
Felix Beckcb17a632008-12-25 13:38:41 +0100167}
168
169/**
Holger Dengler75014552012-08-28 16:41:50 +0200170 * ap_configuration_available(): Test if AP configuration
171 * information is available.
172 *
173 * Returns 1 if AP configuration information is available.
174 */
Heiko Carstensc80773e2012-09-14 11:21:17 +0200175#ifdef CONFIG_64BIT
Holger Dengler75014552012-08-28 16:41:50 +0200176static int ap_configuration_available(void)
177{
178 return test_facility(2) && test_facility(12);
179}
Heiko Carstensc80773e2012-09-14 11:21:17 +0200180#endif
Holger Dengler75014552012-08-28 16:41:50 +0200181
182/**
Felix Beck1749a812008-04-17 07:46:28 +0200183 * ap_test_queue(): Test adjunct processor queue.
184 * @qid: The AP queue number
185 * @queue_depth: Pointer to queue depth value
186 * @device_type: Pointer to device type value
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200187 *
Felix Beck1749a812008-04-17 07:46:28 +0200188 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200189 */
190static inline struct ap_queue_status
191ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
192{
193 register unsigned long reg0 asm ("0") = qid;
194 register struct ap_queue_status reg1 asm ("1");
195 register unsigned long reg2 asm ("2") = 0UL;
196
197 asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
198 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
199 *device_type = (int) (reg2 >> 24);
200 *queue_depth = (int) (reg2 & 0xff);
201 return reg1;
202}
203
204/**
Felix Beck1749a812008-04-17 07:46:28 +0200205 * ap_reset_queue(): Reset adjunct processor queue.
206 * @qid: The AP queue number
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200207 *
Felix Beck1749a812008-04-17 07:46:28 +0200208 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200209 */
210static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
211{
212 register unsigned long reg0 asm ("0") = qid | 0x01000000UL;
213 register struct ap_queue_status reg1 asm ("1");
214 register unsigned long reg2 asm ("2") = 0UL;
215
216 asm volatile(
217 ".long 0xb2af0000" /* PQAP(RAPQ) */
218 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
219 return reg1;
220}
221
Felix Beckcb17a632008-12-25 13:38:41 +0100222#ifdef CONFIG_64BIT
223/**
224 * ap_queue_interruption_control(): Enable interruption for a specific AP.
225 * @qid: The AP queue number
226 * @ind: The notification indicator byte
227 *
228 * Returns AP queue status.
229 */
230static inline struct ap_queue_status
231ap_queue_interruption_control(ap_qid_t qid, void *ind)
232{
233 register unsigned long reg0 asm ("0") = qid | 0x03000000UL;
234 register unsigned long reg1_in asm ("1") = 0x0000800000000000UL | AP_ISC;
235 register struct ap_queue_status reg1_out asm ("1");
236 register void *reg2 asm ("2") = ind;
237 asm volatile(
Holger Denglera7475af2012-05-16 14:10:26 +0200238 ".long 0xb2af0000" /* PQAP(AQIC) */
Felix Beckcb17a632008-12-25 13:38:41 +0100239 : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
240 :
241 : "cc" );
242 return reg1_out;
243}
244#endif
245
Holger Dengler6bed05b2011-07-24 10:48:25 +0200246#ifdef CONFIG_64BIT
247static inline struct ap_queue_status
248__ap_query_functions(ap_qid_t qid, unsigned int *functions)
Felix Beckb1f933d2011-01-05 12:47:44 +0100249{
250 register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
Holger Dengler6bed05b2011-07-24 10:48:25 +0200251 register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
252 register unsigned long reg2 asm ("2");
Felix Beckb1f933d2011-01-05 12:47:44 +0100253
254 asm volatile(
Holger Denglera7475af2012-05-16 14:10:26 +0200255 ".long 0xb2af0000\n" /* PQAP(TAPQ) */
Holger Dengler6bed05b2011-07-24 10:48:25 +0200256 "0:\n"
257 EX_TABLE(0b, 0b)
258 : "+d" (reg0), "+d" (reg1), "=d" (reg2)
Felix Beckb1f933d2011-01-05 12:47:44 +0100259 :
260 : "cc");
261
Holger Dengler6bed05b2011-07-24 10:48:25 +0200262 *functions = (unsigned int)(reg2 >> 32);
Felix Beckb1f933d2011-01-05 12:47:44 +0100263 return reg1;
264}
Holger Dengler6bed05b2011-07-24 10:48:25 +0200265#endif
266
Holger Dengler75014552012-08-28 16:41:50 +0200267#ifdef CONFIG_64BIT
268static inline int __ap_query_configuration(struct ap_config_info *config)
269{
270 register unsigned long reg0 asm ("0") = 0x04000000UL;
271 register unsigned long reg1 asm ("1") = -EINVAL;
272 register unsigned char *reg2 asm ("2") = (unsigned char *)config;
273
274 asm volatile(
275 ".long 0xb2af0000\n" /* PQAP(QCI) */
276 "0: la %1,0\n"
277 "1:\n"
278 EX_TABLE(0b, 1b)
279 : "+d" (reg0), "+d" (reg1), "+d" (reg2)
280 :
281 : "cc");
282
283 return reg1;
284}
285#endif
286
Holger Dengler6bed05b2011-07-24 10:48:25 +0200287/**
288 * ap_query_functions(): Query supported functions.
289 * @qid: The AP queue number
290 * @functions: Pointer to functions field.
291 *
292 * Returns
293 * 0 on success.
294 * -ENODEV if queue not valid.
295 * -EBUSY if device busy.
296 * -EINVAL if query function is not supported
297 */
298static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
299{
300#ifdef CONFIG_64BIT
301 struct ap_queue_status status;
302 int i;
303 status = __ap_query_functions(qid, functions);
304
305 for (i = 0; i < AP_MAX_RESET; i++) {
306 if (ap_queue_status_invalid_test(&status))
307 return -ENODEV;
308
309 switch (status.response_code) {
310 case AP_RESPONSE_NORMAL:
311 return 0;
312 case AP_RESPONSE_RESET_IN_PROGRESS:
313 case AP_RESPONSE_BUSY:
314 break;
315 case AP_RESPONSE_Q_NOT_AVAIL:
316 case AP_RESPONSE_DECONFIGURED:
317 case AP_RESPONSE_CHECKSTOPPED:
318 case AP_RESPONSE_INVALID_ADDRESS:
319 return -ENODEV;
320 case AP_RESPONSE_OTHERWISE_CHANGED:
321 break;
322 default:
323 break;
324 }
325 if (i < AP_MAX_RESET - 1) {
326 udelay(5);
327 status = __ap_query_functions(qid, functions);
328 }
329 }
330 return -EBUSY;
331#else
332 return -EINVAL;
333#endif
334}
Felix Beckb1f933d2011-01-05 12:47:44 +0100335
336/**
Felix Beckcb17a632008-12-25 13:38:41 +0100337 * ap_queue_enable_interruption(): Enable interruption on an AP.
338 * @qid: The AP queue number
339 * @ind: the notification indicator byte
340 *
341 * Enables interruption on AP queue via ap_queue_interruption_control(). Based
342 * on the return value it waits a while and tests the AP queue if interrupts
343 * have been switched on using ap_test_queue().
344 */
345static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
346{
347#ifdef CONFIG_64BIT
348 struct ap_queue_status status;
349 int t_depth, t_device_type, rc, i;
350
351 rc = -EBUSY;
352 status = ap_queue_interruption_control(qid, ind);
353
354 for (i = 0; i < AP_MAX_RESET; i++) {
355 switch (status.response_code) {
356 case AP_RESPONSE_NORMAL:
357 if (status.int_enabled)
358 return 0;
359 break;
360 case AP_RESPONSE_RESET_IN_PROGRESS:
361 case AP_RESPONSE_BUSY:
Holger Dengler8738e072012-07-02 12:39:59 +0200362 if (i < AP_MAX_RESET - 1) {
363 udelay(5);
364 status = ap_queue_interruption_control(qid,
365 ind);
366 continue;
367 }
Felix Beckcb17a632008-12-25 13:38:41 +0100368 break;
369 case AP_RESPONSE_Q_NOT_AVAIL:
370 case AP_RESPONSE_DECONFIGURED:
371 case AP_RESPONSE_CHECKSTOPPED:
372 case AP_RESPONSE_INVALID_ADDRESS:
373 return -ENODEV;
374 case AP_RESPONSE_OTHERWISE_CHANGED:
375 if (status.int_enabled)
376 return 0;
377 break;
378 default:
379 break;
380 }
381 if (i < AP_MAX_RESET - 1) {
382 udelay(5);
383 status = ap_test_queue(qid, &t_depth, &t_device_type);
384 }
385 }
386 return rc;
387#else
388 return -EINVAL;
389#endif
390}
391
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200392/**
Felix Beck1749a812008-04-17 07:46:28 +0200393 * __ap_send(): Send message to adjunct processor queue.
394 * @qid: The AP queue number
395 * @psmid: The program supplied message identifier
396 * @msg: The message text
397 * @length: The message length
Felix Becka6a5d732009-12-07 12:51:55 +0100398 * @special: Special Bit
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200399 *
Felix Beck1749a812008-04-17 07:46:28 +0200400 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200401 * Condition code 1 on NQAP can't happen because the L bit is 1.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200402 * Condition code 2 on NQAP also means the send is incomplete,
403 * because a segment boundary was reached. The NQAP is repeated.
404 */
405static inline struct ap_queue_status
Felix Becka6a5d732009-12-07 12:51:55 +0100406__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length,
407 unsigned int special)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200408{
409 typedef struct { char _[length]; } msgblock;
410 register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
411 register struct ap_queue_status reg1 asm ("1");
412 register unsigned long reg2 asm ("2") = (unsigned long) msg;
413 register unsigned long reg3 asm ("3") = (unsigned long) length;
414 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
415 register unsigned long reg5 asm ("5") = (unsigned int) psmid;
416
Felix Becka6a5d732009-12-07 12:51:55 +0100417 if (special == 1)
418 reg0 |= 0x400000UL;
419
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200420 asm volatile (
Holger Denglera7475af2012-05-16 14:10:26 +0200421 "0: .long 0xb2ad0042\n" /* NQAP */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200422 " brc 2,0b"
423 : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
424 : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg)
425 : "cc" );
426 return reg1;
427}
428
429int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
430{
431 struct ap_queue_status status;
432
Felix Becka6a5d732009-12-07 12:51:55 +0100433 status = __ap_send(qid, psmid, msg, length, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200434 switch (status.response_code) {
435 case AP_RESPONSE_NORMAL:
436 return 0;
437 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200438 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200439 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +0100440 case AP_RESPONSE_REQ_FAC_NOT_INST:
441 return -EINVAL;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200442 default: /* Device is gone. */
443 return -ENODEV;
444 }
445}
446EXPORT_SYMBOL(ap_send);
447
Felix Beck1749a812008-04-17 07:46:28 +0200448/**
449 * __ap_recv(): Receive message from adjunct processor queue.
450 * @qid: The AP queue number
451 * @psmid: Pointer to program supplied message identifier
452 * @msg: The message text
453 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200454 *
Felix Beck1749a812008-04-17 07:46:28 +0200455 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200456 * Condition code 1 on DQAP means the receive has taken place
457 * but only partially. The response is incomplete, hence the
458 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200459 * Condition code 2 on DQAP also means the receive is incomplete,
460 * this time because a segment boundary was reached. Again, the
461 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200462 * Note that gpr2 is used by the DQAP instruction to keep track of
463 * any 'residual' length, in case the instruction gets interrupted.
464 * Hence it gets zeroed before the instruction.
465 */
466static inline struct ap_queue_status
467__ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
468{
469 typedef struct { char _[length]; } msgblock;
470 register unsigned long reg0 asm("0") = qid | 0x80000000UL;
471 register struct ap_queue_status reg1 asm ("1");
472 register unsigned long reg2 asm("2") = 0UL;
473 register unsigned long reg4 asm("4") = (unsigned long) msg;
474 register unsigned long reg5 asm("5") = (unsigned long) length;
475 register unsigned long reg6 asm("6") = 0UL;
476 register unsigned long reg7 asm("7") = 0UL;
477
478
479 asm volatile(
Holger Denglera7475af2012-05-16 14:10:26 +0200480 "0: .long 0xb2ae0064\n" /* DQAP */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200481 " brc 6,0b\n"
482 : "+d" (reg0), "=d" (reg1), "+d" (reg2),
483 "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
484 "=m" (*(msgblock *) msg) : : "cc" );
485 *psmid = (((unsigned long long) reg6) << 32) + reg7;
486 return reg1;
487}
488
489int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
490{
491 struct ap_queue_status status;
492
493 status = __ap_recv(qid, psmid, msg, length);
494 switch (status.response_code) {
495 case AP_RESPONSE_NORMAL:
496 return 0;
497 case AP_RESPONSE_NO_PENDING_REPLY:
498 if (status.queue_empty)
499 return -ENOENT;
500 return -EBUSY;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200501 case AP_RESPONSE_RESET_IN_PROGRESS:
502 return -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200503 default:
504 return -ENODEV;
505 }
506}
507EXPORT_SYMBOL(ap_recv);
508
509/**
Felix Beck1749a812008-04-17 07:46:28 +0200510 * ap_query_queue(): Check if an AP queue is available.
511 * @qid: The AP queue number
512 * @queue_depth: Pointer to queue depth value
513 * @device_type: Pointer to device type value
514 *
515 * The test is repeated for AP_MAX_RESET times.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200516 */
517static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
518{
519 struct ap_queue_status status;
520 int t_depth, t_device_type, rc, i;
521
522 rc = -EBUSY;
523 for (i = 0; i < AP_MAX_RESET; i++) {
524 status = ap_test_queue(qid, &t_depth, &t_device_type);
525 switch (status.response_code) {
526 case AP_RESPONSE_NORMAL:
527 *queue_depth = t_depth + 1;
528 *device_type = t_device_type;
529 rc = 0;
530 break;
531 case AP_RESPONSE_Q_NOT_AVAIL:
532 rc = -ENODEV;
533 break;
534 case AP_RESPONSE_RESET_IN_PROGRESS:
535 break;
536 case AP_RESPONSE_DECONFIGURED:
537 rc = -ENODEV;
538 break;
539 case AP_RESPONSE_CHECKSTOPPED:
540 rc = -ENODEV;
541 break;
Felix Beckcb17a632008-12-25 13:38:41 +0100542 case AP_RESPONSE_INVALID_ADDRESS:
543 rc = -ENODEV;
544 break;
545 case AP_RESPONSE_OTHERWISE_CHANGED:
546 break;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200547 case AP_RESPONSE_BUSY:
548 break;
549 default:
550 BUG();
551 }
552 if (rc != -EBUSY)
553 break;
554 if (i < AP_MAX_RESET - 1)
555 udelay(5);
556 }
557 return rc;
558}
559
560/**
Felix Beck1749a812008-04-17 07:46:28 +0200561 * ap_init_queue(): Reset an AP queue.
562 * @qid: The AP queue number
563 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200564 * Reset an AP queue and wait for it to become available again.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200565 */
566static int ap_init_queue(ap_qid_t qid)
567{
568 struct ap_queue_status status;
569 int rc, dummy, i;
570
571 rc = -ENODEV;
572 status = ap_reset_queue(qid);
573 for (i = 0; i < AP_MAX_RESET; i++) {
574 switch (status.response_code) {
575 case AP_RESPONSE_NORMAL:
576 if (status.queue_empty)
577 rc = 0;
578 break;
579 case AP_RESPONSE_Q_NOT_AVAIL:
580 case AP_RESPONSE_DECONFIGURED:
581 case AP_RESPONSE_CHECKSTOPPED:
582 i = AP_MAX_RESET; /* return with -ENODEV */
583 break;
584 case AP_RESPONSE_RESET_IN_PROGRESS:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200585 rc = -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200586 case AP_RESPONSE_BUSY:
587 default:
588 break;
589 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200590 if (rc != -ENODEV && rc != -EBUSY)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200591 break;
592 if (i < AP_MAX_RESET - 1) {
593 udelay(5);
594 status = ap_test_queue(qid, &dummy, &dummy);
595 }
596 }
Felix Beckcb17a632008-12-25 13:38:41 +0100597 if (rc == 0 && ap_using_interrupts()) {
Martin Schwidefskyf4eae942013-06-24 10:30:41 +0200598 rc = ap_queue_enable_interruption(qid, ap_airq.lsi_ptr);
Felix Beckcb17a632008-12-25 13:38:41 +0100599 /* If interruption mode is supported by the machine,
600 * but an AP can not be enabled for interruption then
601 * the AP will be discarded. */
602 if (rc)
603 pr_err("Registering adapter interrupts for "
604 "AP %d failed\n", AP_QID_DEVICE(qid));
605 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200606 return rc;
607}
608
609/**
Felix Beck1749a812008-04-17 07:46:28 +0200610 * ap_increase_queue_count(): Arm request timeout.
611 * @ap_dev: Pointer to an AP device.
612 *
613 * Arm request timeout if an AP device was idle and a new request is submitted.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200614 */
615static void ap_increase_queue_count(struct ap_device *ap_dev)
616{
617 int timeout = ap_dev->drv->request_timeout;
618
619 ap_dev->queue_count++;
620 if (ap_dev->queue_count == 1) {
621 mod_timer(&ap_dev->timeout, jiffies + timeout);
622 ap_dev->reset = AP_RESET_ARMED;
623 }
624}
625
626/**
Felix Beck1749a812008-04-17 07:46:28 +0200627 * ap_decrease_queue_count(): Decrease queue count.
628 * @ap_dev: Pointer to an AP device.
629 *
630 * If AP device is still alive, re-schedule request timeout if there are still
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200631 * pending requests.
632 */
633static void ap_decrease_queue_count(struct ap_device *ap_dev)
634{
635 int timeout = ap_dev->drv->request_timeout;
636
637 ap_dev->queue_count--;
638 if (ap_dev->queue_count > 0)
639 mod_timer(&ap_dev->timeout, jiffies + timeout);
640 else
Felix Beck1749a812008-04-17 07:46:28 +0200641 /*
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200642 * The timeout timer should to be disabled now - since
643 * del_timer_sync() is very expensive, we just tell via the
644 * reset flag to ignore the pending timeout timer.
645 */
646 ap_dev->reset = AP_RESET_IGNORE;
647}
648
Felix Beck1749a812008-04-17 07:46:28 +0200649/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200650 * AP device related attributes.
651 */
652static ssize_t ap_hwtype_show(struct device *dev,
653 struct device_attribute *attr, char *buf)
654{
655 struct ap_device *ap_dev = to_ap_dev(dev);
656 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type);
657}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200658
Christian Maaser43c207e62008-12-25 13:38:42 +0100659static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200660static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr,
661 char *buf)
662{
663 struct ap_device *ap_dev = to_ap_dev(dev);
664 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth);
665}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200666
Christian Maaser43c207e62008-12-25 13:38:42 +0100667static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200668static ssize_t ap_request_count_show(struct device *dev,
669 struct device_attribute *attr,
670 char *buf)
671{
672 struct ap_device *ap_dev = to_ap_dev(dev);
673 int rc;
674
675 spin_lock_bh(&ap_dev->lock);
676 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->total_request_count);
677 spin_unlock_bh(&ap_dev->lock);
678 return rc;
679}
680
681static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL);
682
Holger Denglerb26bd942012-08-28 16:43:48 +0200683static ssize_t ap_requestq_count_show(struct device *dev,
684 struct device_attribute *attr, char *buf)
685{
686 struct ap_device *ap_dev = to_ap_dev(dev);
687 int rc;
688
689 spin_lock_bh(&ap_dev->lock);
690 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->requestq_count);
691 spin_unlock_bh(&ap_dev->lock);
692 return rc;
693}
694
695static DEVICE_ATTR(requestq_count, 0444, ap_requestq_count_show, NULL);
696
697static ssize_t ap_pendingq_count_show(struct device *dev,
698 struct device_attribute *attr, char *buf)
699{
700 struct ap_device *ap_dev = to_ap_dev(dev);
701 int rc;
702
703 spin_lock_bh(&ap_dev->lock);
704 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->pendingq_count);
705 spin_unlock_bh(&ap_dev->lock);
706 return rc;
707}
708
709static DEVICE_ATTR(pendingq_count, 0444, ap_pendingq_count_show, NULL);
710
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200711static ssize_t ap_modalias_show(struct device *dev,
712 struct device_attribute *attr, char *buf)
713{
714 return sprintf(buf, "ap:t%02X", to_ap_dev(dev)->device_type);
715}
716
717static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL);
718
Holger Denglerb26bd942012-08-28 16:43:48 +0200719static ssize_t ap_functions_show(struct device *dev,
720 struct device_attribute *attr, char *buf)
721{
722 struct ap_device *ap_dev = to_ap_dev(dev);
723 return snprintf(buf, PAGE_SIZE, "0x%08X\n", ap_dev->functions);
724}
725
726static DEVICE_ATTR(ap_functions, 0444, ap_functions_show, NULL);
727
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200728static struct attribute *ap_dev_attrs[] = {
729 &dev_attr_hwtype.attr,
730 &dev_attr_depth.attr,
731 &dev_attr_request_count.attr,
Holger Denglerb26bd942012-08-28 16:43:48 +0200732 &dev_attr_requestq_count.attr,
733 &dev_attr_pendingq_count.attr,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200734 &dev_attr_modalias.attr,
Holger Denglerb26bd942012-08-28 16:43:48 +0200735 &dev_attr_ap_functions.attr,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200736 NULL
737};
738static struct attribute_group ap_dev_attr_group = {
739 .attrs = ap_dev_attrs
740};
741
742/**
Felix Beck1749a812008-04-17 07:46:28 +0200743 * ap_bus_match()
744 * @dev: Pointer to device
745 * @drv: Pointer to device_driver
746 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200747 * AP bus driver registration/unregistration.
748 */
749static int ap_bus_match(struct device *dev, struct device_driver *drv)
750{
751 struct ap_device *ap_dev = to_ap_dev(dev);
752 struct ap_driver *ap_drv = to_ap_drv(drv);
753 struct ap_device_id *id;
754
Felix Beck1749a812008-04-17 07:46:28 +0200755 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200756 * Compare device type of the device with the list of
757 * supported types of the device_driver.
758 */
759 for (id = ap_drv->ids; id->match_flags; id++) {
760 if ((id->match_flags & AP_DEVICE_ID_MATCH_DEVICE_TYPE) &&
761 (id->dev_type != ap_dev->device_type))
762 continue;
763 return 1;
764 }
765 return 0;
766}
767
768/**
Felix Beck1749a812008-04-17 07:46:28 +0200769 * ap_uevent(): Uevent function for AP devices.
770 * @dev: Pointer to device
771 * @env: Pointer to kobj_uevent_env
772 *
773 * It sets up a single environment variable DEV_TYPE which contains the
774 * hardware device type.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200775 */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200776static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200777{
778 struct ap_device *ap_dev = to_ap_dev(dev);
Kay Sievers7eff2e72007-08-14 15:15:12 +0200779 int retval = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200780
781 if (!ap_dev)
782 return -ENODEV;
783
784 /* Set up DEV_TYPE environment variable. */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200785 retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700786 if (retval)
787 return retval;
788
Cornelia Huck66a4263b2006-12-04 15:40:10 +0100789 /* Add MODALIAS= */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200790 retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700791
Eric Rannaudbf624562007-03-30 22:23:12 -0700792 return retval;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200793}
794
Felix Beck772f5472009-06-22 12:08:16 +0200795static int ap_bus_suspend(struct device *dev, pm_message_t state)
796{
797 struct ap_device *ap_dev = to_ap_dev(dev);
798 unsigned long flags;
799
800 if (!ap_suspend_flag) {
801 ap_suspend_flag = 1;
802
803 /* Disable scanning for devices, thus we do not want to scan
804 * for them after removing.
805 */
806 del_timer_sync(&ap_config_timer);
807 if (ap_work_queue != NULL) {
808 destroy_workqueue(ap_work_queue);
809 ap_work_queue = NULL;
810 }
Felix Beck5314af62009-09-22 22:58:51 +0200811
Felix Beck772f5472009-06-22 12:08:16 +0200812 tasklet_disable(&ap_tasklet);
813 }
814 /* Poll on the device until all requests are finished. */
815 do {
816 flags = 0;
Felix Beck95f15562009-09-11 10:28:51 +0200817 spin_lock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200818 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +0200819 spin_unlock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200820 } while ((flags & 1) || (flags & 2));
821
Felix Beck5314af62009-09-22 22:58:51 +0200822 spin_lock_bh(&ap_dev->lock);
823 ap_dev->unregistered = 1;
824 spin_unlock_bh(&ap_dev->lock);
825
Felix Beck772f5472009-06-22 12:08:16 +0200826 return 0;
827}
828
829static int ap_bus_resume(struct device *dev)
830{
Felix Beck772f5472009-06-22 12:08:16 +0200831 struct ap_device *ap_dev = to_ap_dev(dev);
Martin Schwidefskyf4eae942013-06-24 10:30:41 +0200832 int rc;
Felix Beck772f5472009-06-22 12:08:16 +0200833
834 if (ap_suspend_flag) {
835 ap_suspend_flag = 0;
Martin Schwidefskyf4eae942013-06-24 10:30:41 +0200836 if (ap_interrupts_available()) {
837 if (!ap_using_interrupts()) {
838 rc = register_adapter_interrupt(&ap_airq);
839 ap_airq_flag = (rc == 0);
840 }
841 } else {
842 if (ap_using_interrupts()) {
843 unregister_adapter_interrupt(&ap_airq);
844 ap_airq_flag = 0;
845 }
846 }
Holger Dengler75014552012-08-28 16:41:50 +0200847 ap_query_configuration();
Felix Beck5314af62009-09-22 22:58:51 +0200848 if (!user_set_domain) {
849 ap_domain_index = -1;
850 ap_select_domain();
851 }
Felix Beck772f5472009-06-22 12:08:16 +0200852 init_timer(&ap_config_timer);
853 ap_config_timer.function = ap_config_timeout;
854 ap_config_timer.data = 0;
855 ap_config_timer.expires = jiffies + ap_config_time * HZ;
856 add_timer(&ap_config_timer);
857 ap_work_queue = create_singlethread_workqueue("kapwork");
858 if (!ap_work_queue)
859 return -ENOMEM;
860 tasklet_enable(&ap_tasklet);
861 if (!ap_using_interrupts())
862 ap_schedule_poll_timer();
863 else
864 tasklet_schedule(&ap_tasklet);
865 if (ap_thread_flag)
866 rc = ap_poll_thread_start();
Martin Schwidefskyf4eae942013-06-24 10:30:41 +0200867 else
868 rc = 0;
869 } else
870 rc = 0;
Felix Beck5314af62009-09-22 22:58:51 +0200871 if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) {
872 spin_lock_bh(&ap_dev->lock);
873 ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid),
874 ap_domain_index);
875 spin_unlock_bh(&ap_dev->lock);
876 }
877 queue_work(ap_work_queue, &ap_config_work);
Felix Beck772f5472009-06-22 12:08:16 +0200878
879 return rc;
880}
881
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200882static struct bus_type ap_bus_type = {
883 .name = "ap",
884 .match = &ap_bus_match,
885 .uevent = &ap_uevent,
Felix Beck772f5472009-06-22 12:08:16 +0200886 .suspend = ap_bus_suspend,
887 .resume = ap_bus_resume
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200888};
889
890static int ap_device_probe(struct device *dev)
891{
892 struct ap_device *ap_dev = to_ap_dev(dev);
893 struct ap_driver *ap_drv = to_ap_drv(dev->driver);
894 int rc;
895
896 ap_dev->drv = ap_drv;
897 rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100898 if (!rc) {
Christian Maaser43c207e62008-12-25 13:38:42 +0100899 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100900 list_add(&ap_dev->list, &ap_device_list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100901 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100902 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200903 return rc;
904}
905
906/**
Felix Beck1749a812008-04-17 07:46:28 +0200907 * __ap_flush_queue(): Flush requests.
908 * @ap_dev: Pointer to the AP device
909 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200910 * Flush all requests from the request/pending queue of an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200911 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100912static void __ap_flush_queue(struct ap_device *ap_dev)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200913{
914 struct ap_message *ap_msg, *next;
915
916 list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
917 list_del_init(&ap_msg->list);
918 ap_dev->pendingq_count--;
Holger Dengler54a8f562012-05-16 14:08:22 +0200919 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200920 }
921 list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
922 list_del_init(&ap_msg->list);
923 ap_dev->requestq_count--;
Holger Dengler54a8f562012-05-16 14:08:22 +0200924 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200925 }
926}
927
928void ap_flush_queue(struct ap_device *ap_dev)
929{
930 spin_lock_bh(&ap_dev->lock);
931 __ap_flush_queue(ap_dev);
932 spin_unlock_bh(&ap_dev->lock);
933}
934EXPORT_SYMBOL(ap_flush_queue);
935
936static int ap_device_remove(struct device *dev)
937{
938 struct ap_device *ap_dev = to_ap_dev(dev);
939 struct ap_driver *ap_drv = ap_dev->drv;
940
Ralph Wuerthner4e562962006-10-04 20:02:05 +0200941 ap_flush_queue(ap_dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200942 del_timer_sync(&ap_dev->timeout);
Christian Maaser43c207e62008-12-25 13:38:42 +0100943 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +0100944 list_del_init(&ap_dev->list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100945 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100946 if (ap_drv->remove)
947 ap_drv->remove(ap_dev);
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +0200948 spin_lock_bh(&ap_dev->lock);
949 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
950 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200951 return 0;
952}
953
954int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
955 char *name)
956{
957 struct device_driver *drv = &ap_drv->driver;
958
959 drv->bus = &ap_bus_type;
960 drv->probe = ap_device_probe;
961 drv->remove = ap_device_remove;
962 drv->owner = owner;
963 drv->name = name;
964 return driver_register(drv);
965}
966EXPORT_SYMBOL(ap_driver_register);
967
968void ap_driver_unregister(struct ap_driver *ap_drv)
969{
970 driver_unregister(&ap_drv->driver);
971}
972EXPORT_SYMBOL(ap_driver_unregister);
973
Holger Denglerdabecb22012-09-10 21:34:26 +0200974void ap_bus_force_rescan(void)
975{
Ingo Tuchscherer56bbe682013-04-12 17:52:08 +0200976 /* reconfigure the AP bus rescan timer. */
977 mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ);
978 /* processing a asynchronous bus rescan */
979 queue_work(ap_work_queue, &ap_config_work);
980 flush_work(&ap_config_work);
Holger Denglerdabecb22012-09-10 21:34:26 +0200981}
982EXPORT_SYMBOL(ap_bus_force_rescan);
983
Felix Beck1749a812008-04-17 07:46:28 +0200984/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200985 * AP bus attributes.
986 */
987static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
988{
989 return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
990}
991
992static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
993
994static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
995{
996 return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
997}
998
Felix Beckcb17a632008-12-25 13:38:41 +0100999static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
1000{
1001 return snprintf(buf, PAGE_SIZE, "%d\n",
1002 ap_using_interrupts() ? 1 : 0);
1003}
1004
1005static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL);
1006
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001007static ssize_t ap_config_time_store(struct bus_type *bus,
1008 const char *buf, size_t count)
1009{
1010 int time;
1011
1012 if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120)
1013 return -EINVAL;
1014 ap_config_time = time;
1015 if (!timer_pending(&ap_config_timer) ||
1016 !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) {
1017 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1018 add_timer(&ap_config_timer);
1019 }
1020 return count;
1021}
1022
1023static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store);
1024
1025static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf)
1026{
1027 return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
1028}
1029
1030static ssize_t ap_poll_thread_store(struct bus_type *bus,
1031 const char *buf, size_t count)
1032{
1033 int flag, rc;
1034
1035 if (sscanf(buf, "%d\n", &flag) != 1)
1036 return -EINVAL;
1037 if (flag) {
1038 rc = ap_poll_thread_start();
1039 if (rc)
1040 return rc;
1041 }
1042 else
1043 ap_poll_thread_stop();
1044 return count;
1045}
1046
1047static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
1048
Felix Beckfe137232008-07-14 09:59:08 +02001049static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
1050{
1051 return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
1052}
1053
1054static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
1055 size_t count)
1056{
1057 unsigned long long time;
1058 ktime_t hr_time;
1059
1060 /* 120 seconds = maximum poll interval */
Felix Beckcb17a632008-12-25 13:38:41 +01001061 if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 ||
1062 time > 120000000000ULL)
Felix Beckfe137232008-07-14 09:59:08 +02001063 return -EINVAL;
1064 poll_timeout = time;
1065 hr_time = ktime_set(0, poll_timeout);
1066
1067 if (!hrtimer_is_queued(&ap_poll_timer) ||
Arjan van de Ven6c644ea2008-09-01 15:20:30 -07001068 !hrtimer_forward(&ap_poll_timer, hrtimer_get_expires(&ap_poll_timer), hr_time)) {
1069 hrtimer_set_expires(&ap_poll_timer, hr_time);
1070 hrtimer_start_expires(&ap_poll_timer, HRTIMER_MODE_ABS);
Felix Beckfe137232008-07-14 09:59:08 +02001071 }
1072 return count;
1073}
1074
1075static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
1076
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001077static struct bus_attribute *const ap_bus_attrs[] = {
1078 &bus_attr_ap_domain,
1079 &bus_attr_config_time,
1080 &bus_attr_poll_thread,
Felix Beckcb17a632008-12-25 13:38:41 +01001081 &bus_attr_ap_interrupts,
Felix Beckfe137232008-07-14 09:59:08 +02001082 &bus_attr_poll_timeout,
1083 NULL,
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001084};
1085
Holger Dengler75014552012-08-28 16:41:50 +02001086static inline int ap_test_config(unsigned int *field, unsigned int nr)
1087{
1088 if (nr > 0xFFu)
1089 return 0;
1090 return ap_test_bit((field + (nr >> 5)), (nr & 0x1f));
1091}
1092
1093/*
1094 * ap_test_config_card_id(): Test, whether an AP card ID is configured.
1095 * @id AP card ID
1096 *
1097 * Returns 0 if the card is not configured
1098 * 1 if the card is configured or
1099 * if the configuration information is not available
1100 */
1101static inline int ap_test_config_card_id(unsigned int id)
1102{
1103 if (!ap_configuration)
1104 return 1;
1105 return ap_test_config(ap_configuration->apm, id);
1106}
1107
1108/*
1109 * ap_test_config_domain(): Test, whether an AP usage domain is configured.
1110 * @domain AP usage domain ID
1111 *
1112 * Returns 0 if the usage domain is not configured
1113 * 1 if the usage domain is configured or
1114 * if the configuration information is not available
1115 */
1116static inline int ap_test_config_domain(unsigned int domain)
1117{
1118 if (!ap_configuration)
1119 return 1;
1120 return ap_test_config(ap_configuration->aqm, domain);
1121}
1122
1123/**
1124 * ap_query_configuration(): Query AP configuration information.
1125 *
1126 * Query information of installed cards and configured domains from AP.
1127 */
1128static void ap_query_configuration(void)
1129{
1130#ifdef CONFIG_64BIT
1131 if (ap_configuration_available()) {
1132 if (!ap_configuration)
1133 ap_configuration =
1134 kzalloc(sizeof(struct ap_config_info),
1135 GFP_KERNEL);
1136 if (ap_configuration)
1137 __ap_query_configuration(ap_configuration);
1138 } else
1139 ap_configuration = NULL;
1140#else
1141 ap_configuration = NULL;
1142#endif
1143}
1144
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001145/**
Felix Beck1749a812008-04-17 07:46:28 +02001146 * ap_select_domain(): Select an AP domain.
1147 *
1148 * Pick one of the 16 AP domains.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001149 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001150static int ap_select_domain(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001151{
1152 int queue_depth, device_type, count, max_count, best_domain;
Holger Dengler75014552012-08-28 16:41:50 +02001153 ap_qid_t qid;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001154 int rc, i, j;
1155
Felix Beck1749a812008-04-17 07:46:28 +02001156 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001157 * We want to use a single domain. Either the one specified with
1158 * the "domain=" parameter or the domain with the maximum number
1159 * of devices.
1160 */
1161 if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS)
1162 /* Domain has already been selected. */
1163 return 0;
1164 best_domain = -1;
1165 max_count = 0;
1166 for (i = 0; i < AP_DOMAINS; i++) {
Holger Dengler75014552012-08-28 16:41:50 +02001167 if (!ap_test_config_domain(i))
1168 continue;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001169 count = 0;
1170 for (j = 0; j < AP_DEVICES; j++) {
Holger Dengler75014552012-08-28 16:41:50 +02001171 if (!ap_test_config_card_id(j))
1172 continue;
1173 qid = AP_MKQID(j, i);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001174 rc = ap_query_queue(qid, &queue_depth, &device_type);
1175 if (rc)
1176 continue;
1177 count++;
1178 }
1179 if (count > max_count) {
1180 max_count = count;
1181 best_domain = i;
1182 }
1183 }
1184 if (best_domain >= 0){
1185 ap_domain_index = best_domain;
1186 return 0;
1187 }
1188 return -ENODEV;
1189}
1190
1191/**
Felix Beck1749a812008-04-17 07:46:28 +02001192 * ap_probe_device_type(): Find the device type of an AP.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001193 * @ap_dev: pointer to the AP device.
Felix Beck1749a812008-04-17 07:46:28 +02001194 *
1195 * Find the device type if query queue returned a device type of 0.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001196 */
1197static int ap_probe_device_type(struct ap_device *ap_dev)
1198{
1199 static unsigned char msg[] = {
1200 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
1201 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1202 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
1203 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1204 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50,
1205 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,
1206 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00,
1207 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,
1208 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1209 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,
1210 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1211 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,
1212 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00,
1213 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1214 0x00,0x00,0x00,0x00,0xb8,0x05,0x00,0x00,
1215 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1216 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1217 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1218 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1219 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1220 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1221 0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,
1222 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1223 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
1224 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20,
1225 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,
1226 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22,
1227 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1228 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
1229 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,
1230 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,
1231 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,
1232 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1233 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,
1234 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00,
1235 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,
1236 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01,
1237 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,
1238 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68,
1239 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,
1240 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0,
1241 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,
1242 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04,
1243 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,
1244 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d,
1245 };
1246 struct ap_queue_status status;
1247 unsigned long long psmid;
1248 char *reply;
1249 int rc, i;
1250
1251 reply = (void *) get_zeroed_page(GFP_KERNEL);
1252 if (!reply) {
1253 rc = -ENOMEM;
1254 goto out;
1255 }
1256
1257 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
Felix Becka6a5d732009-12-07 12:51:55 +01001258 msg, sizeof(msg), 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001259 if (status.response_code != AP_RESPONSE_NORMAL) {
1260 rc = -ENODEV;
1261 goto out_free;
1262 }
1263
1264 /* Wait for the test message to complete. */
1265 for (i = 0; i < 6; i++) {
1266 mdelay(300);
1267 status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
1268 if (status.response_code == AP_RESPONSE_NORMAL &&
1269 psmid == 0x0102030405060708ULL)
1270 break;
1271 }
1272 if (i < 6) {
1273 /* Got an answer. */
1274 if (reply[0] == 0x00 && reply[1] == 0x86)
1275 ap_dev->device_type = AP_DEVICE_TYPE_PCICC;
1276 else
1277 ap_dev->device_type = AP_DEVICE_TYPE_PCICA;
1278 rc = 0;
1279 } else
1280 rc = -ENODEV;
1281
1282out_free:
1283 free_page((unsigned long) reply);
1284out:
1285 return rc;
1286}
1287
Martin Schwidefskyf4eae942013-06-24 10:30:41 +02001288static void ap_interrupt_handler(struct airq_struct *airq)
Felix Beckcb17a632008-12-25 13:38:41 +01001289{
Heiko Carstens420f42e2013-01-02 15:18:18 +01001290 inc_irq_stat(IRQIO_APB);
Felix Beckcb17a632008-12-25 13:38:41 +01001291 tasklet_schedule(&ap_tasklet);
1292}
1293
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001294/**
Felix Beck1749a812008-04-17 07:46:28 +02001295 * __ap_scan_bus(): Scan the AP bus.
1296 * @dev: Pointer to device
1297 * @data: Pointer to data
1298 *
1299 * Scan the AP bus for new devices.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001300 */
1301static int __ap_scan_bus(struct device *dev, void *data)
1302{
1303 return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data;
1304}
1305
1306static void ap_device_release(struct device *dev)
1307{
1308 struct ap_device *ap_dev = to_ap_dev(dev);
1309
1310 kfree(ap_dev);
1311}
1312
Al Viro4927b3f2006-12-06 19:18:20 +00001313static void ap_scan_bus(struct work_struct *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001314{
1315 struct ap_device *ap_dev;
1316 struct device *dev;
1317 ap_qid_t qid;
1318 int queue_depth, device_type;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001319 unsigned int device_functions;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001320 int rc, i;
1321
Holger Dengler75014552012-08-28 16:41:50 +02001322 ap_query_configuration();
Ingo Tuchscherer56bbe682013-04-12 17:52:08 +02001323 if (ap_select_domain() != 0) {
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001324 return;
Ingo Tuchscherer56bbe682013-04-12 17:52:08 +02001325 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001326 for (i = 0; i < AP_DEVICES; i++) {
1327 qid = AP_MKQID(i, ap_domain_index);
1328 dev = bus_find_device(&ap_bus_type, NULL,
1329 (void *)(unsigned long)qid,
1330 __ap_scan_bus);
Holger Dengler75014552012-08-28 16:41:50 +02001331 if (ap_test_config_card_id(i))
1332 rc = ap_query_queue(qid, &queue_depth, &device_type);
1333 else
1334 rc = -ENODEV;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001335 if (dev) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001336 if (rc == -EBUSY) {
1337 set_current_state(TASK_UNINTERRUPTIBLE);
1338 schedule_timeout(AP_RESET_TIMEOUT);
1339 rc = ap_query_queue(qid, &queue_depth,
1340 &device_type);
1341 }
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001342 ap_dev = to_ap_dev(dev);
1343 spin_lock_bh(&ap_dev->lock);
1344 if (rc || ap_dev->unregistered) {
1345 spin_unlock_bh(&ap_dev->lock);
Felix Beck5314af62009-09-22 22:58:51 +02001346 if (ap_dev->unregistered)
1347 i--;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001348 device_unregister(dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001349 put_device(dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001350 continue;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001351 }
1352 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001353 put_device(dev);
1354 continue;
1355 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001356 if (rc)
1357 continue;
1358 rc = ap_init_queue(qid);
1359 if (rc)
1360 continue;
1361 ap_dev = kzalloc(sizeof(*ap_dev), GFP_KERNEL);
1362 if (!ap_dev)
1363 break;
1364 ap_dev->qid = qid;
1365 ap_dev->queue_depth = queue_depth;
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001366 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001367 spin_lock_init(&ap_dev->lock);
1368 INIT_LIST_HEAD(&ap_dev->pendingq);
1369 INIT_LIST_HEAD(&ap_dev->requestq);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001370 INIT_LIST_HEAD(&ap_dev->list);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001371 setup_timer(&ap_dev->timeout, ap_request_timeout,
1372 (unsigned long) ap_dev);
Holger Dengler6bed05b2011-07-24 10:48:25 +02001373 switch (device_type) {
1374 case 0:
Holger Dengler1e2076f2012-08-28 16:48:29 +02001375 /* device type probing for old cards */
Holger Denglercf2d0072011-05-23 10:24:30 +02001376 if (ap_probe_device_type(ap_dev)) {
1377 kfree(ap_dev);
1378 continue;
1379 }
Holger Dengler6bed05b2011-07-24 10:48:25 +02001380 break;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001381 default:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001382 ap_dev->device_type = device_type;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001383 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001384
Holger Dengler1e2076f2012-08-28 16:48:29 +02001385 rc = ap_query_functions(qid, &device_functions);
1386 if (!rc)
1387 ap_dev->functions = device_functions;
1388 else
1389 ap_dev->functions = 0u;
1390
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001391 ap_dev->device.bus = &ap_bus_type;
1392 ap_dev->device.parent = ap_root_device;
Felix Beckedc44fa2009-09-11 10:28:52 +02001393 if (dev_set_name(&ap_dev->device, "card%02x",
1394 AP_QID_DEVICE(ap_dev->qid))) {
1395 kfree(ap_dev);
1396 continue;
1397 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001398 ap_dev->device.release = ap_device_release;
1399 rc = device_register(&ap_dev->device);
1400 if (rc) {
Sebastian Ottc6304932009-09-11 10:28:38 +02001401 put_device(&ap_dev->device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001402 continue;
1403 }
1404 /* Add device attributes. */
1405 rc = sysfs_create_group(&ap_dev->device.kobj,
1406 &ap_dev_attr_group);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001407 if (!rc) {
1408 spin_lock_bh(&ap_dev->lock);
1409 ap_dev->unregistered = 0;
1410 spin_unlock_bh(&ap_dev->lock);
1411 }
1412 else
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001413 device_unregister(&ap_dev->device);
1414 }
1415}
1416
1417static void
1418ap_config_timeout(unsigned long ptr)
1419{
1420 queue_work(ap_work_queue, &ap_config_work);
1421 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1422 add_timer(&ap_config_timer);
1423}
1424
1425/**
Holger Denglerbc615de2011-11-14 11:19:04 +01001426 * __ap_schedule_poll_timer(): Schedule poll timer.
Felix Beck1749a812008-04-17 07:46:28 +02001427 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001428 * Set up the timer to run the poll tasklet
1429 */
Holger Denglerbc615de2011-11-14 11:19:04 +01001430static inline void __ap_schedule_poll_timer(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001431{
Felix Beck8d406c62009-07-24 12:39:53 +02001432 ktime_t hr_time;
Felix Beck93521312009-12-07 12:52:00 +01001433
1434 spin_lock_bh(&ap_poll_timer_lock);
Holger Denglerbc615de2011-11-14 11:19:04 +01001435 if (hrtimer_is_queued(&ap_poll_timer) || ap_suspend_flag)
Felix Beck93521312009-12-07 12:52:00 +01001436 goto out;
Felix Beck8d406c62009-07-24 12:39:53 +02001437 if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
1438 hr_time = ktime_set(0, poll_timeout);
1439 hrtimer_forward_now(&ap_poll_timer, hr_time);
1440 hrtimer_restart(&ap_poll_timer);
1441 }
Felix Beck93521312009-12-07 12:52:00 +01001442out:
1443 spin_unlock_bh(&ap_poll_timer_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001444}
1445
1446/**
Holger Denglerbc615de2011-11-14 11:19:04 +01001447 * ap_schedule_poll_timer(): Schedule poll timer.
1448 *
1449 * Set up the timer to run the poll tasklet
1450 */
1451static inline void ap_schedule_poll_timer(void)
1452{
1453 if (ap_using_interrupts())
1454 return;
1455 __ap_schedule_poll_timer();
1456}
1457
1458/**
Felix Beck1749a812008-04-17 07:46:28 +02001459 * ap_poll_read(): Receive pending reply messages from an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001460 * @ap_dev: pointer to the AP device
1461 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1462 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001463 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001464 * Returns 0 if the device is still present, -ENODEV if not.
1465 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001466static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001467{
1468 struct ap_queue_status status;
1469 struct ap_message *ap_msg;
1470
1471 if (ap_dev->queue_count <= 0)
1472 return 0;
1473 status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
1474 ap_dev->reply->message, ap_dev->reply->length);
1475 switch (status.response_code) {
1476 case AP_RESPONSE_NORMAL:
1477 atomic_dec(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001478 ap_decrease_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001479 list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
1480 if (ap_msg->psmid != ap_dev->reply->psmid)
1481 continue;
1482 list_del_init(&ap_msg->list);
1483 ap_dev->pendingq_count--;
Holger Dengler54a8f562012-05-16 14:08:22 +02001484 ap_msg->receive(ap_dev, ap_msg, ap_dev->reply);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001485 break;
1486 }
1487 if (ap_dev->queue_count > 0)
1488 *flags |= 1;
1489 break;
1490 case AP_RESPONSE_NO_PENDING_REPLY:
1491 if (status.queue_empty) {
1492 /* The card shouldn't forget requests but who knows. */
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +02001493 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001494 ap_dev->queue_count = 0;
1495 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1496 ap_dev->requestq_count += ap_dev->pendingq_count;
1497 ap_dev->pendingq_count = 0;
1498 } else
1499 *flags |= 2;
1500 break;
1501 default:
1502 return -ENODEV;
1503 }
1504 return 0;
1505}
1506
1507/**
Felix Beck1749a812008-04-17 07:46:28 +02001508 * ap_poll_write(): Send messages from the request queue to an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001509 * @ap_dev: pointer to the AP device
1510 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1511 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001512 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001513 * Returns 0 if the device is still present, -ENODEV if not.
1514 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001515static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001516{
1517 struct ap_queue_status status;
1518 struct ap_message *ap_msg;
1519
1520 if (ap_dev->requestq_count <= 0 ||
1521 ap_dev->queue_count >= ap_dev->queue_depth)
1522 return 0;
1523 /* Start the next request on the queue. */
1524 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
1525 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001526 ap_msg->message, ap_msg->length, ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001527 switch (status.response_code) {
1528 case AP_RESPONSE_NORMAL:
1529 atomic_inc(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001530 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001531 list_move_tail(&ap_msg->list, &ap_dev->pendingq);
1532 ap_dev->requestq_count--;
1533 ap_dev->pendingq_count++;
1534 if (ap_dev->queue_count < ap_dev->queue_depth &&
1535 ap_dev->requestq_count > 0)
1536 *flags |= 1;
1537 *flags |= 2;
1538 break;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001539 case AP_RESPONSE_RESET_IN_PROGRESS:
Holger Denglerbc615de2011-11-14 11:19:04 +01001540 __ap_schedule_poll_timer();
1541 case AP_RESPONSE_Q_FULL:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001542 *flags |= 2;
1543 break;
1544 case AP_RESPONSE_MESSAGE_TOO_BIG:
Felix Becka6a5d732009-12-07 12:51:55 +01001545 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001546 return -EINVAL;
1547 default:
1548 return -ENODEV;
1549 }
1550 return 0;
1551}
1552
1553/**
Felix Beck1749a812008-04-17 07:46:28 +02001554 * ap_poll_queue(): Poll AP device for pending replies and send new messages.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001555 * @ap_dev: pointer to the bus device
1556 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1557 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001558 *
1559 * Poll AP device for pending replies and send new messages. If either
1560 * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001561 * Returns 0.
1562 */
1563static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
1564{
1565 int rc;
1566
1567 rc = ap_poll_read(ap_dev, flags);
1568 if (rc)
1569 return rc;
1570 return ap_poll_write(ap_dev, flags);
1571}
1572
1573/**
Felix Beck1749a812008-04-17 07:46:28 +02001574 * __ap_queue_message(): Queue a message to a device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001575 * @ap_dev: pointer to the AP device
1576 * @ap_msg: the message to be queued
Felix Beck1749a812008-04-17 07:46:28 +02001577 *
1578 * Queue a message to a device. Returns 0 if successful.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001579 */
1580static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1581{
1582 struct ap_queue_status status;
1583
1584 if (list_empty(&ap_dev->requestq) &&
1585 ap_dev->queue_count < ap_dev->queue_depth) {
1586 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001587 ap_msg->message, ap_msg->length,
1588 ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001589 switch (status.response_code) {
1590 case AP_RESPONSE_NORMAL:
1591 list_add_tail(&ap_msg->list, &ap_dev->pendingq);
1592 atomic_inc(&ap_poll_requests);
1593 ap_dev->pendingq_count++;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001594 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001595 ap_dev->total_request_count++;
1596 break;
1597 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001598 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001599 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1600 ap_dev->requestq_count++;
1601 ap_dev->total_request_count++;
1602 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +01001603 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001604 case AP_RESPONSE_MESSAGE_TOO_BIG:
Holger Dengler54a8f562012-05-16 14:08:22 +02001605 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001606 return -EINVAL;
1607 default: /* Device is gone. */
Holger Dengler54a8f562012-05-16 14:08:22 +02001608 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001609 return -ENODEV;
1610 }
1611 } else {
1612 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1613 ap_dev->requestq_count++;
1614 ap_dev->total_request_count++;
1615 return -EBUSY;
1616 }
1617 ap_schedule_poll_timer();
1618 return 0;
1619}
1620
1621void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1622{
1623 unsigned long flags;
1624 int rc;
1625
Holger Dengler54a8f562012-05-16 14:08:22 +02001626 /* For asynchronous message handling a valid receive-callback
1627 * is required. */
1628 BUG_ON(!ap_msg->receive);
1629
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001630 spin_lock_bh(&ap_dev->lock);
1631 if (!ap_dev->unregistered) {
1632 /* Make room on the queue by polling for finished requests. */
1633 rc = ap_poll_queue(ap_dev, &flags);
1634 if (!rc)
1635 rc = __ap_queue_message(ap_dev, ap_msg);
1636 if (!rc)
1637 wake_up(&ap_poll_wait);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001638 if (rc == -ENODEV)
1639 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001640 } else {
Holger Dengler54a8f562012-05-16 14:08:22 +02001641 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001642 rc = -ENODEV;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001643 }
1644 spin_unlock_bh(&ap_dev->lock);
1645 if (rc == -ENODEV)
1646 device_unregister(&ap_dev->device);
1647}
1648EXPORT_SYMBOL(ap_queue_message);
1649
1650/**
Felix Beck1749a812008-04-17 07:46:28 +02001651 * ap_cancel_message(): Cancel a crypto request.
1652 * @ap_dev: The AP device that has the message queued
1653 * @ap_msg: The message that is to be removed
1654 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001655 * Cancel a crypto request. This is done by removing the request
Felix Beck1749a812008-04-17 07:46:28 +02001656 * from the device pending or request queue. Note that the
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001657 * request stays on the AP queue. When it finishes the message
1658 * reply will be discarded because the psmid can't be found.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001659 */
1660void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1661{
1662 struct ap_message *tmp;
1663
1664 spin_lock_bh(&ap_dev->lock);
1665 if (!list_empty(&ap_msg->list)) {
1666 list_for_each_entry(tmp, &ap_dev->pendingq, list)
1667 if (tmp->psmid == ap_msg->psmid) {
1668 ap_dev->pendingq_count--;
1669 goto found;
1670 }
1671 ap_dev->requestq_count--;
1672 found:
1673 list_del_init(&ap_msg->list);
1674 }
1675 spin_unlock_bh(&ap_dev->lock);
1676}
1677EXPORT_SYMBOL(ap_cancel_message);
1678
1679/**
Felix Beck1749a812008-04-17 07:46:28 +02001680 * ap_poll_timeout(): AP receive polling for finished AP requests.
Felix Beckfe137232008-07-14 09:59:08 +02001681 * @unused: Unused pointer.
Felix Beck1749a812008-04-17 07:46:28 +02001682 *
Felix Beckfe137232008-07-14 09:59:08 +02001683 * Schedules the AP tasklet using a high resolution timer.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001684 */
Felix Beckfe137232008-07-14 09:59:08 +02001685static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001686{
1687 tasklet_schedule(&ap_tasklet);
Felix Beckfe137232008-07-14 09:59:08 +02001688 return HRTIMER_NORESTART;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001689}
1690
1691/**
Felix Beck1749a812008-04-17 07:46:28 +02001692 * ap_reset(): Reset a not responding AP device.
1693 * @ap_dev: Pointer to the AP device
1694 *
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001695 * Reset a not responding AP device and move all requests from the
1696 * pending queue to the request queue.
1697 */
1698static void ap_reset(struct ap_device *ap_dev)
1699{
1700 int rc;
1701
1702 ap_dev->reset = AP_RESET_IGNORE;
1703 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
1704 ap_dev->queue_count = 0;
1705 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1706 ap_dev->requestq_count += ap_dev->pendingq_count;
1707 ap_dev->pendingq_count = 0;
1708 rc = ap_init_queue(ap_dev->qid);
1709 if (rc == -ENODEV)
1710 ap_dev->unregistered = 1;
Holger Dengler75464962011-12-01 13:32:23 +01001711 else
1712 __ap_schedule_poll_timer();
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001713}
1714
Christian Maaser43c207e62008-12-25 13:38:42 +01001715static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001716{
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001717 if (!ap_dev->unregistered) {
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001718 if (ap_poll_queue(ap_dev, flags))
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001719 ap_dev->unregistered = 1;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001720 if (ap_dev->reset == AP_RESET_DO)
1721 ap_reset(ap_dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001722 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001723 return 0;
1724}
1725
Felix Beck1749a812008-04-17 07:46:28 +02001726/**
1727 * ap_poll_all(): Poll all AP devices.
1728 * @dummy: Unused variable
1729 *
1730 * Poll all AP devices on the bus in a round robin fashion. Continue
1731 * polling until bit 2^0 of the control flags is not set. If bit 2^1
1732 * of the control flags has been set arm the poll timer.
1733 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001734static void ap_poll_all(unsigned long dummy)
1735{
1736 unsigned long flags;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001737 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001738
Felix Beckcb17a632008-12-25 13:38:41 +01001739 /* Reset the indicator if interrupts are used. Thus new interrupts can
1740 * be received. Doing it in the beginning of the tasklet is therefor
1741 * important that no requests on any AP get lost.
1742 */
1743 if (ap_using_interrupts())
Martin Schwidefskyf4eae942013-06-24 10:30:41 +02001744 xchg(ap_airq.lsi_ptr, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001745 do {
1746 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001747 spin_lock(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001748 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001749 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001750 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001751 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001752 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001753 spin_unlock(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001754 } while (flags & 1);
1755 if (flags & 2)
1756 ap_schedule_poll_timer();
1757}
1758
1759/**
Felix Beck1749a812008-04-17 07:46:28 +02001760 * ap_poll_thread(): Thread that polls for finished requests.
1761 * @data: Unused pointer
1762 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001763 * AP bus poll thread. The purpose of this thread is to poll for
1764 * finished requests in a loop if there is a "free" cpu - that is
1765 * a cpu that doesn't have anything better to do. The polling stops
1766 * as soon as there is another task or if all messages have been
1767 * delivered.
1768 */
1769static int ap_poll_thread(void *data)
1770{
1771 DECLARE_WAITQUEUE(wait, current);
1772 unsigned long flags;
1773 int requests;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001774 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001775
Christian Borntraegerd83682b2006-10-06 16:38:22 +02001776 set_user_nice(current, 19);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001777 while (1) {
Felix Beck772f5472009-06-22 12:08:16 +02001778 if (ap_suspend_flag)
1779 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001780 if (need_resched()) {
1781 schedule();
1782 continue;
1783 }
1784 add_wait_queue(&ap_poll_wait, &wait);
1785 set_current_state(TASK_INTERRUPTIBLE);
1786 if (kthread_should_stop())
1787 break;
1788 requests = atomic_read(&ap_poll_requests);
1789 if (requests <= 0)
1790 schedule();
1791 set_current_state(TASK_RUNNING);
1792 remove_wait_queue(&ap_poll_wait, &wait);
1793
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001794 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001795 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001796 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001797 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001798 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001799 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001800 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001801 spin_unlock_bh(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001802 }
1803 set_current_state(TASK_RUNNING);
1804 remove_wait_queue(&ap_poll_wait, &wait);
1805 return 0;
1806}
1807
1808static int ap_poll_thread_start(void)
1809{
1810 int rc;
1811
Felix Beck772f5472009-06-22 12:08:16 +02001812 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beckcb17a632008-12-25 13:38:41 +01001813 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001814 mutex_lock(&ap_poll_thread_mutex);
1815 if (!ap_poll_kthread) {
1816 ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
Thomas Meyerba8da212013-06-01 11:51:13 +02001817 rc = PTR_RET(ap_poll_kthread);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001818 if (rc)
1819 ap_poll_kthread = NULL;
1820 }
1821 else
1822 rc = 0;
1823 mutex_unlock(&ap_poll_thread_mutex);
1824 return rc;
1825}
1826
1827static void ap_poll_thread_stop(void)
1828{
1829 mutex_lock(&ap_poll_thread_mutex);
1830 if (ap_poll_kthread) {
1831 kthread_stop(ap_poll_kthread);
1832 ap_poll_kthread = NULL;
1833 }
1834 mutex_unlock(&ap_poll_thread_mutex);
1835}
1836
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001837/**
Felix Beck1749a812008-04-17 07:46:28 +02001838 * ap_request_timeout(): Handling of request timeouts
1839 * @data: Holds the AP device.
1840 *
1841 * Handles request timeouts.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001842 */
1843static void ap_request_timeout(unsigned long data)
1844{
1845 struct ap_device *ap_dev = (struct ap_device *) data;
1846
Felix Beckcb17a632008-12-25 13:38:41 +01001847 if (ap_dev->reset == AP_RESET_ARMED) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001848 ap_dev->reset = AP_RESET_DO;
Felix Beckcb17a632008-12-25 13:38:41 +01001849
1850 if (ap_using_interrupts())
1851 tasklet_schedule(&ap_tasklet);
1852 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001853}
1854
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001855static void ap_reset_domain(void)
1856{
1857 int i;
1858
Ralph Wuerthner39aa7cf2007-10-12 16:11:29 +02001859 if (ap_domain_index != -1)
1860 for (i = 0; i < AP_DEVICES; i++)
1861 ap_reset_queue(AP_MKQID(i, ap_domain_index));
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001862}
1863
1864static void ap_reset_all(void)
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001865{
1866 int i, j;
1867
1868 for (i = 0; i < AP_DOMAINS; i++)
1869 for (j = 0; j < AP_DEVICES; j++)
1870 ap_reset_queue(AP_MKQID(j, i));
1871}
1872
1873static struct reset_call ap_reset_call = {
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001874 .fn = ap_reset_all,
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001875};
1876
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001877/**
Felix Beck1749a812008-04-17 07:46:28 +02001878 * ap_module_init(): The module initialization code.
1879 *
1880 * Initializes the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001881 */
1882int __init ap_module_init(void)
1883{
1884 int rc, i;
1885
1886 if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001887 pr_warning("%d is not a valid cryptographic domain\n",
1888 ap_domain_index);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001889 return -EINVAL;
1890 }
Felix Beck5314af62009-09-22 22:58:51 +02001891 /* In resume callback we need to know if the user had set the domain.
1892 * If so, we can not just reset it.
1893 */
1894 if (ap_domain_index >= 0)
1895 user_set_domain = 1;
1896
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001897 if (ap_instructions_available() != 0) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001898 pr_warning("The hardware system does not support "
1899 "AP instructions\n");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001900 return -ENODEV;
1901 }
Felix Beckcb17a632008-12-25 13:38:41 +01001902 if (ap_interrupts_available()) {
Martin Schwidefskyf4eae942013-06-24 10:30:41 +02001903 rc = register_adapter_interrupt(&ap_airq);
1904 ap_airq_flag = (rc == 0);
Felix Beckcb17a632008-12-25 13:38:41 +01001905 }
1906
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001907 register_reset_call(&ap_reset_call);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001908
1909 /* Create /sys/bus/ap. */
1910 rc = bus_register(&ap_bus_type);
1911 if (rc)
1912 goto out;
1913 for (i = 0; ap_bus_attrs[i]; i++) {
1914 rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]);
1915 if (rc)
1916 goto out_bus;
1917 }
1918
1919 /* Create /sys/devices/ap. */
Mark McLoughlin035da162008-12-15 12:58:29 +00001920 ap_root_device = root_device_register("ap");
Thomas Meyerba8da212013-06-01 11:51:13 +02001921 rc = PTR_RET(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001922 if (rc)
1923 goto out_bus;
1924
1925 ap_work_queue = create_singlethread_workqueue("kapwork");
1926 if (!ap_work_queue) {
1927 rc = -ENOMEM;
1928 goto out_root;
1929 }
1930
Holger Dengler75014552012-08-28 16:41:50 +02001931 ap_query_configuration();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001932 if (ap_select_domain() == 0)
1933 ap_scan_bus(NULL);
1934
Felix Beck1749a812008-04-17 07:46:28 +02001935 /* Setup the AP bus rescan timer. */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001936 init_timer(&ap_config_timer);
1937 ap_config_timer.function = ap_config_timeout;
1938 ap_config_timer.data = 0;
1939 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1940 add_timer(&ap_config_timer);
1941
Felix Beckfe137232008-07-14 09:59:08 +02001942 /* Setup the high resultion poll timer.
1943 * If we are running under z/VM adjust polling to z/VM polling rate.
1944 */
1945 if (MACHINE_IS_VM)
1946 poll_timeout = 1500000;
Felix Beck93521312009-12-07 12:52:00 +01001947 spin_lock_init(&ap_poll_timer_lock);
Felix Beckfe137232008-07-14 09:59:08 +02001948 hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1949 ap_poll_timer.function = ap_poll_timeout;
1950
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001951 /* Start the low priority AP bus poll thread. */
1952 if (ap_thread_flag) {
1953 rc = ap_poll_thread_start();
1954 if (rc)
1955 goto out_work;
1956 }
1957
1958 return 0;
1959
1960out_work:
1961 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001962 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001963 destroy_workqueue(ap_work_queue);
1964out_root:
Mark McLoughlin035da162008-12-15 12:58:29 +00001965 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001966out_bus:
1967 while (i--)
1968 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1969 bus_unregister(&ap_bus_type);
1970out:
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001971 unregister_reset_call(&ap_reset_call);
Martin Schwidefskyf4eae942013-06-24 10:30:41 +02001972 if (ap_using_interrupts())
1973 unregister_adapter_interrupt(&ap_airq);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001974 return rc;
1975}
1976
1977static int __ap_match_all(struct device *dev, void *data)
1978{
1979 return 1;
1980}
1981
1982/**
Felix Beck1749a812008-04-17 07:46:28 +02001983 * ap_modules_exit(): The module termination code
1984 *
1985 * Terminates the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001986 */
1987void ap_module_exit(void)
1988{
1989 int i;
1990 struct device *dev;
1991
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001992 ap_reset_domain();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001993 ap_poll_thread_stop();
1994 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001995 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001996 destroy_workqueue(ap_work_queue);
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001997 tasklet_kill(&ap_tasklet);
Mark McLoughlin035da162008-12-15 12:58:29 +00001998 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001999 while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
2000 __ap_match_all)))
2001 {
2002 device_unregister(dev);
2003 put_device(dev);
2004 }
2005 for (i = 0; ap_bus_attrs[i]; i++)
2006 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
2007 bus_unregister(&ap_bus_type);
Ralph Wuerthner85eca852006-12-08 15:54:07 +01002008 unregister_reset_call(&ap_reset_call);
Martin Schwidefskyf4eae942013-06-24 10:30:41 +02002009 if (ap_using_interrupts())
2010 unregister_adapter_interrupt(&ap_airq);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02002011}
2012
Martin Schwidefsky1534c382006-09-20 15:58:25 +02002013module_init(ap_module_init);
2014module_exit(ap_module_exit);