blob: ae258a4b4e5ea8866333fec3204dba7513fbda5c [file] [log] [blame]
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001/*
Heiko Carstensa53c8fa2012-07-20 11:15:04 +02002 * Copyright IBM Corp. 2006
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);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020065
Felix Beck1749a812008-04-17 07:46:28 +020066/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020067 * Module description.
68 */
69MODULE_AUTHOR("IBM Corporation");
70MODULE_DESCRIPTION("Adjunct Processor Bus driver, "
Heiko Carstensa53c8fa2012-07-20 11:15:04 +020071 "Copyright IBM Corp. 2006");
Martin Schwidefsky1534c382006-09-20 15:58:25 +020072MODULE_LICENSE("GPL");
73
Felix Beck1749a812008-04-17 07:46:28 +020074/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020075 * Module parameter
76 */
77int ap_domain_index = -1; /* Adjunct Processor Domain Index */
78module_param_named(domain, ap_domain_index, int, 0000);
79MODULE_PARM_DESC(domain, "domain index for ap devices");
80EXPORT_SYMBOL(ap_domain_index);
81
Felix Beckb90b34c2008-02-09 18:24:30 +010082static int ap_thread_flag = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +020083module_param_named(poll_thread, ap_thread_flag, int, 0000);
Felix Beckb90b34c2008-02-09 18:24:30 +010084MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off).");
Martin Schwidefsky1534c382006-09-20 15:58:25 +020085
86static struct device *ap_root_device = NULL;
Christian Maaser43c207e62008-12-25 13:38:42 +010087static DEFINE_SPINLOCK(ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +010088static LIST_HEAD(ap_device_list);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020089
Felix Beck1749a812008-04-17 07:46:28 +020090/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +020091 * Workqueue & timer for bus rescan.
92 */
93static struct workqueue_struct *ap_work_queue;
94static struct timer_list ap_config_timer;
95static int ap_config_time = AP_CONFIG_TIME;
Al Viro4927b3f2006-12-06 19:18:20 +000096static DECLARE_WORK(ap_config_work, ap_scan_bus);
Martin Schwidefsky1534c382006-09-20 15:58:25 +020097
Felix Beck1749a812008-04-17 07:46:28 +020098/*
Felix Beckcb17a632008-12-25 13:38:41 +010099 * Tasklet & timer for AP request polling and interrupts
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200100 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200101static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0);
102static atomic_t ap_poll_requests = ATOMIC_INIT(0);
103static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
104static struct task_struct *ap_poll_kthread = NULL;
105static DEFINE_MUTEX(ap_poll_thread_mutex);
Felix Beck93521312009-12-07 12:52:00 +0100106static DEFINE_SPINLOCK(ap_poll_timer_lock);
Felix Beckcb17a632008-12-25 13:38:41 +0100107static void *ap_interrupt_indicator;
Felix Beckfe137232008-07-14 09:59:08 +0200108static struct hrtimer ap_poll_timer;
109/* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
110 * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
111static unsigned long long poll_timeout = 250000;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200112
Felix Beck772f5472009-06-22 12:08:16 +0200113/* Suspend flag */
114static int ap_suspend_flag;
Felix Beck5314af62009-09-22 22:58:51 +0200115/* Flag to check if domain was set through module parameter domain=. This is
116 * important when supsend and resume is done in a z/VM environment where the
117 * domain might change. */
118static int user_set_domain = 0;
Felix Beck772f5472009-06-22 12:08:16 +0200119static struct bus_type ap_bus_type;
120
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200121/**
Felix Beckcb17a632008-12-25 13:38:41 +0100122 * ap_using_interrupts() - Returns non-zero if interrupt support is
123 * available.
124 */
125static inline int ap_using_interrupts(void)
126{
127 return ap_interrupt_indicator != NULL;
128}
129
130/**
Felix Beck1749a812008-04-17 07:46:28 +0200131 * ap_intructions_available() - Test if AP instructions are available.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200132 *
Felix Beck1749a812008-04-17 07:46:28 +0200133 * Returns 0 if the AP instructions are installed.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200134 */
135static inline int ap_instructions_available(void)
136{
137 register unsigned long reg0 asm ("0") = AP_MKQID(0,0);
138 register unsigned long reg1 asm ("1") = -ENODEV;
139 register unsigned long reg2 asm ("2") = 0UL;
140
141 asm volatile(
142 " .long 0xb2af0000\n" /* PQAP(TAPQ) */
143 "0: la %1,0\n"
144 "1:\n"
145 EX_TABLE(0b, 1b)
146 : "+d" (reg0), "+d" (reg1), "+d" (reg2) : : "cc" );
147 return reg1;
148}
149
150/**
Felix Beckcb17a632008-12-25 13:38:41 +0100151 * ap_interrupts_available(): Test if AP interrupts are available.
152 *
153 * Returns 1 if AP interrupts are available.
154 */
155static int ap_interrupts_available(void)
156{
Felix Beck53ec24b12011-01-05 12:46:44 +0100157 return test_facility(2) && test_facility(65);
Felix Beckcb17a632008-12-25 13:38:41 +0100158}
159
160/**
Felix Beck1749a812008-04-17 07:46:28 +0200161 * ap_test_queue(): Test adjunct processor queue.
162 * @qid: The AP queue number
163 * @queue_depth: Pointer to queue depth value
164 * @device_type: Pointer to device type value
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200165 *
Felix Beck1749a812008-04-17 07:46:28 +0200166 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200167 */
168static inline struct ap_queue_status
169ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
170{
171 register unsigned long reg0 asm ("0") = qid;
172 register struct ap_queue_status reg1 asm ("1");
173 register unsigned long reg2 asm ("2") = 0UL;
174
175 asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
176 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
177 *device_type = (int) (reg2 >> 24);
178 *queue_depth = (int) (reg2 & 0xff);
179 return reg1;
180}
181
182/**
Felix Beck1749a812008-04-17 07:46:28 +0200183 * ap_reset_queue(): Reset adjunct processor queue.
184 * @qid: The AP queue number
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200185 *
Felix Beck1749a812008-04-17 07:46:28 +0200186 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200187 */
188static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
189{
190 register unsigned long reg0 asm ("0") = qid | 0x01000000UL;
191 register struct ap_queue_status reg1 asm ("1");
192 register unsigned long reg2 asm ("2") = 0UL;
193
194 asm volatile(
195 ".long 0xb2af0000" /* PQAP(RAPQ) */
196 : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
197 return reg1;
198}
199
Felix Beckcb17a632008-12-25 13:38:41 +0100200#ifdef CONFIG_64BIT
201/**
202 * ap_queue_interruption_control(): Enable interruption for a specific AP.
203 * @qid: The AP queue number
204 * @ind: The notification indicator byte
205 *
206 * Returns AP queue status.
207 */
208static inline struct ap_queue_status
209ap_queue_interruption_control(ap_qid_t qid, void *ind)
210{
211 register unsigned long reg0 asm ("0") = qid | 0x03000000UL;
212 register unsigned long reg1_in asm ("1") = 0x0000800000000000UL | AP_ISC;
213 register struct ap_queue_status reg1_out asm ("1");
214 register void *reg2 asm ("2") = ind;
215 asm volatile(
Holger Denglera7475af2012-05-16 14:10:26 +0200216 ".long 0xb2af0000" /* PQAP(AQIC) */
Felix Beckcb17a632008-12-25 13:38:41 +0100217 : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
218 :
219 : "cc" );
220 return reg1_out;
221}
222#endif
223
Holger Dengler6bed05b2011-07-24 10:48:25 +0200224#ifdef CONFIG_64BIT
225static inline struct ap_queue_status
226__ap_query_functions(ap_qid_t qid, unsigned int *functions)
Felix Beckb1f933d2011-01-05 12:47:44 +0100227{
228 register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
Holger Dengler6bed05b2011-07-24 10:48:25 +0200229 register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
230 register unsigned long reg2 asm ("2");
Felix Beckb1f933d2011-01-05 12:47:44 +0100231
232 asm volatile(
Holger Denglera7475af2012-05-16 14:10:26 +0200233 ".long 0xb2af0000\n" /* PQAP(TAPQ) */
Holger Dengler6bed05b2011-07-24 10:48:25 +0200234 "0:\n"
235 EX_TABLE(0b, 0b)
236 : "+d" (reg0), "+d" (reg1), "=d" (reg2)
Felix Beckb1f933d2011-01-05 12:47:44 +0100237 :
238 : "cc");
239
Holger Dengler6bed05b2011-07-24 10:48:25 +0200240 *functions = (unsigned int)(reg2 >> 32);
Felix Beckb1f933d2011-01-05 12:47:44 +0100241 return reg1;
242}
Holger Dengler6bed05b2011-07-24 10:48:25 +0200243#endif
244
245/**
246 * ap_query_functions(): Query supported functions.
247 * @qid: The AP queue number
248 * @functions: Pointer to functions field.
249 *
250 * Returns
251 * 0 on success.
252 * -ENODEV if queue not valid.
253 * -EBUSY if device busy.
254 * -EINVAL if query function is not supported
255 */
256static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
257{
258#ifdef CONFIG_64BIT
259 struct ap_queue_status status;
260 int i;
261 status = __ap_query_functions(qid, functions);
262
263 for (i = 0; i < AP_MAX_RESET; i++) {
264 if (ap_queue_status_invalid_test(&status))
265 return -ENODEV;
266
267 switch (status.response_code) {
268 case AP_RESPONSE_NORMAL:
269 return 0;
270 case AP_RESPONSE_RESET_IN_PROGRESS:
271 case AP_RESPONSE_BUSY:
272 break;
273 case AP_RESPONSE_Q_NOT_AVAIL:
274 case AP_RESPONSE_DECONFIGURED:
275 case AP_RESPONSE_CHECKSTOPPED:
276 case AP_RESPONSE_INVALID_ADDRESS:
277 return -ENODEV;
278 case AP_RESPONSE_OTHERWISE_CHANGED:
279 break;
280 default:
281 break;
282 }
283 if (i < AP_MAX_RESET - 1) {
284 udelay(5);
285 status = __ap_query_functions(qid, functions);
286 }
287 }
288 return -EBUSY;
289#else
290 return -EINVAL;
291#endif
292}
Felix Beckb1f933d2011-01-05 12:47:44 +0100293
294/**
295 * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
296 * support.
297 * @qid: The AP queue number
298 *
299 * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
300 */
301int ap_4096_commands_available(ap_qid_t qid)
302{
Holger Dengler6bed05b2011-07-24 10:48:25 +0200303 unsigned int functions;
Felix Beckb1f933d2011-01-05 12:47:44 +0100304
Holger Dengler6bed05b2011-07-24 10:48:25 +0200305 if (ap_query_functions(qid, &functions))
306 return 0;
307
308 return test_ap_facility(functions, 1) &&
309 test_ap_facility(functions, 2);
Felix Beckb1f933d2011-01-05 12:47:44 +0100310}
311EXPORT_SYMBOL(ap_4096_commands_available);
312
Felix Beckcb17a632008-12-25 13:38:41 +0100313/**
314 * ap_queue_enable_interruption(): Enable interruption on an AP.
315 * @qid: The AP queue number
316 * @ind: the notification indicator byte
317 *
318 * Enables interruption on AP queue via ap_queue_interruption_control(). Based
319 * on the return value it waits a while and tests the AP queue if interrupts
320 * have been switched on using ap_test_queue().
321 */
322static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
323{
324#ifdef CONFIG_64BIT
325 struct ap_queue_status status;
326 int t_depth, t_device_type, rc, i;
327
328 rc = -EBUSY;
329 status = ap_queue_interruption_control(qid, ind);
330
331 for (i = 0; i < AP_MAX_RESET; i++) {
332 switch (status.response_code) {
333 case AP_RESPONSE_NORMAL:
334 if (status.int_enabled)
335 return 0;
336 break;
337 case AP_RESPONSE_RESET_IN_PROGRESS:
338 case AP_RESPONSE_BUSY:
Holger Dengler8738e072012-07-02 12:39:59 +0200339 if (i < AP_MAX_RESET - 1) {
340 udelay(5);
341 status = ap_queue_interruption_control(qid,
342 ind);
343 continue;
344 }
Felix Beckcb17a632008-12-25 13:38:41 +0100345 break;
346 case AP_RESPONSE_Q_NOT_AVAIL:
347 case AP_RESPONSE_DECONFIGURED:
348 case AP_RESPONSE_CHECKSTOPPED:
349 case AP_RESPONSE_INVALID_ADDRESS:
350 return -ENODEV;
351 case AP_RESPONSE_OTHERWISE_CHANGED:
352 if (status.int_enabled)
353 return 0;
354 break;
355 default:
356 break;
357 }
358 if (i < AP_MAX_RESET - 1) {
359 udelay(5);
360 status = ap_test_queue(qid, &t_depth, &t_device_type);
361 }
362 }
363 return rc;
364#else
365 return -EINVAL;
366#endif
367}
368
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200369/**
Felix Beck1749a812008-04-17 07:46:28 +0200370 * __ap_send(): Send message to adjunct processor queue.
371 * @qid: The AP queue number
372 * @psmid: The program supplied message identifier
373 * @msg: The message text
374 * @length: The message length
Felix Becka6a5d732009-12-07 12:51:55 +0100375 * @special: Special Bit
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200376 *
Felix Beck1749a812008-04-17 07:46:28 +0200377 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200378 * Condition code 1 on NQAP can't happen because the L bit is 1.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200379 * Condition code 2 on NQAP also means the send is incomplete,
380 * because a segment boundary was reached. The NQAP is repeated.
381 */
382static inline struct ap_queue_status
Felix Becka6a5d732009-12-07 12:51:55 +0100383__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length,
384 unsigned int special)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200385{
386 typedef struct { char _[length]; } msgblock;
387 register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
388 register struct ap_queue_status reg1 asm ("1");
389 register unsigned long reg2 asm ("2") = (unsigned long) msg;
390 register unsigned long reg3 asm ("3") = (unsigned long) length;
391 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
392 register unsigned long reg5 asm ("5") = (unsigned int) psmid;
393
Felix Becka6a5d732009-12-07 12:51:55 +0100394 if (special == 1)
395 reg0 |= 0x400000UL;
396
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200397 asm volatile (
Holger Denglera7475af2012-05-16 14:10:26 +0200398 "0: .long 0xb2ad0042\n" /* NQAP */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200399 " brc 2,0b"
400 : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
401 : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg)
402 : "cc" );
403 return reg1;
404}
405
406int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
407{
408 struct ap_queue_status status;
409
Felix Becka6a5d732009-12-07 12:51:55 +0100410 status = __ap_send(qid, psmid, msg, length, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200411 switch (status.response_code) {
412 case AP_RESPONSE_NORMAL:
413 return 0;
414 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200415 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200416 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +0100417 case AP_RESPONSE_REQ_FAC_NOT_INST:
418 return -EINVAL;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200419 default: /* Device is gone. */
420 return -ENODEV;
421 }
422}
423EXPORT_SYMBOL(ap_send);
424
Felix Beck1749a812008-04-17 07:46:28 +0200425/**
426 * __ap_recv(): Receive message from adjunct processor queue.
427 * @qid: The AP queue number
428 * @psmid: Pointer to program supplied message identifier
429 * @msg: The message text
430 * @length: The message length
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200431 *
Felix Beck1749a812008-04-17 07:46:28 +0200432 * Returns AP queue status structure.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200433 * Condition code 1 on DQAP means the receive has taken place
434 * but only partially. The response is incomplete, hence the
435 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200436 * Condition code 2 on DQAP also means the receive is incomplete,
437 * this time because a segment boundary was reached. Again, the
438 * DQAP is repeated.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200439 * Note that gpr2 is used by the DQAP instruction to keep track of
440 * any 'residual' length, in case the instruction gets interrupted.
441 * Hence it gets zeroed before the instruction.
442 */
443static inline struct ap_queue_status
444__ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
445{
446 typedef struct { char _[length]; } msgblock;
447 register unsigned long reg0 asm("0") = qid | 0x80000000UL;
448 register struct ap_queue_status reg1 asm ("1");
449 register unsigned long reg2 asm("2") = 0UL;
450 register unsigned long reg4 asm("4") = (unsigned long) msg;
451 register unsigned long reg5 asm("5") = (unsigned long) length;
452 register unsigned long reg6 asm("6") = 0UL;
453 register unsigned long reg7 asm("7") = 0UL;
454
455
456 asm volatile(
Holger Denglera7475af2012-05-16 14:10:26 +0200457 "0: .long 0xb2ae0064\n" /* DQAP */
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200458 " brc 6,0b\n"
459 : "+d" (reg0), "=d" (reg1), "+d" (reg2),
460 "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
461 "=m" (*(msgblock *) msg) : : "cc" );
462 *psmid = (((unsigned long long) reg6) << 32) + reg7;
463 return reg1;
464}
465
466int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
467{
468 struct ap_queue_status status;
469
470 status = __ap_recv(qid, psmid, msg, length);
471 switch (status.response_code) {
472 case AP_RESPONSE_NORMAL:
473 return 0;
474 case AP_RESPONSE_NO_PENDING_REPLY:
475 if (status.queue_empty)
476 return -ENOENT;
477 return -EBUSY;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200478 case AP_RESPONSE_RESET_IN_PROGRESS:
479 return -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200480 default:
481 return -ENODEV;
482 }
483}
484EXPORT_SYMBOL(ap_recv);
485
486/**
Felix Beck1749a812008-04-17 07:46:28 +0200487 * ap_query_queue(): Check if an AP queue is available.
488 * @qid: The AP queue number
489 * @queue_depth: Pointer to queue depth value
490 * @device_type: Pointer to device type value
491 *
492 * The test is repeated for AP_MAX_RESET times.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200493 */
494static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
495{
496 struct ap_queue_status status;
497 int t_depth, t_device_type, rc, i;
498
499 rc = -EBUSY;
500 for (i = 0; i < AP_MAX_RESET; i++) {
501 status = ap_test_queue(qid, &t_depth, &t_device_type);
502 switch (status.response_code) {
503 case AP_RESPONSE_NORMAL:
504 *queue_depth = t_depth + 1;
505 *device_type = t_device_type;
506 rc = 0;
507 break;
508 case AP_RESPONSE_Q_NOT_AVAIL:
509 rc = -ENODEV;
510 break;
511 case AP_RESPONSE_RESET_IN_PROGRESS:
512 break;
513 case AP_RESPONSE_DECONFIGURED:
514 rc = -ENODEV;
515 break;
516 case AP_RESPONSE_CHECKSTOPPED:
517 rc = -ENODEV;
518 break;
Felix Beckcb17a632008-12-25 13:38:41 +0100519 case AP_RESPONSE_INVALID_ADDRESS:
520 rc = -ENODEV;
521 break;
522 case AP_RESPONSE_OTHERWISE_CHANGED:
523 break;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200524 case AP_RESPONSE_BUSY:
525 break;
526 default:
527 BUG();
528 }
529 if (rc != -EBUSY)
530 break;
531 if (i < AP_MAX_RESET - 1)
532 udelay(5);
533 }
534 return rc;
535}
536
537/**
Felix Beck1749a812008-04-17 07:46:28 +0200538 * ap_init_queue(): Reset an AP queue.
539 * @qid: The AP queue number
540 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200541 * Reset an AP queue and wait for it to become available again.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200542 */
543static int ap_init_queue(ap_qid_t qid)
544{
545 struct ap_queue_status status;
546 int rc, dummy, i;
547
548 rc = -ENODEV;
549 status = ap_reset_queue(qid);
550 for (i = 0; i < AP_MAX_RESET; i++) {
551 switch (status.response_code) {
552 case AP_RESPONSE_NORMAL:
553 if (status.queue_empty)
554 rc = 0;
555 break;
556 case AP_RESPONSE_Q_NOT_AVAIL:
557 case AP_RESPONSE_DECONFIGURED:
558 case AP_RESPONSE_CHECKSTOPPED:
559 i = AP_MAX_RESET; /* return with -ENODEV */
560 break;
561 case AP_RESPONSE_RESET_IN_PROGRESS:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200562 rc = -EBUSY;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200563 case AP_RESPONSE_BUSY:
564 default:
565 break;
566 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200567 if (rc != -ENODEV && rc != -EBUSY)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200568 break;
569 if (i < AP_MAX_RESET - 1) {
570 udelay(5);
571 status = ap_test_queue(qid, &dummy, &dummy);
572 }
573 }
Felix Beckcb17a632008-12-25 13:38:41 +0100574 if (rc == 0 && ap_using_interrupts()) {
575 rc = ap_queue_enable_interruption(qid, ap_interrupt_indicator);
576 /* If interruption mode is supported by the machine,
577 * but an AP can not be enabled for interruption then
578 * the AP will be discarded. */
579 if (rc)
580 pr_err("Registering adapter interrupts for "
581 "AP %d failed\n", AP_QID_DEVICE(qid));
582 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200583 return rc;
584}
585
586/**
Felix Beck1749a812008-04-17 07:46:28 +0200587 * ap_increase_queue_count(): Arm request timeout.
588 * @ap_dev: Pointer to an AP device.
589 *
590 * Arm request timeout if an AP device was idle and a new request is submitted.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200591 */
592static void ap_increase_queue_count(struct ap_device *ap_dev)
593{
594 int timeout = ap_dev->drv->request_timeout;
595
596 ap_dev->queue_count++;
597 if (ap_dev->queue_count == 1) {
598 mod_timer(&ap_dev->timeout, jiffies + timeout);
599 ap_dev->reset = AP_RESET_ARMED;
600 }
601}
602
603/**
Felix Beck1749a812008-04-17 07:46:28 +0200604 * ap_decrease_queue_count(): Decrease queue count.
605 * @ap_dev: Pointer to an AP device.
606 *
607 * If AP device is still alive, re-schedule request timeout if there are still
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200608 * pending requests.
609 */
610static void ap_decrease_queue_count(struct ap_device *ap_dev)
611{
612 int timeout = ap_dev->drv->request_timeout;
613
614 ap_dev->queue_count--;
615 if (ap_dev->queue_count > 0)
616 mod_timer(&ap_dev->timeout, jiffies + timeout);
617 else
Felix Beck1749a812008-04-17 07:46:28 +0200618 /*
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200619 * The timeout timer should to be disabled now - since
620 * del_timer_sync() is very expensive, we just tell via the
621 * reset flag to ignore the pending timeout timer.
622 */
623 ap_dev->reset = AP_RESET_IGNORE;
624}
625
Felix Beck1749a812008-04-17 07:46:28 +0200626/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200627 * AP device related attributes.
628 */
629static ssize_t ap_hwtype_show(struct device *dev,
630 struct device_attribute *attr, char *buf)
631{
632 struct ap_device *ap_dev = to_ap_dev(dev);
633 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type);
634}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200635
Christian Maaser43c207e62008-12-25 13:38:42 +0100636static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200637static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr,
638 char *buf)
639{
640 struct ap_device *ap_dev = to_ap_dev(dev);
641 return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth);
642}
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200643
Christian Maaser43c207e62008-12-25 13:38:42 +0100644static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200645static ssize_t ap_request_count_show(struct device *dev,
646 struct device_attribute *attr,
647 char *buf)
648{
649 struct ap_device *ap_dev = to_ap_dev(dev);
650 int rc;
651
652 spin_lock_bh(&ap_dev->lock);
653 rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->total_request_count);
654 spin_unlock_bh(&ap_dev->lock);
655 return rc;
656}
657
658static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL);
659
660static ssize_t ap_modalias_show(struct device *dev,
661 struct device_attribute *attr, char *buf)
662{
663 return sprintf(buf, "ap:t%02X", to_ap_dev(dev)->device_type);
664}
665
666static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL);
667
668static struct attribute *ap_dev_attrs[] = {
669 &dev_attr_hwtype.attr,
670 &dev_attr_depth.attr,
671 &dev_attr_request_count.attr,
672 &dev_attr_modalias.attr,
673 NULL
674};
675static struct attribute_group ap_dev_attr_group = {
676 .attrs = ap_dev_attrs
677};
678
679/**
Felix Beck1749a812008-04-17 07:46:28 +0200680 * ap_bus_match()
681 * @dev: Pointer to device
682 * @drv: Pointer to device_driver
683 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200684 * AP bus driver registration/unregistration.
685 */
686static int ap_bus_match(struct device *dev, struct device_driver *drv)
687{
688 struct ap_device *ap_dev = to_ap_dev(dev);
689 struct ap_driver *ap_drv = to_ap_drv(drv);
690 struct ap_device_id *id;
691
Felix Beck1749a812008-04-17 07:46:28 +0200692 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200693 * Compare device type of the device with the list of
694 * supported types of the device_driver.
695 */
696 for (id = ap_drv->ids; id->match_flags; id++) {
697 if ((id->match_flags & AP_DEVICE_ID_MATCH_DEVICE_TYPE) &&
698 (id->dev_type != ap_dev->device_type))
699 continue;
700 return 1;
701 }
702 return 0;
703}
704
705/**
Felix Beck1749a812008-04-17 07:46:28 +0200706 * ap_uevent(): Uevent function for AP devices.
707 * @dev: Pointer to device
708 * @env: Pointer to kobj_uevent_env
709 *
710 * It sets up a single environment variable DEV_TYPE which contains the
711 * hardware device type.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200712 */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200713static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200714{
715 struct ap_device *ap_dev = to_ap_dev(dev);
Kay Sievers7eff2e72007-08-14 15:15:12 +0200716 int retval = 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200717
718 if (!ap_dev)
719 return -ENODEV;
720
721 /* Set up DEV_TYPE environment variable. */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200722 retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700723 if (retval)
724 return retval;
725
Cornelia Huck66a4263b2006-12-04 15:40:10 +0100726 /* Add MODALIAS= */
Kay Sievers7eff2e72007-08-14 15:15:12 +0200727 retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
Eric Rannaudbf624562007-03-30 22:23:12 -0700728
Eric Rannaudbf624562007-03-30 22:23:12 -0700729 return retval;
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200730}
731
Felix Beck772f5472009-06-22 12:08:16 +0200732static int ap_bus_suspend(struct device *dev, pm_message_t state)
733{
734 struct ap_device *ap_dev = to_ap_dev(dev);
735 unsigned long flags;
736
737 if (!ap_suspend_flag) {
738 ap_suspend_flag = 1;
739
740 /* Disable scanning for devices, thus we do not want to scan
741 * for them after removing.
742 */
743 del_timer_sync(&ap_config_timer);
744 if (ap_work_queue != NULL) {
745 destroy_workqueue(ap_work_queue);
746 ap_work_queue = NULL;
747 }
Felix Beck5314af62009-09-22 22:58:51 +0200748
Felix Beck772f5472009-06-22 12:08:16 +0200749 tasklet_disable(&ap_tasklet);
750 }
751 /* Poll on the device until all requests are finished. */
752 do {
753 flags = 0;
Felix Beck95f15562009-09-11 10:28:51 +0200754 spin_lock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200755 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +0200756 spin_unlock_bh(&ap_dev->lock);
Felix Beck772f5472009-06-22 12:08:16 +0200757 } while ((flags & 1) || (flags & 2));
758
Felix Beck5314af62009-09-22 22:58:51 +0200759 spin_lock_bh(&ap_dev->lock);
760 ap_dev->unregistered = 1;
761 spin_unlock_bh(&ap_dev->lock);
762
Felix Beck772f5472009-06-22 12:08:16 +0200763 return 0;
764}
765
766static int ap_bus_resume(struct device *dev)
767{
768 int rc = 0;
769 struct ap_device *ap_dev = to_ap_dev(dev);
770
771 if (ap_suspend_flag) {
772 ap_suspend_flag = 0;
773 if (!ap_interrupts_available())
774 ap_interrupt_indicator = NULL;
Felix Beck5314af62009-09-22 22:58:51 +0200775 if (!user_set_domain) {
776 ap_domain_index = -1;
777 ap_select_domain();
778 }
Felix Beck772f5472009-06-22 12:08:16 +0200779 init_timer(&ap_config_timer);
780 ap_config_timer.function = ap_config_timeout;
781 ap_config_timer.data = 0;
782 ap_config_timer.expires = jiffies + ap_config_time * HZ;
783 add_timer(&ap_config_timer);
784 ap_work_queue = create_singlethread_workqueue("kapwork");
785 if (!ap_work_queue)
786 return -ENOMEM;
787 tasklet_enable(&ap_tasklet);
788 if (!ap_using_interrupts())
789 ap_schedule_poll_timer();
790 else
791 tasklet_schedule(&ap_tasklet);
792 if (ap_thread_flag)
793 rc = ap_poll_thread_start();
Felix Beck772f5472009-06-22 12:08:16 +0200794 }
Felix Beck5314af62009-09-22 22:58:51 +0200795 if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) {
796 spin_lock_bh(&ap_dev->lock);
797 ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid),
798 ap_domain_index);
799 spin_unlock_bh(&ap_dev->lock);
800 }
801 queue_work(ap_work_queue, &ap_config_work);
Felix Beck772f5472009-06-22 12:08:16 +0200802
803 return rc;
804}
805
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200806static struct bus_type ap_bus_type = {
807 .name = "ap",
808 .match = &ap_bus_match,
809 .uevent = &ap_uevent,
Felix Beck772f5472009-06-22 12:08:16 +0200810 .suspend = ap_bus_suspend,
811 .resume = ap_bus_resume
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200812};
813
814static int ap_device_probe(struct device *dev)
815{
816 struct ap_device *ap_dev = to_ap_dev(dev);
817 struct ap_driver *ap_drv = to_ap_drv(dev->driver);
818 int rc;
819
820 ap_dev->drv = ap_drv;
821 rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100822 if (!rc) {
Christian Maaser43c207e62008-12-25 13:38:42 +0100823 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100824 list_add(&ap_dev->list, &ap_device_list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100825 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100826 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200827 return rc;
828}
829
830/**
Felix Beck1749a812008-04-17 07:46:28 +0200831 * __ap_flush_queue(): Flush requests.
832 * @ap_dev: Pointer to the AP device
833 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200834 * Flush all requests from the request/pending queue of an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200835 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +0100836static void __ap_flush_queue(struct ap_device *ap_dev)
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200837{
838 struct ap_message *ap_msg, *next;
839
840 list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
841 list_del_init(&ap_msg->list);
842 ap_dev->pendingq_count--;
Holger Dengler54a8f562012-05-16 14:08:22 +0200843 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200844 }
845 list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
846 list_del_init(&ap_msg->list);
847 ap_dev->requestq_count--;
Holger Dengler54a8f562012-05-16 14:08:22 +0200848 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200849 }
850}
851
852void ap_flush_queue(struct ap_device *ap_dev)
853{
854 spin_lock_bh(&ap_dev->lock);
855 __ap_flush_queue(ap_dev);
856 spin_unlock_bh(&ap_dev->lock);
857}
858EXPORT_SYMBOL(ap_flush_queue);
859
860static int ap_device_remove(struct device *dev)
861{
862 struct ap_device *ap_dev = to_ap_dev(dev);
863 struct ap_driver *ap_drv = ap_dev->drv;
864
Ralph Wuerthner4e562962006-10-04 20:02:05 +0200865 ap_flush_queue(ap_dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200866 del_timer_sync(&ap_dev->timeout);
Christian Maaser43c207e62008-12-25 13:38:42 +0100867 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +0100868 list_del_init(&ap_dev->list);
Christian Maaser43c207e62008-12-25 13:38:42 +0100869 spin_unlock_bh(&ap_device_list_lock);
Ralph Wuerthnerfaa582c2008-03-05 12:37:13 +0100870 if (ap_drv->remove)
871 ap_drv->remove(ap_dev);
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +0200872 spin_lock_bh(&ap_dev->lock);
873 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
874 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200875 return 0;
876}
877
878int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
879 char *name)
880{
881 struct device_driver *drv = &ap_drv->driver;
882
883 drv->bus = &ap_bus_type;
884 drv->probe = ap_device_probe;
885 drv->remove = ap_device_remove;
886 drv->owner = owner;
887 drv->name = name;
888 return driver_register(drv);
889}
890EXPORT_SYMBOL(ap_driver_register);
891
892void ap_driver_unregister(struct ap_driver *ap_drv)
893{
894 driver_unregister(&ap_drv->driver);
895}
896EXPORT_SYMBOL(ap_driver_unregister);
897
Felix Beck1749a812008-04-17 07:46:28 +0200898/*
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200899 * AP bus attributes.
900 */
901static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
902{
903 return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
904}
905
906static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
907
908static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
909{
910 return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
911}
912
Felix Beckcb17a632008-12-25 13:38:41 +0100913static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
914{
915 return snprintf(buf, PAGE_SIZE, "%d\n",
916 ap_using_interrupts() ? 1 : 0);
917}
918
919static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL);
920
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200921static ssize_t ap_config_time_store(struct bus_type *bus,
922 const char *buf, size_t count)
923{
924 int time;
925
926 if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120)
927 return -EINVAL;
928 ap_config_time = time;
929 if (!timer_pending(&ap_config_timer) ||
930 !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) {
931 ap_config_timer.expires = jiffies + ap_config_time * HZ;
932 add_timer(&ap_config_timer);
933 }
934 return count;
935}
936
937static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store);
938
939static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf)
940{
941 return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
942}
943
944static ssize_t ap_poll_thread_store(struct bus_type *bus,
945 const char *buf, size_t count)
946{
947 int flag, rc;
948
949 if (sscanf(buf, "%d\n", &flag) != 1)
950 return -EINVAL;
951 if (flag) {
952 rc = ap_poll_thread_start();
953 if (rc)
954 return rc;
955 }
956 else
957 ap_poll_thread_stop();
958 return count;
959}
960
961static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
962
Felix Beckfe137232008-07-14 09:59:08 +0200963static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
964{
965 return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
966}
967
968static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
969 size_t count)
970{
971 unsigned long long time;
972 ktime_t hr_time;
973
974 /* 120 seconds = maximum poll interval */
Felix Beckcb17a632008-12-25 13:38:41 +0100975 if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 ||
976 time > 120000000000ULL)
Felix Beckfe137232008-07-14 09:59:08 +0200977 return -EINVAL;
978 poll_timeout = time;
979 hr_time = ktime_set(0, poll_timeout);
980
981 if (!hrtimer_is_queued(&ap_poll_timer) ||
Arjan van de Ven6c644ea2008-09-01 15:20:30 -0700982 !hrtimer_forward(&ap_poll_timer, hrtimer_get_expires(&ap_poll_timer), hr_time)) {
983 hrtimer_set_expires(&ap_poll_timer, hr_time);
984 hrtimer_start_expires(&ap_poll_timer, HRTIMER_MODE_ABS);
Felix Beckfe137232008-07-14 09:59:08 +0200985 }
986 return count;
987}
988
989static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
990
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200991static struct bus_attribute *const ap_bus_attrs[] = {
992 &bus_attr_ap_domain,
993 &bus_attr_config_time,
994 &bus_attr_poll_thread,
Felix Beckcb17a632008-12-25 13:38:41 +0100995 &bus_attr_ap_interrupts,
Felix Beckfe137232008-07-14 09:59:08 +0200996 &bus_attr_poll_timeout,
997 NULL,
Martin Schwidefsky1534c382006-09-20 15:58:25 +0200998};
999
1000/**
Felix Beck1749a812008-04-17 07:46:28 +02001001 * ap_select_domain(): Select an AP domain.
1002 *
1003 * Pick one of the 16 AP domains.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001004 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001005static int ap_select_domain(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001006{
1007 int queue_depth, device_type, count, max_count, best_domain;
1008 int rc, i, j;
1009
Felix Beck1749a812008-04-17 07:46:28 +02001010 /*
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001011 * We want to use a single domain. Either the one specified with
1012 * the "domain=" parameter or the domain with the maximum number
1013 * of devices.
1014 */
1015 if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS)
1016 /* Domain has already been selected. */
1017 return 0;
1018 best_domain = -1;
1019 max_count = 0;
1020 for (i = 0; i < AP_DOMAINS; i++) {
1021 count = 0;
1022 for (j = 0; j < AP_DEVICES; j++) {
1023 ap_qid_t qid = AP_MKQID(j, i);
1024 rc = ap_query_queue(qid, &queue_depth, &device_type);
1025 if (rc)
1026 continue;
1027 count++;
1028 }
1029 if (count > max_count) {
1030 max_count = count;
1031 best_domain = i;
1032 }
1033 }
1034 if (best_domain >= 0){
1035 ap_domain_index = best_domain;
1036 return 0;
1037 }
1038 return -ENODEV;
1039}
1040
1041/**
Felix Beck1749a812008-04-17 07:46:28 +02001042 * ap_probe_device_type(): Find the device type of an AP.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001043 * @ap_dev: pointer to the AP device.
Felix Beck1749a812008-04-17 07:46:28 +02001044 *
1045 * Find the device type if query queue returned a device type of 0.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001046 */
1047static int ap_probe_device_type(struct ap_device *ap_dev)
1048{
1049 static unsigned char msg[] = {
1050 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
1051 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1052 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
1053 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1054 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50,
1055 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,
1056 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00,
1057 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,
1058 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1059 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,
1060 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1061 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,
1062 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00,
1063 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1064 0x00,0x00,0x00,0x00,0xb8,0x05,0x00,0x00,
1065 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1066 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1067 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1068 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1069 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1070 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1071 0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,
1072 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1073 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
1074 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20,
1075 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,
1076 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22,
1077 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1078 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,
1079 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,
1080 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,
1081 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,
1082 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,
1083 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,
1084 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00,
1085 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,
1086 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01,
1087 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,
1088 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68,
1089 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,
1090 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0,
1091 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,
1092 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04,
1093 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,
1094 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d,
1095 };
1096 struct ap_queue_status status;
1097 unsigned long long psmid;
1098 char *reply;
1099 int rc, i;
1100
1101 reply = (void *) get_zeroed_page(GFP_KERNEL);
1102 if (!reply) {
1103 rc = -ENOMEM;
1104 goto out;
1105 }
1106
1107 status = __ap_send(ap_dev->qid, 0x0102030405060708ULL,
Felix Becka6a5d732009-12-07 12:51:55 +01001108 msg, sizeof(msg), 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001109 if (status.response_code != AP_RESPONSE_NORMAL) {
1110 rc = -ENODEV;
1111 goto out_free;
1112 }
1113
1114 /* Wait for the test message to complete. */
1115 for (i = 0; i < 6; i++) {
1116 mdelay(300);
1117 status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
1118 if (status.response_code == AP_RESPONSE_NORMAL &&
1119 psmid == 0x0102030405060708ULL)
1120 break;
1121 }
1122 if (i < 6) {
1123 /* Got an answer. */
1124 if (reply[0] == 0x00 && reply[1] == 0x86)
1125 ap_dev->device_type = AP_DEVICE_TYPE_PCICC;
1126 else
1127 ap_dev->device_type = AP_DEVICE_TYPE_PCICA;
1128 rc = 0;
1129 } else
1130 rc = -ENODEV;
1131
1132out_free:
1133 free_page((unsigned long) reply);
1134out:
1135 return rc;
1136}
1137
Felix Beckcb17a632008-12-25 13:38:41 +01001138static void ap_interrupt_handler(void *unused1, void *unused2)
1139{
Holger Dengler62d146f2011-01-05 12:47:38 +01001140 kstat_cpu(smp_processor_id()).irqs[IOINT_APB]++;
Felix Beckcb17a632008-12-25 13:38:41 +01001141 tasklet_schedule(&ap_tasklet);
1142}
1143
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001144/**
Felix Beck1749a812008-04-17 07:46:28 +02001145 * __ap_scan_bus(): Scan the AP bus.
1146 * @dev: Pointer to device
1147 * @data: Pointer to data
1148 *
1149 * Scan the AP bus for new devices.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001150 */
1151static int __ap_scan_bus(struct device *dev, void *data)
1152{
1153 return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data;
1154}
1155
1156static void ap_device_release(struct device *dev)
1157{
1158 struct ap_device *ap_dev = to_ap_dev(dev);
1159
1160 kfree(ap_dev);
1161}
1162
Al Viro4927b3f2006-12-06 19:18:20 +00001163static void ap_scan_bus(struct work_struct *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001164{
1165 struct ap_device *ap_dev;
1166 struct device *dev;
1167 ap_qid_t qid;
1168 int queue_depth, device_type;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001169 unsigned int device_functions;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001170 int rc, i;
1171
1172 if (ap_select_domain() != 0)
1173 return;
1174 for (i = 0; i < AP_DEVICES; i++) {
1175 qid = AP_MKQID(i, ap_domain_index);
1176 dev = bus_find_device(&ap_bus_type, NULL,
1177 (void *)(unsigned long)qid,
1178 __ap_scan_bus);
Ralph Wuerthnerf3b017d2006-10-27 12:39:26 +02001179 rc = ap_query_queue(qid, &queue_depth, &device_type);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001180 if (dev) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001181 if (rc == -EBUSY) {
1182 set_current_state(TASK_UNINTERRUPTIBLE);
1183 schedule_timeout(AP_RESET_TIMEOUT);
1184 rc = ap_query_queue(qid, &queue_depth,
1185 &device_type);
1186 }
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001187 ap_dev = to_ap_dev(dev);
1188 spin_lock_bh(&ap_dev->lock);
1189 if (rc || ap_dev->unregistered) {
1190 spin_unlock_bh(&ap_dev->lock);
Felix Beck5314af62009-09-22 22:58:51 +02001191 if (ap_dev->unregistered)
1192 i--;
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001193 device_unregister(dev);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001194 put_device(dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001195 continue;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001196 }
1197 spin_unlock_bh(&ap_dev->lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001198 put_device(dev);
1199 continue;
1200 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001201 if (rc)
1202 continue;
1203 rc = ap_init_queue(qid);
1204 if (rc)
1205 continue;
1206 ap_dev = kzalloc(sizeof(*ap_dev), GFP_KERNEL);
1207 if (!ap_dev)
1208 break;
1209 ap_dev->qid = qid;
1210 ap_dev->queue_depth = queue_depth;
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001211 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001212 spin_lock_init(&ap_dev->lock);
1213 INIT_LIST_HEAD(&ap_dev->pendingq);
1214 INIT_LIST_HEAD(&ap_dev->requestq);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001215 INIT_LIST_HEAD(&ap_dev->list);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001216 setup_timer(&ap_dev->timeout, ap_request_timeout,
1217 (unsigned long) ap_dev);
Holger Dengler6bed05b2011-07-24 10:48:25 +02001218 switch (device_type) {
1219 case 0:
Holger Denglercf2d0072011-05-23 10:24:30 +02001220 if (ap_probe_device_type(ap_dev)) {
1221 kfree(ap_dev);
1222 continue;
1223 }
Holger Dengler6bed05b2011-07-24 10:48:25 +02001224 break;
1225 case 10:
1226 if (ap_query_functions(qid, &device_functions)) {
1227 kfree(ap_dev);
1228 continue;
1229 }
1230 if (test_ap_facility(device_functions, 3))
1231 ap_dev->device_type = AP_DEVICE_TYPE_CEX3C;
1232 else if (test_ap_facility(device_functions, 4))
1233 ap_dev->device_type = AP_DEVICE_TYPE_CEX3A;
1234 else {
1235 kfree(ap_dev);
1236 continue;
1237 }
1238 break;
1239 default:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001240 ap_dev->device_type = device_type;
Holger Dengler6bed05b2011-07-24 10:48:25 +02001241 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001242
1243 ap_dev->device.bus = &ap_bus_type;
1244 ap_dev->device.parent = ap_root_device;
Felix Beckedc44fa2009-09-11 10:28:52 +02001245 if (dev_set_name(&ap_dev->device, "card%02x",
1246 AP_QID_DEVICE(ap_dev->qid))) {
1247 kfree(ap_dev);
1248 continue;
1249 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001250 ap_dev->device.release = ap_device_release;
1251 rc = device_register(&ap_dev->device);
1252 if (rc) {
Sebastian Ottc6304932009-09-11 10:28:38 +02001253 put_device(&ap_dev->device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001254 continue;
1255 }
1256 /* Add device attributes. */
1257 rc = sysfs_create_group(&ap_dev->device.kobj,
1258 &ap_dev_attr_group);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001259 if (!rc) {
1260 spin_lock_bh(&ap_dev->lock);
1261 ap_dev->unregistered = 0;
1262 spin_unlock_bh(&ap_dev->lock);
1263 }
1264 else
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001265 device_unregister(&ap_dev->device);
1266 }
1267}
1268
1269static void
1270ap_config_timeout(unsigned long ptr)
1271{
1272 queue_work(ap_work_queue, &ap_config_work);
1273 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1274 add_timer(&ap_config_timer);
1275}
1276
1277/**
Holger Denglerbc615de2011-11-14 11:19:04 +01001278 * __ap_schedule_poll_timer(): Schedule poll timer.
Felix Beck1749a812008-04-17 07:46:28 +02001279 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001280 * Set up the timer to run the poll tasklet
1281 */
Holger Denglerbc615de2011-11-14 11:19:04 +01001282static inline void __ap_schedule_poll_timer(void)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001283{
Felix Beck8d406c62009-07-24 12:39:53 +02001284 ktime_t hr_time;
Felix Beck93521312009-12-07 12:52:00 +01001285
1286 spin_lock_bh(&ap_poll_timer_lock);
Holger Denglerbc615de2011-11-14 11:19:04 +01001287 if (hrtimer_is_queued(&ap_poll_timer) || ap_suspend_flag)
Felix Beck93521312009-12-07 12:52:00 +01001288 goto out;
Felix Beck8d406c62009-07-24 12:39:53 +02001289 if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
1290 hr_time = ktime_set(0, poll_timeout);
1291 hrtimer_forward_now(&ap_poll_timer, hr_time);
1292 hrtimer_restart(&ap_poll_timer);
1293 }
Felix Beck93521312009-12-07 12:52:00 +01001294out:
1295 spin_unlock_bh(&ap_poll_timer_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001296}
1297
1298/**
Holger Denglerbc615de2011-11-14 11:19:04 +01001299 * ap_schedule_poll_timer(): Schedule poll timer.
1300 *
1301 * Set up the timer to run the poll tasklet
1302 */
1303static inline void ap_schedule_poll_timer(void)
1304{
1305 if (ap_using_interrupts())
1306 return;
1307 __ap_schedule_poll_timer();
1308}
1309
1310/**
Felix Beck1749a812008-04-17 07:46:28 +02001311 * ap_poll_read(): Receive pending reply messages from an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001312 * @ap_dev: pointer to the AP device
1313 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1314 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001315 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001316 * Returns 0 if the device is still present, -ENODEV if not.
1317 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001318static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001319{
1320 struct ap_queue_status status;
1321 struct ap_message *ap_msg;
1322
1323 if (ap_dev->queue_count <= 0)
1324 return 0;
1325 status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid,
1326 ap_dev->reply->message, ap_dev->reply->length);
1327 switch (status.response_code) {
1328 case AP_RESPONSE_NORMAL:
1329 atomic_dec(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001330 ap_decrease_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001331 list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
1332 if (ap_msg->psmid != ap_dev->reply->psmid)
1333 continue;
1334 list_del_init(&ap_msg->list);
1335 ap_dev->pendingq_count--;
Holger Dengler54a8f562012-05-16 14:08:22 +02001336 ap_msg->receive(ap_dev, ap_msg, ap_dev->reply);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001337 break;
1338 }
1339 if (ap_dev->queue_count > 0)
1340 *flags |= 1;
1341 break;
1342 case AP_RESPONSE_NO_PENDING_REPLY:
1343 if (status.queue_empty) {
1344 /* The card shouldn't forget requests but who knows. */
Ralph Wuerthnere675c0d2007-03-26 20:42:43 +02001345 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001346 ap_dev->queue_count = 0;
1347 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1348 ap_dev->requestq_count += ap_dev->pendingq_count;
1349 ap_dev->pendingq_count = 0;
1350 } else
1351 *flags |= 2;
1352 break;
1353 default:
1354 return -ENODEV;
1355 }
1356 return 0;
1357}
1358
1359/**
Felix Beck1749a812008-04-17 07:46:28 +02001360 * ap_poll_write(): Send messages from the request queue to an AP device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001361 * @ap_dev: pointer to the AP device
1362 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1363 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001364 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001365 * Returns 0 if the device is still present, -ENODEV if not.
1366 */
Heiko Carstens4d284ca2007-02-05 21:18:53 +01001367static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001368{
1369 struct ap_queue_status status;
1370 struct ap_message *ap_msg;
1371
1372 if (ap_dev->requestq_count <= 0 ||
1373 ap_dev->queue_count >= ap_dev->queue_depth)
1374 return 0;
1375 /* Start the next request on the queue. */
1376 ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list);
1377 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001378 ap_msg->message, ap_msg->length, ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001379 switch (status.response_code) {
1380 case AP_RESPONSE_NORMAL:
1381 atomic_inc(&ap_poll_requests);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001382 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001383 list_move_tail(&ap_msg->list, &ap_dev->pendingq);
1384 ap_dev->requestq_count--;
1385 ap_dev->pendingq_count++;
1386 if (ap_dev->queue_count < ap_dev->queue_depth &&
1387 ap_dev->requestq_count > 0)
1388 *flags |= 1;
1389 *flags |= 2;
1390 break;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001391 case AP_RESPONSE_RESET_IN_PROGRESS:
Holger Denglerbc615de2011-11-14 11:19:04 +01001392 __ap_schedule_poll_timer();
1393 case AP_RESPONSE_Q_FULL:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001394 *flags |= 2;
1395 break;
1396 case AP_RESPONSE_MESSAGE_TOO_BIG:
Felix Becka6a5d732009-12-07 12:51:55 +01001397 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001398 return -EINVAL;
1399 default:
1400 return -ENODEV;
1401 }
1402 return 0;
1403}
1404
1405/**
Felix Beck1749a812008-04-17 07:46:28 +02001406 * ap_poll_queue(): Poll AP device for pending replies and send new messages.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001407 * @ap_dev: pointer to the bus device
1408 * @flags: pointer to control flags, bit 2^0 is set if another poll is
1409 * required, bit 2^1 is set if the poll timer needs to get armed
Felix Beck1749a812008-04-17 07:46:28 +02001410 *
1411 * Poll AP device for pending replies and send new messages. If either
1412 * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001413 * Returns 0.
1414 */
1415static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
1416{
1417 int rc;
1418
1419 rc = ap_poll_read(ap_dev, flags);
1420 if (rc)
1421 return rc;
1422 return ap_poll_write(ap_dev, flags);
1423}
1424
1425/**
Felix Beck1749a812008-04-17 07:46:28 +02001426 * __ap_queue_message(): Queue a message to a device.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001427 * @ap_dev: pointer to the AP device
1428 * @ap_msg: the message to be queued
Felix Beck1749a812008-04-17 07:46:28 +02001429 *
1430 * Queue a message to a device. Returns 0 if successful.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001431 */
1432static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1433{
1434 struct ap_queue_status status;
1435
1436 if (list_empty(&ap_dev->requestq) &&
1437 ap_dev->queue_count < ap_dev->queue_depth) {
1438 status = __ap_send(ap_dev->qid, ap_msg->psmid,
Felix Becka6a5d732009-12-07 12:51:55 +01001439 ap_msg->message, ap_msg->length,
1440 ap_msg->special);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001441 switch (status.response_code) {
1442 case AP_RESPONSE_NORMAL:
1443 list_add_tail(&ap_msg->list, &ap_dev->pendingq);
1444 atomic_inc(&ap_poll_requests);
1445 ap_dev->pendingq_count++;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001446 ap_increase_queue_count(ap_dev);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001447 ap_dev->total_request_count++;
1448 break;
1449 case AP_RESPONSE_Q_FULL:
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001450 case AP_RESPONSE_RESET_IN_PROGRESS:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001451 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1452 ap_dev->requestq_count++;
1453 ap_dev->total_request_count++;
1454 return -EBUSY;
Felix Becka6a5d732009-12-07 12:51:55 +01001455 case AP_RESPONSE_REQ_FAC_NOT_INST:
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001456 case AP_RESPONSE_MESSAGE_TOO_BIG:
Holger Dengler54a8f562012-05-16 14:08:22 +02001457 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001458 return -EINVAL;
1459 default: /* Device is gone. */
Holger Dengler54a8f562012-05-16 14:08:22 +02001460 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001461 return -ENODEV;
1462 }
1463 } else {
1464 list_add_tail(&ap_msg->list, &ap_dev->requestq);
1465 ap_dev->requestq_count++;
1466 ap_dev->total_request_count++;
1467 return -EBUSY;
1468 }
1469 ap_schedule_poll_timer();
1470 return 0;
1471}
1472
1473void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1474{
1475 unsigned long flags;
1476 int rc;
1477
Holger Dengler54a8f562012-05-16 14:08:22 +02001478 /* For asynchronous message handling a valid receive-callback
1479 * is required. */
1480 BUG_ON(!ap_msg->receive);
1481
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001482 spin_lock_bh(&ap_dev->lock);
1483 if (!ap_dev->unregistered) {
1484 /* Make room on the queue by polling for finished requests. */
1485 rc = ap_poll_queue(ap_dev, &flags);
1486 if (!rc)
1487 rc = __ap_queue_message(ap_dev, ap_msg);
1488 if (!rc)
1489 wake_up(&ap_poll_wait);
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001490 if (rc == -ENODEV)
1491 ap_dev->unregistered = 1;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001492 } else {
Holger Dengler54a8f562012-05-16 14:08:22 +02001493 ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001494 rc = -ENODEV;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001495 }
1496 spin_unlock_bh(&ap_dev->lock);
1497 if (rc == -ENODEV)
1498 device_unregister(&ap_dev->device);
1499}
1500EXPORT_SYMBOL(ap_queue_message);
1501
1502/**
Felix Beck1749a812008-04-17 07:46:28 +02001503 * ap_cancel_message(): Cancel a crypto request.
1504 * @ap_dev: The AP device that has the message queued
1505 * @ap_msg: The message that is to be removed
1506 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001507 * Cancel a crypto request. This is done by removing the request
Felix Beck1749a812008-04-17 07:46:28 +02001508 * from the device pending or request queue. Note that the
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001509 * request stays on the AP queue. When it finishes the message
1510 * reply will be discarded because the psmid can't be found.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001511 */
1512void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
1513{
1514 struct ap_message *tmp;
1515
1516 spin_lock_bh(&ap_dev->lock);
1517 if (!list_empty(&ap_msg->list)) {
1518 list_for_each_entry(tmp, &ap_dev->pendingq, list)
1519 if (tmp->psmid == ap_msg->psmid) {
1520 ap_dev->pendingq_count--;
1521 goto found;
1522 }
1523 ap_dev->requestq_count--;
1524 found:
1525 list_del_init(&ap_msg->list);
1526 }
1527 spin_unlock_bh(&ap_dev->lock);
1528}
1529EXPORT_SYMBOL(ap_cancel_message);
1530
1531/**
Felix Beck1749a812008-04-17 07:46:28 +02001532 * ap_poll_timeout(): AP receive polling for finished AP requests.
Felix Beckfe137232008-07-14 09:59:08 +02001533 * @unused: Unused pointer.
Felix Beck1749a812008-04-17 07:46:28 +02001534 *
Felix Beckfe137232008-07-14 09:59:08 +02001535 * Schedules the AP tasklet using a high resolution timer.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001536 */
Felix Beckfe137232008-07-14 09:59:08 +02001537static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001538{
1539 tasklet_schedule(&ap_tasklet);
Felix Beckfe137232008-07-14 09:59:08 +02001540 return HRTIMER_NORESTART;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001541}
1542
1543/**
Felix Beck1749a812008-04-17 07:46:28 +02001544 * ap_reset(): Reset a not responding AP device.
1545 * @ap_dev: Pointer to the AP device
1546 *
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001547 * Reset a not responding AP device and move all requests from the
1548 * pending queue to the request queue.
1549 */
1550static void ap_reset(struct ap_device *ap_dev)
1551{
1552 int rc;
1553
1554 ap_dev->reset = AP_RESET_IGNORE;
1555 atomic_sub(ap_dev->queue_count, &ap_poll_requests);
1556 ap_dev->queue_count = 0;
1557 list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
1558 ap_dev->requestq_count += ap_dev->pendingq_count;
1559 ap_dev->pendingq_count = 0;
1560 rc = ap_init_queue(ap_dev->qid);
1561 if (rc == -ENODEV)
1562 ap_dev->unregistered = 1;
Holger Dengler75464962011-12-01 13:32:23 +01001563 else
1564 __ap_schedule_poll_timer();
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001565}
1566
Christian Maaser43c207e62008-12-25 13:38:42 +01001567static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags)
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001568{
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001569 if (!ap_dev->unregistered) {
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001570 if (ap_poll_queue(ap_dev, flags))
Ralph Wuerthner4e562962006-10-04 20:02:05 +02001571 ap_dev->unregistered = 1;
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001572 if (ap_dev->reset == AP_RESET_DO)
1573 ap_reset(ap_dev);
Ralph Wuerthnerc6a48262007-03-26 20:42:42 +02001574 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001575 return 0;
1576}
1577
Felix Beck1749a812008-04-17 07:46:28 +02001578/**
1579 * ap_poll_all(): Poll all AP devices.
1580 * @dummy: Unused variable
1581 *
1582 * Poll all AP devices on the bus in a round robin fashion. Continue
1583 * polling until bit 2^0 of the control flags is not set. If bit 2^1
1584 * of the control flags has been set arm the poll timer.
1585 */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001586static void ap_poll_all(unsigned long dummy)
1587{
1588 unsigned long flags;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001589 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001590
Felix Beckcb17a632008-12-25 13:38:41 +01001591 /* Reset the indicator if interrupts are used. Thus new interrupts can
1592 * be received. Doing it in the beginning of the tasklet is therefor
1593 * important that no requests on any AP get lost.
1594 */
1595 if (ap_using_interrupts())
1596 xchg((u8 *)ap_interrupt_indicator, 0);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001597 do {
1598 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001599 spin_lock(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001600 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001601 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001602 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001603 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001604 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001605 spin_unlock(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001606 } while (flags & 1);
1607 if (flags & 2)
1608 ap_schedule_poll_timer();
1609}
1610
1611/**
Felix Beck1749a812008-04-17 07:46:28 +02001612 * ap_poll_thread(): Thread that polls for finished requests.
1613 * @data: Unused pointer
1614 *
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001615 * AP bus poll thread. The purpose of this thread is to poll for
1616 * finished requests in a loop if there is a "free" cpu - that is
1617 * a cpu that doesn't have anything better to do. The polling stops
1618 * as soon as there is another task or if all messages have been
1619 * delivered.
1620 */
1621static int ap_poll_thread(void *data)
1622{
1623 DECLARE_WAITQUEUE(wait, current);
1624 unsigned long flags;
1625 int requests;
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001626 struct ap_device *ap_dev;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001627
Christian Borntraegerd83682b2006-10-06 16:38:22 +02001628 set_user_nice(current, 19);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001629 while (1) {
Felix Beck772f5472009-06-22 12:08:16 +02001630 if (ap_suspend_flag)
1631 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001632 if (need_resched()) {
1633 schedule();
1634 continue;
1635 }
1636 add_wait_queue(&ap_poll_wait, &wait);
1637 set_current_state(TASK_INTERRUPTIBLE);
1638 if (kthread_should_stop())
1639 break;
1640 requests = atomic_read(&ap_poll_requests);
1641 if (requests <= 0)
1642 schedule();
1643 set_current_state(TASK_RUNNING);
1644 remove_wait_queue(&ap_poll_wait, &wait);
1645
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001646 flags = 0;
Christian Maaser43c207e62008-12-25 13:38:42 +01001647 spin_lock_bh(&ap_device_list_lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001648 list_for_each_entry(ap_dev, &ap_device_list, list) {
Felix Beck95f15562009-09-11 10:28:51 +02001649 spin_lock(&ap_dev->lock);
Christian Maaser43c207e62008-12-25 13:38:42 +01001650 __ap_poll_device(ap_dev, &flags);
Felix Beck95f15562009-09-11 10:28:51 +02001651 spin_unlock(&ap_dev->lock);
Ralph Wuerthnercf352ce2007-03-19 13:19:14 +01001652 }
Christian Maaser43c207e62008-12-25 13:38:42 +01001653 spin_unlock_bh(&ap_device_list_lock);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001654 }
1655 set_current_state(TASK_RUNNING);
1656 remove_wait_queue(&ap_poll_wait, &wait);
1657 return 0;
1658}
1659
1660static int ap_poll_thread_start(void)
1661{
1662 int rc;
1663
Felix Beck772f5472009-06-22 12:08:16 +02001664 if (ap_using_interrupts() || ap_suspend_flag)
Felix Beckcb17a632008-12-25 13:38:41 +01001665 return 0;
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001666 mutex_lock(&ap_poll_thread_mutex);
1667 if (!ap_poll_kthread) {
1668 ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll");
1669 rc = IS_ERR(ap_poll_kthread) ? PTR_ERR(ap_poll_kthread) : 0;
1670 if (rc)
1671 ap_poll_kthread = NULL;
1672 }
1673 else
1674 rc = 0;
1675 mutex_unlock(&ap_poll_thread_mutex);
1676 return rc;
1677}
1678
1679static void ap_poll_thread_stop(void)
1680{
1681 mutex_lock(&ap_poll_thread_mutex);
1682 if (ap_poll_kthread) {
1683 kthread_stop(ap_poll_kthread);
1684 ap_poll_kthread = NULL;
1685 }
1686 mutex_unlock(&ap_poll_thread_mutex);
1687}
1688
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001689/**
Felix Beck1749a812008-04-17 07:46:28 +02001690 * ap_request_timeout(): Handling of request timeouts
1691 * @data: Holds the AP device.
1692 *
1693 * Handles request timeouts.
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001694 */
1695static void ap_request_timeout(unsigned long data)
1696{
1697 struct ap_device *ap_dev = (struct ap_device *) data;
1698
Felix Beckcb17a632008-12-25 13:38:41 +01001699 if (ap_dev->reset == AP_RESET_ARMED) {
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001700 ap_dev->reset = AP_RESET_DO;
Felix Beckcb17a632008-12-25 13:38:41 +01001701
1702 if (ap_using_interrupts())
1703 tasklet_schedule(&ap_tasklet);
1704 }
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +02001705}
1706
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001707static void ap_reset_domain(void)
1708{
1709 int i;
1710
Ralph Wuerthner39aa7cf2007-10-12 16:11:29 +02001711 if (ap_domain_index != -1)
1712 for (i = 0; i < AP_DEVICES; i++)
1713 ap_reset_queue(AP_MKQID(i, ap_domain_index));
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001714}
1715
1716static void ap_reset_all(void)
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001717{
1718 int i, j;
1719
1720 for (i = 0; i < AP_DOMAINS; i++)
1721 for (j = 0; j < AP_DEVICES; j++)
1722 ap_reset_queue(AP_MKQID(j, i));
1723}
1724
1725static struct reset_call ap_reset_call = {
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001726 .fn = ap_reset_all,
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001727};
1728
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001729/**
Felix Beck1749a812008-04-17 07:46:28 +02001730 * ap_module_init(): The module initialization code.
1731 *
1732 * Initializes the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001733 */
1734int __init ap_module_init(void)
1735{
1736 int rc, i;
1737
1738 if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001739 pr_warning("%d is not a valid cryptographic domain\n",
1740 ap_domain_index);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001741 return -EINVAL;
1742 }
Felix Beck5314af62009-09-22 22:58:51 +02001743 /* In resume callback we need to know if the user had set the domain.
1744 * If so, we can not just reset it.
1745 */
1746 if (ap_domain_index >= 0)
1747 user_set_domain = 1;
1748
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001749 if (ap_instructions_available() != 0) {
Martin Schwidefsky136f7a12008-12-25 13:39:46 +01001750 pr_warning("The hardware system does not support "
1751 "AP instructions\n");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001752 return -ENODEV;
1753 }
Felix Beckcb17a632008-12-25 13:38:41 +01001754 if (ap_interrupts_available()) {
1755 isc_register(AP_ISC);
1756 ap_interrupt_indicator = s390_register_adapter_interrupt(
1757 &ap_interrupt_handler, NULL, AP_ISC);
1758 if (IS_ERR(ap_interrupt_indicator)) {
1759 ap_interrupt_indicator = NULL;
1760 isc_unregister(AP_ISC);
1761 }
1762 }
1763
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001764 register_reset_call(&ap_reset_call);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001765
1766 /* Create /sys/bus/ap. */
1767 rc = bus_register(&ap_bus_type);
1768 if (rc)
1769 goto out;
1770 for (i = 0; ap_bus_attrs[i]; i++) {
1771 rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]);
1772 if (rc)
1773 goto out_bus;
1774 }
1775
1776 /* Create /sys/devices/ap. */
Mark McLoughlin035da162008-12-15 12:58:29 +00001777 ap_root_device = root_device_register("ap");
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001778 rc = IS_ERR(ap_root_device) ? PTR_ERR(ap_root_device) : 0;
1779 if (rc)
1780 goto out_bus;
1781
1782 ap_work_queue = create_singlethread_workqueue("kapwork");
1783 if (!ap_work_queue) {
1784 rc = -ENOMEM;
1785 goto out_root;
1786 }
1787
1788 if (ap_select_domain() == 0)
1789 ap_scan_bus(NULL);
1790
Felix Beck1749a812008-04-17 07:46:28 +02001791 /* Setup the AP bus rescan timer. */
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001792 init_timer(&ap_config_timer);
1793 ap_config_timer.function = ap_config_timeout;
1794 ap_config_timer.data = 0;
1795 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1796 add_timer(&ap_config_timer);
1797
Felix Beckfe137232008-07-14 09:59:08 +02001798 /* Setup the high resultion poll timer.
1799 * If we are running under z/VM adjust polling to z/VM polling rate.
1800 */
1801 if (MACHINE_IS_VM)
1802 poll_timeout = 1500000;
Felix Beck93521312009-12-07 12:52:00 +01001803 spin_lock_init(&ap_poll_timer_lock);
Felix Beckfe137232008-07-14 09:59:08 +02001804 hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1805 ap_poll_timer.function = ap_poll_timeout;
1806
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001807 /* Start the low priority AP bus poll thread. */
1808 if (ap_thread_flag) {
1809 rc = ap_poll_thread_start();
1810 if (rc)
1811 goto out_work;
1812 }
1813
1814 return 0;
1815
1816out_work:
1817 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001818 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001819 destroy_workqueue(ap_work_queue);
1820out_root:
Mark McLoughlin035da162008-12-15 12:58:29 +00001821 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001822out_bus:
1823 while (i--)
1824 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1825 bus_unregister(&ap_bus_type);
1826out:
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001827 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001828 if (ap_using_interrupts()) {
1829 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1830 isc_unregister(AP_ISC);
1831 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001832 return rc;
1833}
1834
1835static int __ap_match_all(struct device *dev, void *data)
1836{
1837 return 1;
1838}
1839
1840/**
Felix Beck1749a812008-04-17 07:46:28 +02001841 * ap_modules_exit(): The module termination code
1842 *
1843 * Terminates the module.
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001844 */
1845void ap_module_exit(void)
1846{
1847 int i;
1848 struct device *dev;
1849
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001850 ap_reset_domain();
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001851 ap_poll_thread_stop();
1852 del_timer_sync(&ap_config_timer);
Felix Beckfe137232008-07-14 09:59:08 +02001853 hrtimer_cancel(&ap_poll_timer);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001854 destroy_workqueue(ap_work_queue);
Ralph Wuerthner13e742b2006-12-15 17:18:17 +01001855 tasklet_kill(&ap_tasklet);
Mark McLoughlin035da162008-12-15 12:58:29 +00001856 root_device_unregister(ap_root_device);
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001857 while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
1858 __ap_match_all)))
1859 {
1860 device_unregister(dev);
1861 put_device(dev);
1862 }
1863 for (i = 0; ap_bus_attrs[i]; i++)
1864 bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
1865 bus_unregister(&ap_bus_type);
Ralph Wuerthner85eca852006-12-08 15:54:07 +01001866 unregister_reset_call(&ap_reset_call);
Felix Beckcb17a632008-12-25 13:38:41 +01001867 if (ap_using_interrupts()) {
1868 s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
1869 isc_unregister(AP_ISC);
1870 }
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001871}
1872
Martin Schwidefsky1534c382006-09-20 15:58:25 +02001873module_init(ap_module_init);
1874module_exit(ap_module_exit);