| .. | .. |
|---|
| 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); |
|---|