.. | .. |
---|
18 | 18 | #include <linux/init.h> |
---|
19 | 19 | #include <linux/delay.h> |
---|
20 | 20 | #include <linux/err.h> |
---|
| 21 | +#include <linux/freezer.h> |
---|
21 | 22 | #include <linux/interrupt.h> |
---|
22 | 23 | #include <linux/workqueue.h> |
---|
23 | 24 | #include <linux/slab.h> |
---|
24 | 25 | #include <linux/notifier.h> |
---|
25 | 26 | #include <linux/kthread.h> |
---|
26 | 27 | #include <linux/mutex.h> |
---|
27 | | -#include <linux/suspend.h> |
---|
28 | 28 | #include <asm/airq.h> |
---|
29 | 29 | #include <linux/atomic.h> |
---|
30 | 30 | #include <asm/isc.h> |
---|
.. | .. |
---|
62 | 62 | |
---|
63 | 63 | static struct device *ap_root_device; |
---|
64 | 64 | |
---|
65 | | -DEFINE_SPINLOCK(ap_list_lock); |
---|
66 | | -LIST_HEAD(ap_card_list); |
---|
| 65 | +/* Hashtable of all queue devices on the AP bus */ |
---|
| 66 | +DEFINE_HASHTABLE(ap_queues, 8); |
---|
| 67 | +/* lock used for the ap_queues hashtable */ |
---|
| 68 | +DEFINE_SPINLOCK(ap_queues_lock); |
---|
67 | 69 | |
---|
68 | | -/* Default permissions (card and domain masking) */ |
---|
69 | | -static struct ap_perms { |
---|
70 | | - DECLARE_BITMAP(apm, AP_DEVICES); |
---|
71 | | - DECLARE_BITMAP(aqm, AP_DOMAINS); |
---|
72 | | -} ap_perms; |
---|
73 | | -static DEFINE_MUTEX(ap_perms_mutex); |
---|
| 70 | +/* Default permissions (ioctl, card and domain masking) */ |
---|
| 71 | +struct ap_perms ap_perms; |
---|
| 72 | +EXPORT_SYMBOL(ap_perms); |
---|
| 73 | +DEFINE_MUTEX(ap_perms_mutex); |
---|
| 74 | +EXPORT_SYMBOL(ap_perms_mutex); |
---|
74 | 75 | |
---|
75 | | -static struct ap_config_info *ap_configuration; |
---|
76 | | -static bool initialised; |
---|
| 76 | +static struct ap_config_info *ap_qci_info; |
---|
77 | 77 | |
---|
78 | 78 | /* |
---|
79 | 79 | * AP bus related debug feature things. |
---|
.. | .. |
---|
92 | 92 | * Tasklet & timer for AP request polling and interrupts |
---|
93 | 93 | */ |
---|
94 | 94 | static void ap_tasklet_fn(unsigned long); |
---|
95 | | -static DECLARE_TASKLET(ap_tasklet, ap_tasklet_fn, 0); |
---|
| 95 | +static DECLARE_TASKLET_OLD(ap_tasklet, ap_tasklet_fn); |
---|
96 | 96 | static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait); |
---|
97 | 97 | static struct task_struct *ap_poll_kthread; |
---|
98 | 98 | static DEFINE_MUTEX(ap_poll_thread_mutex); |
---|
.. | .. |
---|
104 | 104 | */ |
---|
105 | 105 | static unsigned long long poll_timeout = 250000; |
---|
106 | 106 | |
---|
107 | | -/* Suspend flag */ |
---|
108 | | -static int ap_suspend_flag; |
---|
109 | | -/* Maximum domain id */ |
---|
110 | | -static int ap_max_domain_id; |
---|
111 | | -/* |
---|
112 | | - * Flag to check if domain was set through module parameter domain=. This is |
---|
113 | | - * important when supsend and resume is done in a z/VM environment where the |
---|
114 | | - * domain might change. |
---|
115 | | - */ |
---|
116 | | -static int user_set_domain; |
---|
| 107 | +/* Maximum domain id, if not given via qci */ |
---|
| 108 | +static int ap_max_domain_id = 15; |
---|
| 109 | +/* Maximum adapter id, if not given via qci */ |
---|
| 110 | +static int ap_max_adapter_id = 63; |
---|
| 111 | + |
---|
117 | 112 | static struct bus_type ap_bus_type; |
---|
118 | 113 | |
---|
119 | 114 | /* Adapter interrupt definitions */ |
---|
120 | | -static void ap_interrupt_handler(struct airq_struct *airq); |
---|
| 115 | +static void ap_interrupt_handler(struct airq_struct *airq, bool floating); |
---|
121 | 116 | |
---|
122 | | -static int ap_airq_flag; |
---|
| 117 | +static bool ap_irq_flag; |
---|
123 | 118 | |
---|
124 | 119 | static struct airq_struct ap_airq = { |
---|
125 | 120 | .handler = ap_interrupt_handler, |
---|
126 | 121 | .isc = AP_ISC, |
---|
127 | 122 | }; |
---|
128 | | - |
---|
129 | | -/** |
---|
130 | | - * ap_using_interrupts() - Returns non-zero if interrupt support is |
---|
131 | | - * available. |
---|
132 | | - */ |
---|
133 | | -static inline int ap_using_interrupts(void) |
---|
134 | | -{ |
---|
135 | | - return ap_airq_flag; |
---|
136 | | -} |
---|
137 | 123 | |
---|
138 | 124 | /** |
---|
139 | 125 | * ap_airq_ptr() - Get the address of the adapter interrupt indicator |
---|
.. | .. |
---|
144 | 130 | */ |
---|
145 | 131 | void *ap_airq_ptr(void) |
---|
146 | 132 | { |
---|
147 | | - if (ap_using_interrupts()) |
---|
| 133 | + if (ap_irq_flag) |
---|
148 | 134 | return ap_airq.lsi_ptr; |
---|
149 | 135 | return NULL; |
---|
150 | 136 | } |
---|
.. | .. |
---|
160 | 146 | } |
---|
161 | 147 | |
---|
162 | 148 | /** |
---|
163 | | - * ap_configuration_available(): Test if AP configuration |
---|
164 | | - * information is available. |
---|
| 149 | + * ap_qci_available(): Test if AP configuration |
---|
| 150 | + * information can be queried via QCI subfunction. |
---|
165 | 151 | * |
---|
166 | | - * Returns 1 if AP configuration information is available. |
---|
| 152 | + * Returns 1 if subfunction PQAP(QCI) is available. |
---|
167 | 153 | */ |
---|
168 | | -static int ap_configuration_available(void) |
---|
| 154 | +static int ap_qci_available(void) |
---|
169 | 155 | { |
---|
170 | 156 | return test_facility(12); |
---|
171 | 157 | } |
---|
.. | .. |
---|
188 | 174 | */ |
---|
189 | 175 | static inline int ap_qact_available(void) |
---|
190 | 176 | { |
---|
191 | | - if (ap_configuration) |
---|
192 | | - return ap_configuration->qact; |
---|
| 177 | + if (ap_qci_info) |
---|
| 178 | + return ap_qci_info->qact; |
---|
193 | 179 | return 0; |
---|
194 | 180 | } |
---|
195 | 181 | |
---|
196 | 182 | /* |
---|
197 | | - * ap_query_configuration(): Fetch cryptographic config info |
---|
| 183 | + * ap_fetch_qci_info(): Fetch cryptographic config info |
---|
198 | 184 | * |
---|
199 | 185 | * Returns the ap configuration info fetched via PQAP(QCI). |
---|
200 | 186 | * On success 0 is returned, on failure a negative errno |
---|
201 | 187 | * is returned, e.g. if the PQAP(QCI) instruction is not |
---|
202 | 188 | * available, the return value will be -EOPNOTSUPP. |
---|
203 | 189 | */ |
---|
204 | | -static inline int ap_query_configuration(struct ap_config_info *info) |
---|
| 190 | +static inline int ap_fetch_qci_info(struct ap_config_info *info) |
---|
205 | 191 | { |
---|
206 | | - if (!ap_configuration_available()) |
---|
| 192 | + if (!ap_qci_available()) |
---|
207 | 193 | return -EOPNOTSUPP; |
---|
208 | 194 | if (!info) |
---|
209 | 195 | return -EINVAL; |
---|
210 | 196 | return ap_qci(info); |
---|
211 | 197 | } |
---|
212 | | -EXPORT_SYMBOL(ap_query_configuration); |
---|
213 | 198 | |
---|
214 | 199 | /** |
---|
215 | | - * ap_init_configuration(): Allocate and query configuration array. |
---|
216 | | - */ |
---|
217 | | -static void ap_init_configuration(void) |
---|
218 | | -{ |
---|
219 | | - if (!ap_configuration_available()) |
---|
220 | | - return; |
---|
| 200 | + * ap_init_qci_info(): Allocate and query qci config info. |
---|
| 201 | + * Does also update the static variables ap_max_domain_id |
---|
| 202 | + * and ap_max_adapter_id if this info is available. |
---|
221 | 203 | |
---|
222 | | - ap_configuration = kzalloc(sizeof(*ap_configuration), GFP_KERNEL); |
---|
223 | | - if (!ap_configuration) |
---|
| 204 | + */ |
---|
| 205 | +static void __init ap_init_qci_info(void) |
---|
| 206 | +{ |
---|
| 207 | + if (!ap_qci_available()) { |
---|
| 208 | + AP_DBF_INFO("%s QCI not supported\n", __func__); |
---|
224 | 209 | return; |
---|
225 | | - if (ap_query_configuration(ap_configuration) != 0) { |
---|
226 | | - kfree(ap_configuration); |
---|
227 | | - ap_configuration = NULL; |
---|
| 210 | + } |
---|
| 211 | + |
---|
| 212 | + ap_qci_info = kzalloc(sizeof(*ap_qci_info), GFP_KERNEL); |
---|
| 213 | + if (!ap_qci_info) |
---|
228 | 214 | return; |
---|
| 215 | + if (ap_fetch_qci_info(ap_qci_info) != 0) { |
---|
| 216 | + kfree(ap_qci_info); |
---|
| 217 | + ap_qci_info = NULL; |
---|
| 218 | + return; |
---|
| 219 | + } |
---|
| 220 | + AP_DBF_INFO("%s successful fetched initial qci info\n", __func__); |
---|
| 221 | + |
---|
| 222 | + if (ap_qci_info->apxa) { |
---|
| 223 | + if (ap_qci_info->Na) { |
---|
| 224 | + ap_max_adapter_id = ap_qci_info->Na; |
---|
| 225 | + AP_DBF_INFO("%s new ap_max_adapter_id is %d\n", |
---|
| 226 | + __func__, ap_max_adapter_id); |
---|
| 227 | + } |
---|
| 228 | + if (ap_qci_info->Nd) { |
---|
| 229 | + ap_max_domain_id = ap_qci_info->Nd; |
---|
| 230 | + AP_DBF_INFO("%s new ap_max_domain_id is %d\n", |
---|
| 231 | + __func__, ap_max_domain_id); |
---|
| 232 | + } |
---|
229 | 233 | } |
---|
230 | 234 | } |
---|
231 | 235 | |
---|
.. | .. |
---|
240 | 244 | |
---|
241 | 245 | /* |
---|
242 | 246 | * ap_test_config_card_id(): Test, whether an AP card ID is configured. |
---|
243 | | - * @id AP card ID |
---|
244 | 247 | * |
---|
245 | 248 | * Returns 0 if the card is not configured |
---|
246 | 249 | * 1 if the card is configured or |
---|
.. | .. |
---|
248 | 251 | */ |
---|
249 | 252 | static inline int ap_test_config_card_id(unsigned int id) |
---|
250 | 253 | { |
---|
251 | | - if (!ap_configuration) /* QCI not supported */ |
---|
252 | | - /* only ids 0...3F may be probed */ |
---|
253 | | - return id < 0x40 ? 1 : 0; |
---|
254 | | - return ap_test_config(ap_configuration->apm, id); |
---|
| 254 | + if (id > ap_max_adapter_id) |
---|
| 255 | + return 0; |
---|
| 256 | + if (ap_qci_info) |
---|
| 257 | + return ap_test_config(ap_qci_info->apm, id); |
---|
| 258 | + return 1; |
---|
255 | 259 | } |
---|
256 | 260 | |
---|
257 | 261 | /* |
---|
258 | | - * ap_test_config_domain(): Test, whether an AP usage domain is configured. |
---|
259 | | - * @domain AP usage domain ID |
---|
| 262 | + * ap_test_config_usage_domain(): Test, whether an AP usage domain |
---|
| 263 | + * is configured. |
---|
260 | 264 | * |
---|
261 | 265 | * Returns 0 if the usage domain is not configured |
---|
262 | 266 | * 1 if the usage domain is configured or |
---|
263 | 267 | * if the configuration information is not available |
---|
264 | 268 | */ |
---|
265 | | -static inline int ap_test_config_domain(unsigned int domain) |
---|
| 269 | +int ap_test_config_usage_domain(unsigned int domain) |
---|
266 | 270 | { |
---|
267 | | - if (!ap_configuration) /* QCI not supported */ |
---|
268 | | - return domain < 16; |
---|
269 | | - return ap_test_config(ap_configuration->aqm, domain); |
---|
| 271 | + if (domain > ap_max_domain_id) |
---|
| 272 | + return 0; |
---|
| 273 | + if (ap_qci_info) |
---|
| 274 | + return ap_test_config(ap_qci_info->aqm, domain); |
---|
| 275 | + return 1; |
---|
270 | 276 | } |
---|
| 277 | +EXPORT_SYMBOL(ap_test_config_usage_domain); |
---|
271 | 278 | |
---|
272 | | -/** |
---|
273 | | - * ap_query_queue(): Check if an AP queue is available. |
---|
274 | | - * @qid: The AP queue number |
---|
275 | | - * @queue_depth: Pointer to queue depth value |
---|
276 | | - * @device_type: Pointer to device type value |
---|
277 | | - * @facilities: Pointer to facility indicator |
---|
| 279 | +/* |
---|
| 280 | + * ap_test_config_ctrl_domain(): Test, whether an AP control domain |
---|
| 281 | + * is configured. |
---|
| 282 | + * @domain AP control domain ID |
---|
| 283 | + * |
---|
| 284 | + * Returns 1 if the control domain is configured |
---|
| 285 | + * 0 in all other cases |
---|
278 | 286 | */ |
---|
279 | | -static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type, |
---|
280 | | - unsigned int *facilities) |
---|
| 287 | +int ap_test_config_ctrl_domain(unsigned int domain) |
---|
| 288 | +{ |
---|
| 289 | + if (!ap_qci_info || domain > ap_max_domain_id) |
---|
| 290 | + return 0; |
---|
| 291 | + return ap_test_config(ap_qci_info->adm, domain); |
---|
| 292 | +} |
---|
| 293 | +EXPORT_SYMBOL(ap_test_config_ctrl_domain); |
---|
| 294 | + |
---|
| 295 | +/* |
---|
| 296 | + * ap_queue_info(): Check and get AP queue info. |
---|
| 297 | + * Returns true if TAPQ succeeded and the info is filled or |
---|
| 298 | + * false otherwise. |
---|
| 299 | + */ |
---|
| 300 | +static bool ap_queue_info(ap_qid_t qid, int *q_type, |
---|
| 301 | + unsigned int *q_fac, int *q_depth, bool *q_decfg) |
---|
281 | 302 | { |
---|
282 | 303 | struct ap_queue_status status; |
---|
283 | | - unsigned long info; |
---|
284 | | - int nd; |
---|
| 304 | + unsigned long info = 0; |
---|
285 | 305 | |
---|
286 | | - if (!ap_test_config_card_id(AP_QID_CARD(qid))) |
---|
287 | | - return -ENODEV; |
---|
| 306 | + /* make sure we don't run into a specifiation exception */ |
---|
| 307 | + if (AP_QID_CARD(qid) > ap_max_adapter_id || |
---|
| 308 | + AP_QID_QUEUE(qid) > ap_max_domain_id) |
---|
| 309 | + return false; |
---|
288 | 310 | |
---|
| 311 | + /* call TAPQ on this APQN */ |
---|
289 | 312 | status = ap_test_queue(qid, ap_apft_available(), &info); |
---|
290 | 313 | switch (status.response_code) { |
---|
291 | 314 | case AP_RESPONSE_NORMAL: |
---|
292 | | - *queue_depth = (int)(info & 0xff); |
---|
293 | | - *device_type = (int)((info >> 24) & 0xff); |
---|
294 | | - *facilities = (unsigned int)(info >> 32); |
---|
295 | | - /* Update maximum domain id */ |
---|
296 | | - nd = (info >> 16) & 0xff; |
---|
297 | | - /* if N bit is available, z13 and newer */ |
---|
298 | | - if ((info & (1UL << 57)) && nd > 0) |
---|
299 | | - ap_max_domain_id = nd; |
---|
300 | | - else /* older machine types */ |
---|
301 | | - ap_max_domain_id = 15; |
---|
302 | | - switch (*device_type) { |
---|
| 315 | + case AP_RESPONSE_RESET_IN_PROGRESS: |
---|
| 316 | + case AP_RESPONSE_DECONFIGURED: |
---|
| 317 | + case AP_RESPONSE_CHECKSTOPPED: |
---|
| 318 | + case AP_RESPONSE_BUSY: |
---|
| 319 | + /* |
---|
| 320 | + * According to the architecture in all these cases the |
---|
| 321 | + * info should be filled. All bits 0 is not possible as |
---|
| 322 | + * there is at least one of the mode bits set. |
---|
| 323 | + */ |
---|
| 324 | + if (WARN_ON_ONCE(!info)) |
---|
| 325 | + return false; |
---|
| 326 | + *q_type = (int)((info >> 24) & 0xff); |
---|
| 327 | + *q_fac = (unsigned int)(info >> 32); |
---|
| 328 | + *q_depth = (int)(info & 0xff); |
---|
| 329 | + *q_decfg = status.response_code == AP_RESPONSE_DECONFIGURED; |
---|
| 330 | + switch (*q_type) { |
---|
303 | 331 | /* For CEX2 and CEX3 the available functions |
---|
304 | | - * are not refrected by the facilities bits. |
---|
| 332 | + * are not reflected by the facilities bits. |
---|
305 | 333 | * Instead it is coded into the type. So here |
---|
306 | 334 | * modify the function bits based on the type. |
---|
307 | 335 | */ |
---|
308 | 336 | case AP_DEVICE_TYPE_CEX2A: |
---|
309 | 337 | case AP_DEVICE_TYPE_CEX3A: |
---|
310 | | - *facilities |= 0x08000000; |
---|
| 338 | + *q_fac |= 0x08000000; |
---|
311 | 339 | break; |
---|
312 | 340 | case AP_DEVICE_TYPE_CEX2C: |
---|
313 | 341 | case AP_DEVICE_TYPE_CEX3C: |
---|
314 | | - *facilities |= 0x10000000; |
---|
| 342 | + *q_fac |= 0x10000000; |
---|
315 | 343 | break; |
---|
316 | 344 | default: |
---|
317 | 345 | break; |
---|
318 | 346 | } |
---|
319 | | - return 0; |
---|
320 | | - case AP_RESPONSE_Q_NOT_AVAIL: |
---|
321 | | - case AP_RESPONSE_DECONFIGURED: |
---|
322 | | - case AP_RESPONSE_CHECKSTOPPED: |
---|
323 | | - case AP_RESPONSE_INVALID_ADDRESS: |
---|
324 | | - return -ENODEV; |
---|
325 | | - case AP_RESPONSE_RESET_IN_PROGRESS: |
---|
326 | | - case AP_RESPONSE_OTHERWISE_CHANGED: |
---|
327 | | - case AP_RESPONSE_BUSY: |
---|
328 | | - return -EBUSY; |
---|
| 347 | + return true; |
---|
329 | 348 | default: |
---|
330 | | - BUG(); |
---|
| 349 | + /* |
---|
| 350 | + * A response code which indicates, there is no info available. |
---|
| 351 | + */ |
---|
| 352 | + return false; |
---|
331 | 353 | } |
---|
332 | 354 | } |
---|
333 | 355 | |
---|
334 | | -void ap_wait(enum ap_wait wait) |
---|
| 356 | +void ap_wait(enum ap_sm_wait wait) |
---|
335 | 357 | { |
---|
336 | 358 | ktime_t hr_time; |
---|
337 | 359 | |
---|
338 | 360 | switch (wait) { |
---|
339 | | - case AP_WAIT_AGAIN: |
---|
340 | | - case AP_WAIT_INTERRUPT: |
---|
341 | | - if (ap_using_interrupts()) |
---|
| 361 | + case AP_SM_WAIT_AGAIN: |
---|
| 362 | + case AP_SM_WAIT_INTERRUPT: |
---|
| 363 | + if (ap_irq_flag) |
---|
342 | 364 | break; |
---|
343 | 365 | if (ap_poll_kthread) { |
---|
344 | 366 | wake_up(&ap_poll_wait); |
---|
345 | 367 | break; |
---|
346 | 368 | } |
---|
347 | | - /* Fall through */ |
---|
348 | | - case AP_WAIT_TIMEOUT: |
---|
| 369 | + fallthrough; |
---|
| 370 | + case AP_SM_WAIT_TIMEOUT: |
---|
349 | 371 | spin_lock_bh(&ap_poll_timer_lock); |
---|
350 | 372 | if (!hrtimer_is_queued(&ap_poll_timer)) { |
---|
351 | 373 | hr_time = poll_timeout; |
---|
.. | .. |
---|
354 | 376 | } |
---|
355 | 377 | spin_unlock_bh(&ap_poll_timer_lock); |
---|
356 | 378 | break; |
---|
357 | | - case AP_WAIT_NONE: |
---|
| 379 | + case AP_SM_WAIT_NONE: |
---|
358 | 380 | default: |
---|
359 | 381 | break; |
---|
360 | 382 | } |
---|
.. | .. |
---|
370 | 392 | { |
---|
371 | 393 | struct ap_queue *aq = from_timer(aq, t, timeout); |
---|
372 | 394 | |
---|
373 | | - if (ap_suspend_flag) |
---|
374 | | - return; |
---|
375 | 395 | spin_lock_bh(&aq->lock); |
---|
376 | | - ap_wait(ap_sm_event(aq, AP_EVENT_TIMEOUT)); |
---|
| 396 | + ap_wait(ap_sm_event(aq, AP_SM_EVENT_TIMEOUT)); |
---|
377 | 397 | spin_unlock_bh(&aq->lock); |
---|
378 | 398 | } |
---|
379 | 399 | |
---|
.. | .. |
---|
385 | 405 | */ |
---|
386 | 406 | static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused) |
---|
387 | 407 | { |
---|
388 | | - if (!ap_suspend_flag) |
---|
389 | | - tasklet_schedule(&ap_tasklet); |
---|
| 408 | + tasklet_schedule(&ap_tasklet); |
---|
390 | 409 | return HRTIMER_NORESTART; |
---|
391 | 410 | } |
---|
392 | 411 | |
---|
.. | .. |
---|
394 | 413 | * ap_interrupt_handler() - Schedule ap_tasklet on interrupt |
---|
395 | 414 | * @airq: pointer to adapter interrupt descriptor |
---|
396 | 415 | */ |
---|
397 | | -static void ap_interrupt_handler(struct airq_struct *airq) |
---|
| 416 | +static void ap_interrupt_handler(struct airq_struct *airq, bool floating) |
---|
398 | 417 | { |
---|
399 | 418 | inc_irq_stat(IRQIO_APB); |
---|
400 | | - if (!ap_suspend_flag) |
---|
401 | | - tasklet_schedule(&ap_tasklet); |
---|
| 419 | + tasklet_schedule(&ap_tasklet); |
---|
402 | 420 | } |
---|
403 | 421 | |
---|
404 | 422 | /** |
---|
.. | .. |
---|
409 | 427 | */ |
---|
410 | 428 | static void ap_tasklet_fn(unsigned long dummy) |
---|
411 | 429 | { |
---|
412 | | - struct ap_card *ac; |
---|
| 430 | + int bkt; |
---|
413 | 431 | struct ap_queue *aq; |
---|
414 | | - enum ap_wait wait = AP_WAIT_NONE; |
---|
| 432 | + enum ap_sm_wait wait = AP_SM_WAIT_NONE; |
---|
415 | 433 | |
---|
416 | 434 | /* Reset the indicator if interrupts are used. Thus new interrupts can |
---|
417 | 435 | * be received. Doing it in the beginning of the tasklet is therefor |
---|
418 | 436 | * important that no requests on any AP get lost. |
---|
419 | 437 | */ |
---|
420 | | - if (ap_using_interrupts()) |
---|
| 438 | + if (ap_irq_flag) |
---|
421 | 439 | xchg(ap_airq.lsi_ptr, 0); |
---|
422 | 440 | |
---|
423 | | - spin_lock_bh(&ap_list_lock); |
---|
424 | | - for_each_ap_card(ac) { |
---|
425 | | - for_each_ap_queue(aq, ac) { |
---|
426 | | - spin_lock_bh(&aq->lock); |
---|
427 | | - wait = min(wait, ap_sm_event_loop(aq, AP_EVENT_POLL)); |
---|
428 | | - spin_unlock_bh(&aq->lock); |
---|
429 | | - } |
---|
| 441 | + spin_lock_bh(&ap_queues_lock); |
---|
| 442 | + hash_for_each(ap_queues, bkt, aq, hnode) { |
---|
| 443 | + spin_lock_bh(&aq->lock); |
---|
| 444 | + wait = min(wait, ap_sm_event_loop(aq, AP_SM_EVENT_POLL)); |
---|
| 445 | + spin_unlock_bh(&aq->lock); |
---|
430 | 446 | } |
---|
431 | | - spin_unlock_bh(&ap_list_lock); |
---|
| 447 | + spin_unlock_bh(&ap_queues_lock); |
---|
432 | 448 | |
---|
433 | 449 | ap_wait(wait); |
---|
434 | 450 | } |
---|
435 | 451 | |
---|
436 | 452 | static int ap_pending_requests(void) |
---|
437 | 453 | { |
---|
438 | | - struct ap_card *ac; |
---|
| 454 | + int bkt; |
---|
439 | 455 | struct ap_queue *aq; |
---|
440 | 456 | |
---|
441 | | - spin_lock_bh(&ap_list_lock); |
---|
442 | | - for_each_ap_card(ac) { |
---|
443 | | - for_each_ap_queue(aq, ac) { |
---|
444 | | - if (aq->queue_count == 0) |
---|
445 | | - continue; |
---|
446 | | - spin_unlock_bh(&ap_list_lock); |
---|
447 | | - return 1; |
---|
448 | | - } |
---|
| 457 | + spin_lock_bh(&ap_queues_lock); |
---|
| 458 | + hash_for_each(ap_queues, bkt, aq, hnode) { |
---|
| 459 | + if (aq->queue_count == 0) |
---|
| 460 | + continue; |
---|
| 461 | + spin_unlock_bh(&ap_queues_lock); |
---|
| 462 | + return 1; |
---|
449 | 463 | } |
---|
450 | | - spin_unlock_bh(&ap_list_lock); |
---|
| 464 | + spin_unlock_bh(&ap_queues_lock); |
---|
451 | 465 | return 0; |
---|
452 | 466 | } |
---|
453 | 467 | |
---|
.. | .. |
---|
470 | 484 | while (!kthread_should_stop()) { |
---|
471 | 485 | add_wait_queue(&ap_poll_wait, &wait); |
---|
472 | 486 | set_current_state(TASK_INTERRUPTIBLE); |
---|
473 | | - if (ap_suspend_flag || !ap_pending_requests()) { |
---|
| 487 | + if (!ap_pending_requests()) { |
---|
474 | 488 | schedule(); |
---|
475 | 489 | try_to_freeze(); |
---|
476 | 490 | } |
---|
.. | .. |
---|
491 | 505 | { |
---|
492 | 506 | int rc; |
---|
493 | 507 | |
---|
494 | | - if (ap_using_interrupts() || ap_poll_kthread) |
---|
| 508 | + if (ap_irq_flag || ap_poll_kthread) |
---|
495 | 509 | return 0; |
---|
496 | 510 | mutex_lock(&ap_poll_thread_mutex); |
---|
497 | 511 | ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll"); |
---|
.. | .. |
---|
571 | 585 | return retval; |
---|
572 | 586 | } |
---|
573 | 587 | |
---|
574 | | -static int ap_dev_suspend(struct device *dev) |
---|
575 | | -{ |
---|
576 | | - struct ap_device *ap_dev = to_ap_dev(dev); |
---|
577 | | - |
---|
578 | | - if (ap_dev->drv && ap_dev->drv->suspend) |
---|
579 | | - ap_dev->drv->suspend(ap_dev); |
---|
580 | | - return 0; |
---|
581 | | -} |
---|
582 | | - |
---|
583 | | -static int ap_dev_resume(struct device *dev) |
---|
584 | | -{ |
---|
585 | | - struct ap_device *ap_dev = to_ap_dev(dev); |
---|
586 | | - |
---|
587 | | - if (ap_dev->drv && ap_dev->drv->resume) |
---|
588 | | - ap_dev->drv->resume(ap_dev); |
---|
589 | | - return 0; |
---|
590 | | -} |
---|
591 | | - |
---|
592 | | -static void ap_bus_suspend(void) |
---|
593 | | -{ |
---|
594 | | - AP_DBF(DBF_DEBUG, "%s running\n", __func__); |
---|
595 | | - |
---|
596 | | - ap_suspend_flag = 1; |
---|
597 | | - /* |
---|
598 | | - * Disable scanning for devices, thus we do not want to scan |
---|
599 | | - * for them after removing. |
---|
600 | | - */ |
---|
601 | | - flush_work(&ap_scan_work); |
---|
602 | | - tasklet_disable(&ap_tasklet); |
---|
603 | | -} |
---|
604 | | - |
---|
605 | | -static int __ap_card_devices_unregister(struct device *dev, void *dummy) |
---|
606 | | -{ |
---|
607 | | - if (is_card_dev(dev)) |
---|
608 | | - device_unregister(dev); |
---|
609 | | - return 0; |
---|
610 | | -} |
---|
611 | | - |
---|
612 | | -static int __ap_queue_devices_unregister(struct device *dev, void *dummy) |
---|
613 | | -{ |
---|
614 | | - if (is_queue_dev(dev)) |
---|
615 | | - device_unregister(dev); |
---|
616 | | - return 0; |
---|
617 | | -} |
---|
618 | | - |
---|
619 | 588 | static int __ap_queue_devices_with_id_unregister(struct device *dev, void *data) |
---|
620 | 589 | { |
---|
621 | 590 | if (is_queue_dev(dev) && |
---|
.. | .. |
---|
624 | 593 | return 0; |
---|
625 | 594 | } |
---|
626 | 595 | |
---|
627 | | -static void ap_bus_resume(void) |
---|
628 | | -{ |
---|
629 | | - int rc; |
---|
630 | | - |
---|
631 | | - AP_DBF(DBF_DEBUG, "%s running\n", __func__); |
---|
632 | | - |
---|
633 | | - /* remove all queue devices */ |
---|
634 | | - bus_for_each_dev(&ap_bus_type, NULL, NULL, |
---|
635 | | - __ap_queue_devices_unregister); |
---|
636 | | - /* remove all card devices */ |
---|
637 | | - bus_for_each_dev(&ap_bus_type, NULL, NULL, |
---|
638 | | - __ap_card_devices_unregister); |
---|
639 | | - |
---|
640 | | - /* Reset thin interrupt setting */ |
---|
641 | | - if (ap_interrupts_available() && !ap_using_interrupts()) { |
---|
642 | | - rc = register_adapter_interrupt(&ap_airq); |
---|
643 | | - ap_airq_flag = (rc == 0); |
---|
644 | | - } |
---|
645 | | - if (!ap_interrupts_available() && ap_using_interrupts()) { |
---|
646 | | - unregister_adapter_interrupt(&ap_airq); |
---|
647 | | - ap_airq_flag = 0; |
---|
648 | | - } |
---|
649 | | - /* Reset domain */ |
---|
650 | | - if (!user_set_domain) |
---|
651 | | - ap_domain_index = -1; |
---|
652 | | - /* Get things going again */ |
---|
653 | | - ap_suspend_flag = 0; |
---|
654 | | - if (ap_airq_flag) |
---|
655 | | - xchg(ap_airq.lsi_ptr, 0); |
---|
656 | | - tasklet_enable(&ap_tasklet); |
---|
657 | | - queue_work(system_long_wq, &ap_scan_work); |
---|
658 | | -} |
---|
659 | | - |
---|
660 | | -static int ap_power_event(struct notifier_block *this, unsigned long event, |
---|
661 | | - void *ptr) |
---|
662 | | -{ |
---|
663 | | - switch (event) { |
---|
664 | | - case PM_HIBERNATION_PREPARE: |
---|
665 | | - case PM_SUSPEND_PREPARE: |
---|
666 | | - ap_bus_suspend(); |
---|
667 | | - break; |
---|
668 | | - case PM_POST_HIBERNATION: |
---|
669 | | - case PM_POST_SUSPEND: |
---|
670 | | - ap_bus_resume(); |
---|
671 | | - break; |
---|
672 | | - default: |
---|
673 | | - break; |
---|
674 | | - } |
---|
675 | | - return NOTIFY_DONE; |
---|
676 | | -} |
---|
677 | | -static struct notifier_block ap_power_notifier = { |
---|
678 | | - .notifier_call = ap_power_event, |
---|
679 | | -}; |
---|
680 | | - |
---|
681 | | -static SIMPLE_DEV_PM_OPS(ap_bus_pm_ops, ap_dev_suspend, ap_dev_resume); |
---|
682 | | - |
---|
683 | 596 | static struct bus_type ap_bus_type = { |
---|
684 | 597 | .name = "ap", |
---|
685 | 598 | .match = &ap_bus_match, |
---|
686 | 599 | .uevent = &ap_uevent, |
---|
687 | | - .pm = &ap_bus_pm_ops, |
---|
688 | 600 | }; |
---|
689 | 601 | |
---|
690 | 602 | static int __ap_revise_reserved(struct device *dev, void *dummy) |
---|
.. | .. |
---|
701 | 613 | drvres = to_ap_drv(dev->driver)->flags |
---|
702 | 614 | & AP_DRIVER_FLAG_DEFAULT; |
---|
703 | 615 | if (!!devres != !!drvres) { |
---|
704 | | - AP_DBF(DBF_DEBUG, "reprobing queue=%02x.%04x\n", |
---|
705 | | - card, queue); |
---|
| 616 | + AP_DBF_DBG("reprobing queue=%02x.%04x\n", |
---|
| 617 | + card, queue); |
---|
706 | 618 | rc = device_reprobe(dev); |
---|
707 | 619 | } |
---|
708 | 620 | } |
---|
.. | .. |
---|
759 | 671 | { |
---|
760 | 672 | struct ap_device *ap_dev = to_ap_dev(dev); |
---|
761 | 673 | struct ap_driver *ap_drv = to_ap_drv(dev->driver); |
---|
762 | | - int card, queue, devres, drvres, rc; |
---|
| 674 | + int card, queue, devres, drvres, rc = -ENODEV; |
---|
| 675 | + |
---|
| 676 | + if (!get_device(dev)) |
---|
| 677 | + return rc; |
---|
763 | 678 | |
---|
764 | 679 | if (is_queue_dev(dev)) { |
---|
765 | 680 | /* |
---|
.. | .. |
---|
776 | 691 | mutex_unlock(&ap_perms_mutex); |
---|
777 | 692 | drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT; |
---|
778 | 693 | if (!!devres != !!drvres) |
---|
779 | | - return -ENODEV; |
---|
780 | | - /* (re-)init queue's state machine */ |
---|
781 | | - ap_queue_reinit_state(to_ap_queue(dev)); |
---|
| 694 | + goto out; |
---|
782 | 695 | } |
---|
783 | 696 | |
---|
784 | 697 | /* Add queue/card to list of active queues/cards */ |
---|
785 | | - spin_lock_bh(&ap_list_lock); |
---|
786 | | - if (is_card_dev(dev)) |
---|
787 | | - list_add(&to_ap_card(dev)->list, &ap_card_list); |
---|
788 | | - else |
---|
789 | | - list_add(&to_ap_queue(dev)->list, |
---|
790 | | - &to_ap_queue(dev)->card->queues); |
---|
791 | | - spin_unlock_bh(&ap_list_lock); |
---|
| 698 | + spin_lock_bh(&ap_queues_lock); |
---|
| 699 | + if (is_queue_dev(dev)) |
---|
| 700 | + hash_add(ap_queues, &to_ap_queue(dev)->hnode, |
---|
| 701 | + to_ap_queue(dev)->qid); |
---|
| 702 | + spin_unlock_bh(&ap_queues_lock); |
---|
792 | 703 | |
---|
793 | 704 | ap_dev->drv = ap_drv; |
---|
794 | 705 | rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV; |
---|
795 | 706 | |
---|
796 | 707 | if (rc) { |
---|
797 | | - spin_lock_bh(&ap_list_lock); |
---|
798 | | - if (is_card_dev(dev)) |
---|
799 | | - list_del_init(&to_ap_card(dev)->list); |
---|
800 | | - else |
---|
801 | | - list_del_init(&to_ap_queue(dev)->list); |
---|
802 | | - spin_unlock_bh(&ap_list_lock); |
---|
| 708 | + spin_lock_bh(&ap_queues_lock); |
---|
| 709 | + if (is_queue_dev(dev)) |
---|
| 710 | + hash_del(&to_ap_queue(dev)->hnode); |
---|
| 711 | + spin_unlock_bh(&ap_queues_lock); |
---|
803 | 712 | ap_dev->drv = NULL; |
---|
804 | 713 | } |
---|
805 | 714 | |
---|
| 715 | +out: |
---|
| 716 | + if (rc) |
---|
| 717 | + put_device(dev); |
---|
806 | 718 | return rc; |
---|
807 | 719 | } |
---|
808 | 720 | |
---|
.. | .. |
---|
811 | 723 | struct ap_device *ap_dev = to_ap_dev(dev); |
---|
812 | 724 | struct ap_driver *ap_drv = ap_dev->drv; |
---|
813 | 725 | |
---|
| 726 | + /* prepare ap queue device removal */ |
---|
814 | 727 | if (is_queue_dev(dev)) |
---|
815 | | - ap_queue_remove(to_ap_queue(dev)); |
---|
| 728 | + ap_queue_prepare_remove(to_ap_queue(dev)); |
---|
| 729 | + |
---|
| 730 | + /* driver's chance to clean up gracefully */ |
---|
816 | 731 | if (ap_drv->remove) |
---|
817 | 732 | ap_drv->remove(ap_dev); |
---|
818 | 733 | |
---|
| 734 | + /* now do the ap queue device remove */ |
---|
| 735 | + if (is_queue_dev(dev)) |
---|
| 736 | + ap_queue_remove(to_ap_queue(dev)); |
---|
| 737 | + |
---|
819 | 738 | /* Remove queue/card from list of active queues/cards */ |
---|
820 | | - spin_lock_bh(&ap_list_lock); |
---|
821 | | - if (is_card_dev(dev)) |
---|
822 | | - list_del_init(&to_ap_card(dev)->list); |
---|
823 | | - else |
---|
824 | | - list_del_init(&to_ap_queue(dev)->list); |
---|
825 | | - spin_unlock_bh(&ap_list_lock); |
---|
| 739 | + spin_lock_bh(&ap_queues_lock); |
---|
| 740 | + if (is_queue_dev(dev)) |
---|
| 741 | + hash_del(&to_ap_queue(dev)->hnode); |
---|
| 742 | + spin_unlock_bh(&ap_queues_lock); |
---|
| 743 | + |
---|
| 744 | + put_device(dev); |
---|
826 | 745 | |
---|
827 | 746 | return 0; |
---|
828 | 747 | } |
---|
| 748 | + |
---|
| 749 | +struct ap_queue *ap_get_qdev(ap_qid_t qid) |
---|
| 750 | +{ |
---|
| 751 | + int bkt; |
---|
| 752 | + struct ap_queue *aq; |
---|
| 753 | + |
---|
| 754 | + spin_lock_bh(&ap_queues_lock); |
---|
| 755 | + hash_for_each(ap_queues, bkt, aq, hnode) { |
---|
| 756 | + if (aq->qid == qid) { |
---|
| 757 | + get_device(&aq->ap_dev.device); |
---|
| 758 | + spin_unlock_bh(&ap_queues_lock); |
---|
| 759 | + return aq; |
---|
| 760 | + } |
---|
| 761 | + } |
---|
| 762 | + spin_unlock_bh(&ap_queues_lock); |
---|
| 763 | + |
---|
| 764 | + return NULL; |
---|
| 765 | +} |
---|
| 766 | +EXPORT_SYMBOL(ap_get_qdev); |
---|
829 | 767 | |
---|
830 | 768 | int ap_driver_register(struct ap_driver *ap_drv, struct module *owner, |
---|
831 | 769 | char *name) |
---|
832 | 770 | { |
---|
833 | 771 | struct device_driver *drv = &ap_drv->driver; |
---|
834 | | - |
---|
835 | | - if (!initialised) |
---|
836 | | - return -ENODEV; |
---|
837 | 772 | |
---|
838 | 773 | drv->bus = &ap_bus_type; |
---|
839 | 774 | drv->probe = ap_device_probe; |
---|
.. | .. |
---|
852 | 787 | |
---|
853 | 788 | void ap_bus_force_rescan(void) |
---|
854 | 789 | { |
---|
855 | | - if (ap_suspend_flag) |
---|
856 | | - return; |
---|
857 | 790 | /* processing a asynchronous bus rescan */ |
---|
858 | 791 | del_timer(&ap_config_timer); |
---|
859 | 792 | queue_work(system_long_wq, &ap_scan_work); |
---|
860 | 793 | flush_work(&ap_scan_work); |
---|
861 | 794 | } |
---|
862 | 795 | EXPORT_SYMBOL(ap_bus_force_rescan); |
---|
| 796 | + |
---|
| 797 | +/* |
---|
| 798 | +* A config change has happened, force an ap bus rescan. |
---|
| 799 | +*/ |
---|
| 800 | +void ap_bus_cfg_chg(void) |
---|
| 801 | +{ |
---|
| 802 | + AP_DBF_DBG("%s config change, forcing bus rescan\n", __func__); |
---|
| 803 | + |
---|
| 804 | + ap_bus_force_rescan(); |
---|
| 805 | +} |
---|
863 | 806 | |
---|
864 | 807 | /* |
---|
865 | 808 | * hex2bitmap() - parse hex mask string and set bitmap. |
---|
.. | .. |
---|
949 | 892 | return 0; |
---|
950 | 893 | } |
---|
951 | 894 | |
---|
952 | | -/* |
---|
953 | | - * process_mask_arg() - parse a bitmap string and clear/set the |
---|
954 | | - * bits in the bitmap accordingly. The string may be given as |
---|
955 | | - * absolute value, a hex string like 0x1F2E3D4C5B6A" simple over- |
---|
956 | | - * writing the current content of the bitmap. Or as relative string |
---|
957 | | - * like "+1-16,-32,-0x40,+128" where only single bits or ranges of |
---|
958 | | - * bits are cleared or set. Distinction is done based on the very |
---|
959 | | - * first character which may be '+' or '-' for the relative string |
---|
960 | | - * and othewise assume to be an absolute value string. If parsing fails |
---|
961 | | - * a negative errno value is returned. All arguments and bitmaps are |
---|
962 | | - * big endian order. |
---|
963 | | - */ |
---|
964 | | -static int process_mask_arg(const char *str, |
---|
965 | | - unsigned long *bitmap, int bits, |
---|
966 | | - struct mutex *lock) |
---|
| 895 | +int ap_parse_mask_str(const char *str, |
---|
| 896 | + unsigned long *bitmap, int bits, |
---|
| 897 | + struct mutex *lock) |
---|
967 | 898 | { |
---|
968 | 899 | unsigned long *newmap, size; |
---|
969 | 900 | int rc; |
---|
.. | .. |
---|
994 | 925 | kfree(newmap); |
---|
995 | 926 | return rc; |
---|
996 | 927 | } |
---|
| 928 | +EXPORT_SYMBOL(ap_parse_mask_str); |
---|
997 | 929 | |
---|
998 | 930 | /* |
---|
999 | 931 | * AP bus attributes. |
---|
.. | .. |
---|
1001 | 933 | |
---|
1002 | 934 | static ssize_t ap_domain_show(struct bus_type *bus, char *buf) |
---|
1003 | 935 | { |
---|
1004 | | - return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index); |
---|
| 936 | + return scnprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index); |
---|
1005 | 937 | } |
---|
1006 | 938 | |
---|
1007 | 939 | static ssize_t ap_domain_store(struct bus_type *bus, |
---|
.. | .. |
---|
1013 | 945 | domain < 0 || domain > ap_max_domain_id || |
---|
1014 | 946 | !test_bit_inv(domain, ap_perms.aqm)) |
---|
1015 | 947 | return -EINVAL; |
---|
| 948 | + |
---|
1016 | 949 | spin_lock_bh(&ap_domain_lock); |
---|
1017 | 950 | ap_domain_index = domain; |
---|
1018 | 951 | spin_unlock_bh(&ap_domain_lock); |
---|
1019 | 952 | |
---|
1020 | | - AP_DBF(DBF_DEBUG, "stored new default domain=%d\n", domain); |
---|
| 953 | + AP_DBF_INFO("stored new default domain=%d\n", domain); |
---|
1021 | 954 | |
---|
1022 | 955 | return count; |
---|
1023 | 956 | } |
---|
.. | .. |
---|
1026 | 959 | |
---|
1027 | 960 | static ssize_t ap_control_domain_mask_show(struct bus_type *bus, char *buf) |
---|
1028 | 961 | { |
---|
1029 | | - if (!ap_configuration) /* QCI not supported */ |
---|
1030 | | - return snprintf(buf, PAGE_SIZE, "not supported\n"); |
---|
| 962 | + if (!ap_qci_info) /* QCI not supported */ |
---|
| 963 | + return scnprintf(buf, PAGE_SIZE, "not supported\n"); |
---|
1031 | 964 | |
---|
1032 | | - return snprintf(buf, PAGE_SIZE, |
---|
1033 | | - "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", |
---|
1034 | | - ap_configuration->adm[0], ap_configuration->adm[1], |
---|
1035 | | - ap_configuration->adm[2], ap_configuration->adm[3], |
---|
1036 | | - ap_configuration->adm[4], ap_configuration->adm[5], |
---|
1037 | | - ap_configuration->adm[6], ap_configuration->adm[7]); |
---|
| 965 | + return scnprintf(buf, PAGE_SIZE, |
---|
| 966 | + "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", |
---|
| 967 | + ap_qci_info->adm[0], ap_qci_info->adm[1], |
---|
| 968 | + ap_qci_info->adm[2], ap_qci_info->adm[3], |
---|
| 969 | + ap_qci_info->adm[4], ap_qci_info->adm[5], |
---|
| 970 | + ap_qci_info->adm[6], ap_qci_info->adm[7]); |
---|
1038 | 971 | } |
---|
1039 | 972 | |
---|
1040 | 973 | static BUS_ATTR_RO(ap_control_domain_mask); |
---|
1041 | 974 | |
---|
1042 | 975 | static ssize_t ap_usage_domain_mask_show(struct bus_type *bus, char *buf) |
---|
1043 | 976 | { |
---|
1044 | | - if (!ap_configuration) /* QCI not supported */ |
---|
1045 | | - return snprintf(buf, PAGE_SIZE, "not supported\n"); |
---|
| 977 | + if (!ap_qci_info) /* QCI not supported */ |
---|
| 978 | + return scnprintf(buf, PAGE_SIZE, "not supported\n"); |
---|
1046 | 979 | |
---|
1047 | | - return snprintf(buf, PAGE_SIZE, |
---|
1048 | | - "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", |
---|
1049 | | - ap_configuration->aqm[0], ap_configuration->aqm[1], |
---|
1050 | | - ap_configuration->aqm[2], ap_configuration->aqm[3], |
---|
1051 | | - ap_configuration->aqm[4], ap_configuration->aqm[5], |
---|
1052 | | - ap_configuration->aqm[6], ap_configuration->aqm[7]); |
---|
| 980 | + return scnprintf(buf, PAGE_SIZE, |
---|
| 981 | + "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", |
---|
| 982 | + ap_qci_info->aqm[0], ap_qci_info->aqm[1], |
---|
| 983 | + ap_qci_info->aqm[2], ap_qci_info->aqm[3], |
---|
| 984 | + ap_qci_info->aqm[4], ap_qci_info->aqm[5], |
---|
| 985 | + ap_qci_info->aqm[6], ap_qci_info->aqm[7]); |
---|
1053 | 986 | } |
---|
1054 | 987 | |
---|
1055 | 988 | static BUS_ATTR_RO(ap_usage_domain_mask); |
---|
1056 | 989 | |
---|
| 990 | +static ssize_t ap_adapter_mask_show(struct bus_type *bus, char *buf) |
---|
| 991 | +{ |
---|
| 992 | + if (!ap_qci_info) /* QCI not supported */ |
---|
| 993 | + return scnprintf(buf, PAGE_SIZE, "not supported\n"); |
---|
| 994 | + |
---|
| 995 | + return scnprintf(buf, PAGE_SIZE, |
---|
| 996 | + "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", |
---|
| 997 | + ap_qci_info->apm[0], ap_qci_info->apm[1], |
---|
| 998 | + ap_qci_info->apm[2], ap_qci_info->apm[3], |
---|
| 999 | + ap_qci_info->apm[4], ap_qci_info->apm[5], |
---|
| 1000 | + ap_qci_info->apm[6], ap_qci_info->apm[7]); |
---|
| 1001 | +} |
---|
| 1002 | + |
---|
| 1003 | +static BUS_ATTR_RO(ap_adapter_mask); |
---|
| 1004 | + |
---|
1057 | 1005 | static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf) |
---|
1058 | 1006 | { |
---|
1059 | | - return snprintf(buf, PAGE_SIZE, "%d\n", |
---|
1060 | | - ap_using_interrupts() ? 1 : 0); |
---|
| 1007 | + return scnprintf(buf, PAGE_SIZE, "%d\n", |
---|
| 1008 | + ap_irq_flag ? 1 : 0); |
---|
1061 | 1009 | } |
---|
1062 | 1010 | |
---|
1063 | 1011 | static BUS_ATTR_RO(ap_interrupts); |
---|
1064 | 1012 | |
---|
1065 | 1013 | static ssize_t config_time_show(struct bus_type *bus, char *buf) |
---|
1066 | 1014 | { |
---|
1067 | | - return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time); |
---|
| 1015 | + return scnprintf(buf, PAGE_SIZE, "%d\n", ap_config_time); |
---|
1068 | 1016 | } |
---|
1069 | 1017 | |
---|
1070 | 1018 | static ssize_t config_time_store(struct bus_type *bus, |
---|
.. | .. |
---|
1083 | 1031 | |
---|
1084 | 1032 | static ssize_t poll_thread_show(struct bus_type *bus, char *buf) |
---|
1085 | 1033 | { |
---|
1086 | | - return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0); |
---|
| 1034 | + return scnprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0); |
---|
1087 | 1035 | } |
---|
1088 | 1036 | |
---|
1089 | 1037 | static ssize_t poll_thread_store(struct bus_type *bus, |
---|
.. | .. |
---|
1106 | 1054 | |
---|
1107 | 1055 | static ssize_t poll_timeout_show(struct bus_type *bus, char *buf) |
---|
1108 | 1056 | { |
---|
1109 | | - return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout); |
---|
| 1057 | + return scnprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout); |
---|
1110 | 1058 | } |
---|
1111 | 1059 | |
---|
1112 | 1060 | static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf, |
---|
.. | .. |
---|
1135 | 1083 | |
---|
1136 | 1084 | static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf) |
---|
1137 | 1085 | { |
---|
1138 | | - int max_domain_id; |
---|
1139 | | - |
---|
1140 | | - if (ap_configuration) |
---|
1141 | | - max_domain_id = ap_max_domain_id ? : -1; |
---|
1142 | | - else |
---|
1143 | | - max_domain_id = 15; |
---|
1144 | | - return snprintf(buf, PAGE_SIZE, "%d\n", max_domain_id); |
---|
| 1086 | + return scnprintf(buf, PAGE_SIZE, "%d\n", ap_max_domain_id); |
---|
1145 | 1087 | } |
---|
1146 | 1088 | |
---|
1147 | 1089 | static BUS_ATTR_RO(ap_max_domain_id); |
---|
| 1090 | + |
---|
| 1091 | +static ssize_t ap_max_adapter_id_show(struct bus_type *bus, char *buf) |
---|
| 1092 | +{ |
---|
| 1093 | + return scnprintf(buf, PAGE_SIZE, "%d\n", ap_max_adapter_id); |
---|
| 1094 | +} |
---|
| 1095 | + |
---|
| 1096 | +static BUS_ATTR_RO(ap_max_adapter_id); |
---|
1148 | 1097 | |
---|
1149 | 1098 | static ssize_t apmask_show(struct bus_type *bus, char *buf) |
---|
1150 | 1099 | { |
---|
.. | .. |
---|
1152 | 1101 | |
---|
1153 | 1102 | if (mutex_lock_interruptible(&ap_perms_mutex)) |
---|
1154 | 1103 | return -ERESTARTSYS; |
---|
1155 | | - rc = snprintf(buf, PAGE_SIZE, |
---|
1156 | | - "0x%016lx%016lx%016lx%016lx\n", |
---|
1157 | | - ap_perms.apm[0], ap_perms.apm[1], |
---|
1158 | | - ap_perms.apm[2], ap_perms.apm[3]); |
---|
| 1104 | + rc = scnprintf(buf, PAGE_SIZE, |
---|
| 1105 | + "0x%016lx%016lx%016lx%016lx\n", |
---|
| 1106 | + ap_perms.apm[0], ap_perms.apm[1], |
---|
| 1107 | + ap_perms.apm[2], ap_perms.apm[3]); |
---|
1159 | 1108 | mutex_unlock(&ap_perms_mutex); |
---|
1160 | 1109 | |
---|
1161 | 1110 | return rc; |
---|
.. | .. |
---|
1166 | 1115 | { |
---|
1167 | 1116 | int rc; |
---|
1168 | 1117 | |
---|
1169 | | - rc = process_mask_arg(buf, ap_perms.apm, AP_DEVICES, &ap_perms_mutex); |
---|
| 1118 | + rc = ap_parse_mask_str(buf, ap_perms.apm, AP_DEVICES, &ap_perms_mutex); |
---|
1170 | 1119 | if (rc) |
---|
1171 | 1120 | return rc; |
---|
1172 | 1121 | |
---|
.. | .. |
---|
1183 | 1132 | |
---|
1184 | 1133 | if (mutex_lock_interruptible(&ap_perms_mutex)) |
---|
1185 | 1134 | return -ERESTARTSYS; |
---|
1186 | | - rc = snprintf(buf, PAGE_SIZE, |
---|
1187 | | - "0x%016lx%016lx%016lx%016lx\n", |
---|
1188 | | - ap_perms.aqm[0], ap_perms.aqm[1], |
---|
1189 | | - ap_perms.aqm[2], ap_perms.aqm[3]); |
---|
| 1135 | + rc = scnprintf(buf, PAGE_SIZE, |
---|
| 1136 | + "0x%016lx%016lx%016lx%016lx\n", |
---|
| 1137 | + ap_perms.aqm[0], ap_perms.aqm[1], |
---|
| 1138 | + ap_perms.aqm[2], ap_perms.aqm[3]); |
---|
1190 | 1139 | mutex_unlock(&ap_perms_mutex); |
---|
1191 | 1140 | |
---|
1192 | 1141 | return rc; |
---|
.. | .. |
---|
1197 | 1146 | { |
---|
1198 | 1147 | int rc; |
---|
1199 | 1148 | |
---|
1200 | | - rc = process_mask_arg(buf, ap_perms.aqm, AP_DOMAINS, &ap_perms_mutex); |
---|
| 1149 | + rc = ap_parse_mask_str(buf, ap_perms.aqm, AP_DOMAINS, &ap_perms_mutex); |
---|
1201 | 1150 | if (rc) |
---|
1202 | 1151 | return rc; |
---|
1203 | 1152 | |
---|
.. | .. |
---|
1212 | 1161 | &bus_attr_ap_domain, |
---|
1213 | 1162 | &bus_attr_ap_control_domain_mask, |
---|
1214 | 1163 | &bus_attr_ap_usage_domain_mask, |
---|
| 1164 | + &bus_attr_ap_adapter_mask, |
---|
1215 | 1165 | &bus_attr_config_time, |
---|
1216 | 1166 | &bus_attr_poll_thread, |
---|
1217 | 1167 | &bus_attr_ap_interrupts, |
---|
1218 | 1168 | &bus_attr_poll_timeout, |
---|
1219 | 1169 | &bus_attr_ap_max_domain_id, |
---|
| 1170 | + &bus_attr_ap_max_adapter_id, |
---|
1220 | 1171 | &bus_attr_apmask, |
---|
1221 | 1172 | &bus_attr_aqmask, |
---|
1222 | 1173 | NULL, |
---|
.. | .. |
---|
1228 | 1179 | */ |
---|
1229 | 1180 | static void ap_select_domain(void) |
---|
1230 | 1181 | { |
---|
1231 | | - int count, max_count, best_domain; |
---|
1232 | 1182 | struct ap_queue_status status; |
---|
1233 | | - int i, j; |
---|
| 1183 | + int card, dom; |
---|
1234 | 1184 | |
---|
1235 | 1185 | /* |
---|
1236 | | - * We want to use a single domain. Either the one specified with |
---|
1237 | | - * the "domain=" parameter or the domain with the maximum number |
---|
1238 | | - * of devices. |
---|
| 1186 | + * Choose the default domain. Either the one specified with |
---|
| 1187 | + * the "domain=" parameter or the first domain with at least |
---|
| 1188 | + * one valid APQN. |
---|
1239 | 1189 | */ |
---|
1240 | 1190 | spin_lock_bh(&ap_domain_lock); |
---|
1241 | 1191 | if (ap_domain_index >= 0) { |
---|
1242 | 1192 | /* Domain has already been selected. */ |
---|
1243 | | - spin_unlock_bh(&ap_domain_lock); |
---|
1244 | | - return; |
---|
| 1193 | + goto out; |
---|
1245 | 1194 | } |
---|
1246 | | - best_domain = -1; |
---|
1247 | | - max_count = 0; |
---|
1248 | | - for (i = 0; i < AP_DOMAINS; i++) { |
---|
1249 | | - if (!ap_test_config_domain(i) || |
---|
1250 | | - !test_bit_inv(i, ap_perms.aqm)) |
---|
| 1195 | + for (dom = 0; dom <= ap_max_domain_id; dom++) { |
---|
| 1196 | + if (!ap_test_config_usage_domain(dom) || |
---|
| 1197 | + !test_bit_inv(dom, ap_perms.aqm)) |
---|
1251 | 1198 | continue; |
---|
1252 | | - count = 0; |
---|
1253 | | - for (j = 0; j < AP_DEVICES; j++) { |
---|
1254 | | - if (!ap_test_config_card_id(j)) |
---|
| 1199 | + for (card = 0; card <= ap_max_adapter_id; card++) { |
---|
| 1200 | + if (!ap_test_config_card_id(card) || |
---|
| 1201 | + !test_bit_inv(card, ap_perms.apm)) |
---|
1255 | 1202 | continue; |
---|
1256 | | - status = ap_test_queue(AP_MKQID(j, i), |
---|
| 1203 | + status = ap_test_queue(AP_MKQID(card, dom), |
---|
1257 | 1204 | ap_apft_available(), |
---|
1258 | 1205 | NULL); |
---|
1259 | | - if (status.response_code != AP_RESPONSE_NORMAL) |
---|
1260 | | - continue; |
---|
1261 | | - count++; |
---|
| 1206 | + if (status.response_code == AP_RESPONSE_NORMAL) |
---|
| 1207 | + break; |
---|
1262 | 1208 | } |
---|
1263 | | - if (count > max_count) { |
---|
1264 | | - max_count = count; |
---|
1265 | | - best_domain = i; |
---|
1266 | | - } |
---|
| 1209 | + if (card <= ap_max_adapter_id) |
---|
| 1210 | + break; |
---|
1267 | 1211 | } |
---|
1268 | | - if (best_domain >= 0) { |
---|
1269 | | - ap_domain_index = best_domain; |
---|
1270 | | - AP_DBF(DBF_DEBUG, "new ap_domain_index=%d\n", ap_domain_index); |
---|
| 1212 | + if (dom <= ap_max_domain_id) { |
---|
| 1213 | + ap_domain_index = dom; |
---|
| 1214 | + AP_DBF_INFO("%s new default domain is %d\n", |
---|
| 1215 | + __func__, ap_domain_index); |
---|
1271 | 1216 | } |
---|
| 1217 | +out: |
---|
1272 | 1218 | spin_unlock_bh(&ap_domain_lock); |
---|
1273 | 1219 | } |
---|
1274 | 1220 | |
---|
.. | .. |
---|
1282 | 1228 | int comp_type = 0; |
---|
1283 | 1229 | |
---|
1284 | 1230 | /* < CEX2A is not supported */ |
---|
1285 | | - if (rawtype < AP_DEVICE_TYPE_CEX2A) |
---|
| 1231 | + if (rawtype < AP_DEVICE_TYPE_CEX2A) { |
---|
| 1232 | + AP_DBF_WARN("get_comp_type queue=%02x.%04x unsupported type %d\n", |
---|
| 1233 | + AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype); |
---|
1286 | 1234 | return 0; |
---|
1287 | | - /* up to CEX6 known and fully supported */ |
---|
1288 | | - if (rawtype <= AP_DEVICE_TYPE_CEX6) |
---|
| 1235 | + } |
---|
| 1236 | + /* up to CEX7 known and fully supported */ |
---|
| 1237 | + if (rawtype <= AP_DEVICE_TYPE_CEX7) |
---|
1289 | 1238 | return rawtype; |
---|
1290 | 1239 | /* |
---|
1291 | | - * unknown new type > CEX6, check for compatibility |
---|
| 1240 | + * unknown new type > CEX7, check for compatibility |
---|
1292 | 1241 | * to the highest known and supported type which is |
---|
1293 | | - * currently CEX6 with the help of the QACT function. |
---|
| 1242 | + * currently CEX7 with the help of the QACT function. |
---|
1294 | 1243 | */ |
---|
1295 | 1244 | if (ap_qact_available()) { |
---|
1296 | 1245 | struct ap_queue_status status; |
---|
1297 | 1246 | union ap_qact_ap_info apinfo = {0}; |
---|
1298 | 1247 | |
---|
1299 | 1248 | apinfo.mode = (func >> 26) & 0x07; |
---|
1300 | | - apinfo.cat = AP_DEVICE_TYPE_CEX6; |
---|
| 1249 | + apinfo.cat = AP_DEVICE_TYPE_CEX7; |
---|
1301 | 1250 | status = ap_qact(qid, 0, &apinfo); |
---|
1302 | 1251 | if (status.response_code == AP_RESPONSE_NORMAL |
---|
1303 | 1252 | && apinfo.cat >= AP_DEVICE_TYPE_CEX2A |
---|
1304 | | - && apinfo.cat <= AP_DEVICE_TYPE_CEX6) |
---|
| 1253 | + && apinfo.cat <= AP_DEVICE_TYPE_CEX7) |
---|
1305 | 1254 | comp_type = apinfo.cat; |
---|
1306 | 1255 | } |
---|
1307 | 1256 | if (!comp_type) |
---|
1308 | | - AP_DBF(DBF_WARN, "queue=%02x.%04x unable to map type %d\n", |
---|
1309 | | - AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype); |
---|
| 1257 | + AP_DBF_WARN("get_comp_type queue=%02x.%04x unable to map type %d\n", |
---|
| 1258 | + AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype); |
---|
1310 | 1259 | else if (comp_type != rawtype) |
---|
1311 | | - AP_DBF(DBF_INFO, "queue=%02x.%04x map type %d to %d\n", |
---|
1312 | | - AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype, comp_type); |
---|
| 1260 | + AP_DBF_INFO("get_comp_type queue=%02x.%04x map type %d to %d\n", |
---|
| 1261 | + AP_QID_CARD(qid), AP_QID_QUEUE(qid), |
---|
| 1262 | + rawtype, comp_type); |
---|
1313 | 1263 | return comp_type; |
---|
1314 | 1264 | } |
---|
1315 | 1265 | |
---|
1316 | 1266 | /* |
---|
1317 | | - * helper function to be used with bus_find_dev |
---|
| 1267 | + * Helper function to be used with bus_find_dev |
---|
1318 | 1268 | * matches for the card device with the given id |
---|
1319 | 1269 | */ |
---|
1320 | | -static int __match_card_device_with_id(struct device *dev, void *data) |
---|
| 1270 | +static int __match_card_device_with_id(struct device *dev, const void *data) |
---|
1321 | 1271 | { |
---|
1322 | | - return is_card_dev(dev) && to_ap_card(dev)->id == (int)(long) data; |
---|
| 1272 | + return is_card_dev(dev) && to_ap_card(dev)->id == (int)(long)(void *) data; |
---|
1323 | 1273 | } |
---|
1324 | 1274 | |
---|
1325 | | -/* helper function to be used with bus_find_dev |
---|
| 1275 | +/* |
---|
| 1276 | + * Helper function to be used with bus_find_dev |
---|
1326 | 1277 | * matches for the queue device with a given qid |
---|
1327 | 1278 | */ |
---|
1328 | | -static int __match_queue_device_with_qid(struct device *dev, void *data) |
---|
| 1279 | +static int __match_queue_device_with_qid(struct device *dev, const void *data) |
---|
1329 | 1280 | { |
---|
1330 | 1281 | return is_queue_dev(dev) && to_ap_queue(dev)->qid == (int)(long) data; |
---|
| 1282 | +} |
---|
| 1283 | + |
---|
| 1284 | +/* |
---|
| 1285 | + * Helper function to be used with bus_find_dev |
---|
| 1286 | + * matches any queue device with given queue id |
---|
| 1287 | + */ |
---|
| 1288 | +static int __match_queue_device_with_queue_id(struct device *dev, const void *data) |
---|
| 1289 | +{ |
---|
| 1290 | + return is_queue_dev(dev) |
---|
| 1291 | + && AP_QID_QUEUE(to_ap_queue(dev)->qid) == (int)(long) data; |
---|
| 1292 | +} |
---|
| 1293 | + |
---|
| 1294 | +/* |
---|
| 1295 | + * Helper function for ap_scan_bus(). |
---|
| 1296 | + * Remove card device and associated queue devices. |
---|
| 1297 | + */ |
---|
| 1298 | +static inline void ap_scan_rm_card_dev_and_queue_devs(struct ap_card *ac) |
---|
| 1299 | +{ |
---|
| 1300 | + bus_for_each_dev(&ap_bus_type, NULL, |
---|
| 1301 | + (void *)(long) ac->id, |
---|
| 1302 | + __ap_queue_devices_with_id_unregister); |
---|
| 1303 | + device_unregister(&ac->ap_dev.device); |
---|
| 1304 | +} |
---|
| 1305 | + |
---|
| 1306 | +/* |
---|
| 1307 | + * Helper function for ap_scan_bus(). |
---|
| 1308 | + * Does the scan bus job for all the domains within |
---|
| 1309 | + * a valid adapter given by an ap_card ptr. |
---|
| 1310 | + */ |
---|
| 1311 | +static inline void ap_scan_domains(struct ap_card *ac) |
---|
| 1312 | +{ |
---|
| 1313 | + bool decfg; |
---|
| 1314 | + ap_qid_t qid; |
---|
| 1315 | + unsigned int func; |
---|
| 1316 | + struct device *dev; |
---|
| 1317 | + struct ap_queue *aq; |
---|
| 1318 | + int rc, dom, depth, type; |
---|
| 1319 | + |
---|
| 1320 | + /* |
---|
| 1321 | + * Go through the configuration for the domains and compare them |
---|
| 1322 | + * to the existing queue devices. Also take care of the config |
---|
| 1323 | + * and error state for the queue devices. |
---|
| 1324 | + */ |
---|
| 1325 | + |
---|
| 1326 | + for (dom = 0; dom <= ap_max_domain_id; dom++) { |
---|
| 1327 | + qid = AP_MKQID(ac->id, dom); |
---|
| 1328 | + dev = bus_find_device(&ap_bus_type, NULL, |
---|
| 1329 | + (void *)(long) qid, |
---|
| 1330 | + __match_queue_device_with_qid); |
---|
| 1331 | + aq = dev ? to_ap_queue(dev) : NULL; |
---|
| 1332 | + if (!ap_test_config_usage_domain(dom)) { |
---|
| 1333 | + if (dev) { |
---|
| 1334 | + AP_DBF_INFO("%s(%d,%d) not in config any more, rm queue device\n", |
---|
| 1335 | + __func__, ac->id, dom); |
---|
| 1336 | + device_unregister(dev); |
---|
| 1337 | + put_device(dev); |
---|
| 1338 | + } |
---|
| 1339 | + continue; |
---|
| 1340 | + } |
---|
| 1341 | + /* domain is valid, get info from this APQN */ |
---|
| 1342 | + if (!ap_queue_info(qid, &type, &func, &depth, &decfg)) { |
---|
| 1343 | + if (aq) { |
---|
| 1344 | + AP_DBF_INFO( |
---|
| 1345 | + "%s(%d,%d) ap_queue_info() not successful, rm queue device\n", |
---|
| 1346 | + __func__, ac->id, dom); |
---|
| 1347 | + device_unregister(dev); |
---|
| 1348 | + put_device(dev); |
---|
| 1349 | + } |
---|
| 1350 | + continue; |
---|
| 1351 | + } |
---|
| 1352 | + /* if no queue device exists, create a new one */ |
---|
| 1353 | + if (!aq) { |
---|
| 1354 | + aq = ap_queue_create(qid, ac->ap_dev.device_type); |
---|
| 1355 | + if (!aq) { |
---|
| 1356 | + AP_DBF_WARN("%s(%d,%d) ap_queue_create() failed\n", |
---|
| 1357 | + __func__, ac->id, dom); |
---|
| 1358 | + continue; |
---|
| 1359 | + } |
---|
| 1360 | + aq->card = ac; |
---|
| 1361 | + aq->config = !decfg; |
---|
| 1362 | + dev = &aq->ap_dev.device; |
---|
| 1363 | + dev->bus = &ap_bus_type; |
---|
| 1364 | + dev->parent = &ac->ap_dev.device; |
---|
| 1365 | + dev_set_name(dev, "%02x.%04x", ac->id, dom); |
---|
| 1366 | + /* register queue device */ |
---|
| 1367 | + rc = device_register(dev); |
---|
| 1368 | + if (rc) { |
---|
| 1369 | + AP_DBF_WARN("%s(%d,%d) device_register() failed\n", |
---|
| 1370 | + __func__, ac->id, dom); |
---|
| 1371 | + goto put_dev_and_continue; |
---|
| 1372 | + } |
---|
| 1373 | + /* get it and thus adjust reference counter */ |
---|
| 1374 | + get_device(dev); |
---|
| 1375 | + if (decfg) |
---|
| 1376 | + AP_DBF_INFO("%s(%d,%d) new (decfg) queue device created\n", |
---|
| 1377 | + __func__, ac->id, dom); |
---|
| 1378 | + else |
---|
| 1379 | + AP_DBF_INFO("%s(%d,%d) new queue device created\n", |
---|
| 1380 | + __func__, ac->id, dom); |
---|
| 1381 | + goto put_dev_and_continue; |
---|
| 1382 | + } |
---|
| 1383 | + /* Check config state on the already existing queue device */ |
---|
| 1384 | + spin_lock_bh(&aq->lock); |
---|
| 1385 | + if (decfg && aq->config) { |
---|
| 1386 | + /* config off this queue device */ |
---|
| 1387 | + aq->config = false; |
---|
| 1388 | + if (aq->dev_state > AP_DEV_STATE_UNINITIATED) { |
---|
| 1389 | + aq->dev_state = AP_DEV_STATE_ERROR; |
---|
| 1390 | + aq->last_err_rc = AP_RESPONSE_DECONFIGURED; |
---|
| 1391 | + } |
---|
| 1392 | + spin_unlock_bh(&aq->lock); |
---|
| 1393 | + AP_DBF_INFO("%s(%d,%d) queue device config off\n", |
---|
| 1394 | + __func__, ac->id, dom); |
---|
| 1395 | + /* 'receive' pending messages with -EAGAIN */ |
---|
| 1396 | + ap_flush_queue(aq); |
---|
| 1397 | + goto put_dev_and_continue; |
---|
| 1398 | + } |
---|
| 1399 | + if (!decfg && !aq->config) { |
---|
| 1400 | + /* config on this queue device */ |
---|
| 1401 | + aq->config = true; |
---|
| 1402 | + if (aq->dev_state > AP_DEV_STATE_UNINITIATED) { |
---|
| 1403 | + aq->dev_state = AP_DEV_STATE_OPERATING; |
---|
| 1404 | + aq->sm_state = AP_SM_STATE_RESET_START; |
---|
| 1405 | + } |
---|
| 1406 | + spin_unlock_bh(&aq->lock); |
---|
| 1407 | + AP_DBF_INFO("%s(%d,%d) queue device config on\n", |
---|
| 1408 | + __func__, ac->id, dom); |
---|
| 1409 | + goto put_dev_and_continue; |
---|
| 1410 | + } |
---|
| 1411 | + /* handle other error states */ |
---|
| 1412 | + if (!decfg && aq->dev_state == AP_DEV_STATE_ERROR) { |
---|
| 1413 | + spin_unlock_bh(&aq->lock); |
---|
| 1414 | + /* 'receive' pending messages with -EAGAIN */ |
---|
| 1415 | + ap_flush_queue(aq); |
---|
| 1416 | + /* re-init (with reset) the queue device */ |
---|
| 1417 | + ap_queue_init_state(aq); |
---|
| 1418 | + AP_DBF_INFO("%s(%d,%d) queue device reinit enforced\n", |
---|
| 1419 | + __func__, ac->id, dom); |
---|
| 1420 | + goto put_dev_and_continue; |
---|
| 1421 | + } |
---|
| 1422 | + spin_unlock_bh(&aq->lock); |
---|
| 1423 | +put_dev_and_continue: |
---|
| 1424 | + put_device(dev); |
---|
| 1425 | + } |
---|
| 1426 | +} |
---|
| 1427 | + |
---|
| 1428 | +/* |
---|
| 1429 | + * Helper function for ap_scan_bus(). |
---|
| 1430 | + * Does the scan bus job for the given adapter id. |
---|
| 1431 | + */ |
---|
| 1432 | +static inline void ap_scan_adapter(int ap) |
---|
| 1433 | +{ |
---|
| 1434 | + bool decfg; |
---|
| 1435 | + ap_qid_t qid; |
---|
| 1436 | + unsigned int func; |
---|
| 1437 | + struct device *dev; |
---|
| 1438 | + struct ap_card *ac; |
---|
| 1439 | + int rc, dom, depth, type, comp_type; |
---|
| 1440 | + |
---|
| 1441 | + /* Is there currently a card device for this adapter ? */ |
---|
| 1442 | + dev = bus_find_device(&ap_bus_type, NULL, |
---|
| 1443 | + (void *)(long) ap, |
---|
| 1444 | + __match_card_device_with_id); |
---|
| 1445 | + ac = dev ? to_ap_card(dev) : NULL; |
---|
| 1446 | + |
---|
| 1447 | + /* Adapter not in configuration ? */ |
---|
| 1448 | + if (!ap_test_config_card_id(ap)) { |
---|
| 1449 | + if (ac) { |
---|
| 1450 | + AP_DBF_INFO("%s(%d) ap not in config any more, rm card and queue devices\n", |
---|
| 1451 | + __func__, ap); |
---|
| 1452 | + ap_scan_rm_card_dev_and_queue_devs(ac); |
---|
| 1453 | + put_device(dev); |
---|
| 1454 | + } |
---|
| 1455 | + return; |
---|
| 1456 | + } |
---|
| 1457 | + |
---|
| 1458 | + /* |
---|
| 1459 | + * Adapter ap is valid in the current configuration. So do some checks: |
---|
| 1460 | + * If no card device exists, build one. If a card device exists, check |
---|
| 1461 | + * for type and functions changed. For all this we need to find a valid |
---|
| 1462 | + * APQN first. |
---|
| 1463 | + */ |
---|
| 1464 | + |
---|
| 1465 | + for (dom = 0; dom <= ap_max_domain_id; dom++) |
---|
| 1466 | + if (ap_test_config_usage_domain(dom)) { |
---|
| 1467 | + qid = AP_MKQID(ap, dom); |
---|
| 1468 | + if (ap_queue_info(qid, &type, &func, &depth, &decfg)) |
---|
| 1469 | + break; |
---|
| 1470 | + } |
---|
| 1471 | + if (dom > ap_max_domain_id) { |
---|
| 1472 | + /* Could not find a valid APQN for this adapter */ |
---|
| 1473 | + if (ac) { |
---|
| 1474 | + AP_DBF_INFO( |
---|
| 1475 | + "%s(%d) no type info (no APQN found), rm card and queue devices\n", |
---|
| 1476 | + __func__, ap); |
---|
| 1477 | + ap_scan_rm_card_dev_and_queue_devs(ac); |
---|
| 1478 | + put_device(dev); |
---|
| 1479 | + } else { |
---|
| 1480 | + AP_DBF_DBG("%s(%d) no type info (no APQN found), ignored\n", |
---|
| 1481 | + __func__, ap); |
---|
| 1482 | + } |
---|
| 1483 | + return; |
---|
| 1484 | + } |
---|
| 1485 | + if (!type) { |
---|
| 1486 | + /* No apdater type info available, an unusable adapter */ |
---|
| 1487 | + if (ac) { |
---|
| 1488 | + AP_DBF_INFO("%s(%d) no valid type (0) info, rm card and queue devices\n", |
---|
| 1489 | + __func__, ap); |
---|
| 1490 | + ap_scan_rm_card_dev_and_queue_devs(ac); |
---|
| 1491 | + put_device(dev); |
---|
| 1492 | + } else { |
---|
| 1493 | + AP_DBF_DBG("%s(%d) no valid type (0) info, ignored\n", |
---|
| 1494 | + __func__, ap); |
---|
| 1495 | + } |
---|
| 1496 | + return; |
---|
| 1497 | + } |
---|
| 1498 | + |
---|
| 1499 | + if (ac) { |
---|
| 1500 | + /* Check APQN against existing card device for changes */ |
---|
| 1501 | + if (ac->raw_hwtype != type) { |
---|
| 1502 | + AP_DBF_INFO("%s(%d) hwtype %d changed, rm card and queue devices\n", |
---|
| 1503 | + __func__, ap, type); |
---|
| 1504 | + ap_scan_rm_card_dev_and_queue_devs(ac); |
---|
| 1505 | + put_device(dev); |
---|
| 1506 | + ac = NULL; |
---|
| 1507 | + } else if (ac->functions != func) { |
---|
| 1508 | + AP_DBF_INFO("%s(%d) functions 0x%08x changed, rm card and queue devices\n", |
---|
| 1509 | + __func__, ap, type); |
---|
| 1510 | + ap_scan_rm_card_dev_and_queue_devs(ac); |
---|
| 1511 | + put_device(dev); |
---|
| 1512 | + ac = NULL; |
---|
| 1513 | + } else { |
---|
| 1514 | + if (decfg && ac->config) { |
---|
| 1515 | + ac->config = false; |
---|
| 1516 | + AP_DBF_INFO("%s(%d) card device config off\n", |
---|
| 1517 | + __func__, ap); |
---|
| 1518 | + |
---|
| 1519 | + } |
---|
| 1520 | + if (!decfg && !ac->config) { |
---|
| 1521 | + ac->config = true; |
---|
| 1522 | + AP_DBF_INFO("%s(%d) card device config on\n", |
---|
| 1523 | + __func__, ap); |
---|
| 1524 | + } |
---|
| 1525 | + } |
---|
| 1526 | + } |
---|
| 1527 | + |
---|
| 1528 | + if (!ac) { |
---|
| 1529 | + /* Build a new card device */ |
---|
| 1530 | + comp_type = ap_get_compatible_type(qid, type, func); |
---|
| 1531 | + if (!comp_type) { |
---|
| 1532 | + AP_DBF_WARN("%s(%d) type %d, can't get compatibility type\n", |
---|
| 1533 | + __func__, ap, type); |
---|
| 1534 | + return; |
---|
| 1535 | + } |
---|
| 1536 | + ac = ap_card_create(ap, depth, type, comp_type, func); |
---|
| 1537 | + if (!ac) { |
---|
| 1538 | + AP_DBF_WARN("%s(%d) ap_card_create() failed\n", |
---|
| 1539 | + __func__, ap); |
---|
| 1540 | + return; |
---|
| 1541 | + } |
---|
| 1542 | + ac->config = !decfg; |
---|
| 1543 | + dev = &ac->ap_dev.device; |
---|
| 1544 | + dev->bus = &ap_bus_type; |
---|
| 1545 | + dev->parent = ap_root_device; |
---|
| 1546 | + dev_set_name(dev, "card%02x", ap); |
---|
| 1547 | + /* Register the new card device with AP bus */ |
---|
| 1548 | + rc = device_register(dev); |
---|
| 1549 | + if (rc) { |
---|
| 1550 | + AP_DBF_WARN("%s(%d) device_register() failed\n", |
---|
| 1551 | + __func__, ap); |
---|
| 1552 | + put_device(dev); |
---|
| 1553 | + return; |
---|
| 1554 | + } |
---|
| 1555 | + /* get it and thus adjust reference counter */ |
---|
| 1556 | + get_device(dev); |
---|
| 1557 | + if (decfg) |
---|
| 1558 | + AP_DBF_INFO("%s(%d) new (decfg) card device type=%d func=0x%08x created\n", |
---|
| 1559 | + __func__, ap, type, func); |
---|
| 1560 | + else |
---|
| 1561 | + AP_DBF_INFO("%s(%d) new card device type=%d func=0x%08x created\n", |
---|
| 1562 | + __func__, ap, type, func); |
---|
| 1563 | + } |
---|
| 1564 | + |
---|
| 1565 | + /* Verify the domains and the queue devices for this card */ |
---|
| 1566 | + ap_scan_domains(ac); |
---|
| 1567 | + |
---|
| 1568 | + /* release the card device */ |
---|
| 1569 | + put_device(&ac->ap_dev.device); |
---|
1331 | 1570 | } |
---|
1332 | 1571 | |
---|
1333 | 1572 | /** |
---|
.. | .. |
---|
1336 | 1575 | */ |
---|
1337 | 1576 | static void ap_scan_bus(struct work_struct *unused) |
---|
1338 | 1577 | { |
---|
1339 | | - struct ap_queue *aq; |
---|
1340 | | - struct ap_card *ac; |
---|
1341 | | - struct device *dev; |
---|
1342 | | - ap_qid_t qid; |
---|
1343 | | - int comp_type, depth = 0, type = 0; |
---|
1344 | | - unsigned int func = 0; |
---|
1345 | | - int rc, id, dom, borked, domains, defdomdevs = 0; |
---|
| 1578 | + int ap; |
---|
1346 | 1579 | |
---|
1347 | | - AP_DBF(DBF_DEBUG, "%s running\n", __func__); |
---|
1348 | | - |
---|
1349 | | - ap_query_configuration(ap_configuration); |
---|
| 1580 | + ap_fetch_qci_info(ap_qci_info); |
---|
1350 | 1581 | ap_select_domain(); |
---|
1351 | 1582 | |
---|
1352 | | - for (id = 0; id < AP_DEVICES; id++) { |
---|
1353 | | - /* check if device is registered */ |
---|
1354 | | - dev = bus_find_device(&ap_bus_type, NULL, |
---|
1355 | | - (void *)(long) id, |
---|
1356 | | - __match_card_device_with_id); |
---|
1357 | | - ac = dev ? to_ap_card(dev) : NULL; |
---|
1358 | | - if (!ap_test_config_card_id(id)) { |
---|
1359 | | - if (dev) { |
---|
1360 | | - /* Card device has been removed from |
---|
1361 | | - * configuration, remove the belonging |
---|
1362 | | - * queue devices. |
---|
1363 | | - */ |
---|
1364 | | - bus_for_each_dev(&ap_bus_type, NULL, |
---|
1365 | | - (void *)(long) id, |
---|
1366 | | - __ap_queue_devices_with_id_unregister); |
---|
1367 | | - /* now remove the card device */ |
---|
1368 | | - device_unregister(dev); |
---|
1369 | | - put_device(dev); |
---|
1370 | | - } |
---|
1371 | | - continue; |
---|
1372 | | - } |
---|
1373 | | - /* According to the configuration there should be a card |
---|
1374 | | - * device, so check if there is at least one valid queue |
---|
1375 | | - * and maybe create queue devices and the card device. |
---|
1376 | | - */ |
---|
1377 | | - domains = 0; |
---|
1378 | | - for (dom = 0; dom < AP_DOMAINS; dom++) { |
---|
1379 | | - qid = AP_MKQID(id, dom); |
---|
1380 | | - dev = bus_find_device(&ap_bus_type, NULL, |
---|
1381 | | - (void *)(long) qid, |
---|
1382 | | - __match_queue_device_with_qid); |
---|
1383 | | - aq = dev ? to_ap_queue(dev) : NULL; |
---|
1384 | | - if (!ap_test_config_domain(dom)) { |
---|
1385 | | - if (dev) { |
---|
1386 | | - /* Queue device exists but has been |
---|
1387 | | - * removed from configuration. |
---|
1388 | | - */ |
---|
1389 | | - device_unregister(dev); |
---|
1390 | | - put_device(dev); |
---|
1391 | | - } |
---|
1392 | | - continue; |
---|
1393 | | - } |
---|
1394 | | - rc = ap_query_queue(qid, &depth, &type, &func); |
---|
1395 | | - if (dev) { |
---|
1396 | | - spin_lock_bh(&aq->lock); |
---|
1397 | | - if (rc == -ENODEV || |
---|
1398 | | - /* adapter reconfiguration */ |
---|
1399 | | - (ac && ac->functions != func)) |
---|
1400 | | - aq->state = AP_STATE_BORKED; |
---|
1401 | | - borked = aq->state == AP_STATE_BORKED; |
---|
1402 | | - spin_unlock_bh(&aq->lock); |
---|
1403 | | - if (borked) /* Remove broken device */ |
---|
1404 | | - device_unregister(dev); |
---|
1405 | | - put_device(dev); |
---|
1406 | | - if (!borked) { |
---|
1407 | | - domains++; |
---|
1408 | | - if (dom == ap_domain_index) |
---|
1409 | | - defdomdevs++; |
---|
1410 | | - continue; |
---|
1411 | | - } |
---|
1412 | | - } |
---|
1413 | | - if (rc) |
---|
1414 | | - continue; |
---|
1415 | | - /* a new queue device is needed, check out comp type */ |
---|
1416 | | - comp_type = ap_get_compatible_type(qid, type, func); |
---|
1417 | | - if (!comp_type) |
---|
1418 | | - continue; |
---|
1419 | | - /* maybe a card device needs to be created first */ |
---|
1420 | | - if (!ac) { |
---|
1421 | | - ac = ap_card_create(id, depth, type, |
---|
1422 | | - comp_type, func); |
---|
1423 | | - if (!ac) |
---|
1424 | | - continue; |
---|
1425 | | - ac->ap_dev.device.bus = &ap_bus_type; |
---|
1426 | | - ac->ap_dev.device.parent = ap_root_device; |
---|
1427 | | - dev_set_name(&ac->ap_dev.device, |
---|
1428 | | - "card%02x", id); |
---|
1429 | | - /* Register card with AP bus */ |
---|
1430 | | - rc = device_register(&ac->ap_dev.device); |
---|
1431 | | - if (rc) { |
---|
1432 | | - put_device(&ac->ap_dev.device); |
---|
1433 | | - ac = NULL; |
---|
1434 | | - break; |
---|
1435 | | - } |
---|
1436 | | - /* get it and thus adjust reference counter */ |
---|
1437 | | - get_device(&ac->ap_dev.device); |
---|
1438 | | - } |
---|
1439 | | - /* now create the new queue device */ |
---|
1440 | | - aq = ap_queue_create(qid, comp_type); |
---|
1441 | | - if (!aq) |
---|
1442 | | - continue; |
---|
1443 | | - aq->card = ac; |
---|
1444 | | - aq->ap_dev.device.bus = &ap_bus_type; |
---|
1445 | | - aq->ap_dev.device.parent = &ac->ap_dev.device; |
---|
1446 | | - dev_set_name(&aq->ap_dev.device, |
---|
1447 | | - "%02x.%04x", id, dom); |
---|
1448 | | - /* Register device */ |
---|
1449 | | - rc = device_register(&aq->ap_dev.device); |
---|
1450 | | - if (rc) { |
---|
1451 | | - put_device(&aq->ap_dev.device); |
---|
1452 | | - continue; |
---|
1453 | | - } |
---|
1454 | | - domains++; |
---|
1455 | | - if (dom == ap_domain_index) |
---|
1456 | | - defdomdevs++; |
---|
1457 | | - } /* end domain loop */ |
---|
1458 | | - if (ac) { |
---|
1459 | | - /* remove card dev if there are no queue devices */ |
---|
1460 | | - if (!domains) |
---|
1461 | | - device_unregister(&ac->ap_dev.device); |
---|
1462 | | - put_device(&ac->ap_dev.device); |
---|
1463 | | - } |
---|
1464 | | - } /* end device loop */ |
---|
| 1583 | + AP_DBF_DBG("%s running\n", __func__); |
---|
1465 | 1584 | |
---|
1466 | | - if (ap_domain_index >= 0 && defdomdevs < 1) |
---|
1467 | | - AP_DBF(DBF_INFO, |
---|
1468 | | - "no queue device with default domain %d available\n", |
---|
1469 | | - ap_domain_index); |
---|
| 1585 | + /* loop over all possible adapters */ |
---|
| 1586 | + for (ap = 0; ap <= ap_max_adapter_id; ap++) |
---|
| 1587 | + ap_scan_adapter(ap); |
---|
| 1588 | + |
---|
| 1589 | + /* check if there is at least one queue available with default domain */ |
---|
| 1590 | + if (ap_domain_index >= 0) { |
---|
| 1591 | + struct device *dev = |
---|
| 1592 | + bus_find_device(&ap_bus_type, NULL, |
---|
| 1593 | + (void *)(long) ap_domain_index, |
---|
| 1594 | + __match_queue_device_with_queue_id); |
---|
| 1595 | + if (dev) |
---|
| 1596 | + put_device(dev); |
---|
| 1597 | + else |
---|
| 1598 | + AP_DBF_INFO("no queue device with default domain %d available\n", |
---|
| 1599 | + ap_domain_index); |
---|
| 1600 | + } |
---|
1470 | 1601 | |
---|
1471 | 1602 | mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ); |
---|
1472 | 1603 | } |
---|
1473 | 1604 | |
---|
1474 | 1605 | static void ap_config_timeout(struct timer_list *unused) |
---|
1475 | 1606 | { |
---|
1476 | | - if (ap_suspend_flag) |
---|
1477 | | - return; |
---|
1478 | 1607 | queue_work(system_long_wq, &ap_scan_work); |
---|
1479 | 1608 | } |
---|
1480 | 1609 | |
---|
.. | .. |
---|
1491 | 1620 | static void __init ap_perms_init(void) |
---|
1492 | 1621 | { |
---|
1493 | 1622 | /* all resources useable if no kernel parameter string given */ |
---|
| 1623 | + memset(&ap_perms.ioctlm, 0xFF, sizeof(ap_perms.ioctlm)); |
---|
1494 | 1624 | memset(&ap_perms.apm, 0xFF, sizeof(ap_perms.apm)); |
---|
1495 | 1625 | memset(&ap_perms.aqm, 0xFF, sizeof(ap_perms.aqm)); |
---|
1496 | 1626 | |
---|
1497 | 1627 | /* apm kernel parameter string */ |
---|
1498 | 1628 | if (apm_str) { |
---|
1499 | 1629 | memset(&ap_perms.apm, 0, sizeof(ap_perms.apm)); |
---|
1500 | | - process_mask_arg(apm_str, ap_perms.apm, AP_DEVICES, |
---|
1501 | | - &ap_perms_mutex); |
---|
| 1630 | + ap_parse_mask_str(apm_str, ap_perms.apm, AP_DEVICES, |
---|
| 1631 | + &ap_perms_mutex); |
---|
1502 | 1632 | } |
---|
1503 | 1633 | |
---|
1504 | 1634 | /* aqm kernel parameter string */ |
---|
1505 | 1635 | if (aqm_str) { |
---|
1506 | 1636 | memset(&ap_perms.aqm, 0, sizeof(ap_perms.aqm)); |
---|
1507 | | - process_mask_arg(aqm_str, ap_perms.aqm, AP_DOMAINS, |
---|
1508 | | - &ap_perms_mutex); |
---|
| 1637 | + ap_parse_mask_str(aqm_str, ap_perms.aqm, AP_DOMAINS, |
---|
| 1638 | + &ap_perms_mutex); |
---|
1509 | 1639 | } |
---|
1510 | 1640 | } |
---|
1511 | 1641 | |
---|
.. | .. |
---|
1516 | 1646 | */ |
---|
1517 | 1647 | static int __init ap_module_init(void) |
---|
1518 | 1648 | { |
---|
1519 | | - int max_domain_id; |
---|
1520 | 1649 | int rc, i; |
---|
1521 | 1650 | |
---|
1522 | 1651 | rc = ap_debug_init(); |
---|
.. | .. |
---|
1528 | 1657 | return -ENODEV; |
---|
1529 | 1658 | } |
---|
1530 | 1659 | |
---|
1531 | | - /* set up the AP permissions (ap and aq masks) */ |
---|
| 1660 | + /* init ap_queue hashtable */ |
---|
| 1661 | + hash_init(ap_queues); |
---|
| 1662 | + |
---|
| 1663 | + /* set up the AP permissions (ioctls, ap and aq masks) */ |
---|
1532 | 1664 | ap_perms_init(); |
---|
1533 | 1665 | |
---|
1534 | 1666 | /* Get AP configuration data if available */ |
---|
1535 | | - ap_init_configuration(); |
---|
| 1667 | + ap_init_qci_info(); |
---|
1536 | 1668 | |
---|
1537 | | - if (ap_configuration) |
---|
1538 | | - max_domain_id = |
---|
1539 | | - ap_max_domain_id ? ap_max_domain_id : AP_DOMAINS - 1; |
---|
1540 | | - else |
---|
1541 | | - max_domain_id = 15; |
---|
1542 | | - if (ap_domain_index < -1 || ap_domain_index > max_domain_id || |
---|
| 1669 | + /* check default domain setting */ |
---|
| 1670 | + if (ap_domain_index < -1 || ap_domain_index > ap_max_domain_id || |
---|
1543 | 1671 | (ap_domain_index >= 0 && |
---|
1544 | 1672 | !test_bit_inv(ap_domain_index, ap_perms.aqm))) { |
---|
1545 | 1673 | pr_warn("%d is not a valid cryptographic domain\n", |
---|
1546 | 1674 | ap_domain_index); |
---|
1547 | 1675 | ap_domain_index = -1; |
---|
1548 | 1676 | } |
---|
1549 | | - /* In resume callback we need to know if the user had set the domain. |
---|
1550 | | - * If so, we can not just reset it. |
---|
1551 | | - */ |
---|
1552 | | - if (ap_domain_index >= 0) |
---|
1553 | | - user_set_domain = 1; |
---|
1554 | 1677 | |
---|
| 1678 | + /* enable interrupts if available */ |
---|
1555 | 1679 | if (ap_interrupts_available()) { |
---|
1556 | 1680 | rc = register_adapter_interrupt(&ap_airq); |
---|
1557 | | - ap_airq_flag = (rc == 0); |
---|
| 1681 | + ap_irq_flag = (rc == 0); |
---|
1558 | 1682 | } |
---|
1559 | 1683 | |
---|
1560 | 1684 | /* Create /sys/bus/ap. */ |
---|
.. | .. |
---|
1582 | 1706 | */ |
---|
1583 | 1707 | if (MACHINE_IS_VM) |
---|
1584 | 1708 | poll_timeout = 1500000; |
---|
1585 | | - spin_lock_init(&ap_poll_timer_lock); |
---|
1586 | 1709 | hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
---|
1587 | 1710 | ap_poll_timer.function = ap_poll_timeout; |
---|
1588 | 1711 | |
---|
.. | .. |
---|
1593 | 1716 | goto out_work; |
---|
1594 | 1717 | } |
---|
1595 | 1718 | |
---|
1596 | | - rc = register_pm_notifier(&ap_power_notifier); |
---|
1597 | | - if (rc) |
---|
1598 | | - goto out_pm; |
---|
1599 | | - |
---|
1600 | 1719 | queue_work(system_long_wq, &ap_scan_work); |
---|
1601 | | - initialised = true; |
---|
1602 | 1720 | |
---|
1603 | 1721 | return 0; |
---|
1604 | 1722 | |
---|
1605 | | -out_pm: |
---|
1606 | | - ap_poll_thread_stop(); |
---|
1607 | 1723 | out_work: |
---|
1608 | 1724 | hrtimer_cancel(&ap_poll_timer); |
---|
1609 | 1725 | root_device_unregister(ap_root_device); |
---|
.. | .. |
---|
1612 | 1728 | bus_remove_file(&ap_bus_type, ap_bus_attrs[i]); |
---|
1613 | 1729 | bus_unregister(&ap_bus_type); |
---|
1614 | 1730 | out: |
---|
1615 | | - if (ap_using_interrupts()) |
---|
| 1731 | + if (ap_irq_flag) |
---|
1616 | 1732 | unregister_adapter_interrupt(&ap_airq); |
---|
1617 | | - kfree(ap_configuration); |
---|
| 1733 | + kfree(ap_qci_info); |
---|
1618 | 1734 | return rc; |
---|
1619 | 1735 | } |
---|
1620 | 1736 | device_initcall(ap_module_init); |
---|