diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/s390/block/dasd.c | 22 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_3990_erp.c | 20 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_alias.c | 125 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_devmap.c | 174 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_eckd.c | 116 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_eckd.h | 2 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_int.h | 49 | ||||
| -rw-r--r-- | drivers/s390/char/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/s390/char/fs3270.c | 1 | ||||
| -rw-r--r-- | drivers/s390/char/keyboard.c | 21 | ||||
| -rw-r--r-- | drivers/s390/char/vmcp.c | 38 | ||||
| -rw-r--r-- | drivers/s390/char/zcore.c | 4 | ||||
| -rw-r--r-- | drivers/s390/cio/chsc_sch.c | 1 | ||||
| -rw-r--r-- | drivers/s390/cio/cio.c | 3 | ||||
| -rw-r--r-- | drivers/s390/cio/css.c | 8 | ||||
| -rw-r--r-- | drivers/s390/cio/qdio.h | 15 | ||||
| -rw-r--r-- | drivers/s390/cio/qdio_main.c | 67 | ||||
| -rw-r--r-- | drivers/s390/cio/qdio_setup.c | 8 | ||||
| -rw-r--r-- | drivers/s390/cio/qdio_thinint.c | 4 | ||||
| -rw-r--r-- | drivers/s390/crypto/zcrypt_api.c | 2 | ||||
| -rw-r--r-- | drivers/s390/net/qeth_core_main.c | 17 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_cfdc.c | 1 |
22 files changed, 396 insertions, 305 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index fa2339cb1681..0e86247d791e 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
| @@ -65,6 +65,7 @@ static void dasd_device_tasklet(struct dasd_device *); | |||
| 65 | static void dasd_block_tasklet(struct dasd_block *); | 65 | static void dasd_block_tasklet(struct dasd_block *); |
| 66 | static void do_kick_device(struct work_struct *); | 66 | static void do_kick_device(struct work_struct *); |
| 67 | static void do_restore_device(struct work_struct *); | 67 | static void do_restore_device(struct work_struct *); |
| 68 | static void do_reload_device(struct work_struct *); | ||
| 68 | static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); | 69 | static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); |
| 69 | static void dasd_device_timeout(unsigned long); | 70 | static void dasd_device_timeout(unsigned long); |
| 70 | static void dasd_block_timeout(unsigned long); | 71 | static void dasd_block_timeout(unsigned long); |
| @@ -115,6 +116,7 @@ struct dasd_device *dasd_alloc_device(void) | |||
| 115 | device->timer.data = (unsigned long) device; | 116 | device->timer.data = (unsigned long) device; |
| 116 | INIT_WORK(&device->kick_work, do_kick_device); | 117 | INIT_WORK(&device->kick_work, do_kick_device); |
| 117 | INIT_WORK(&device->restore_device, do_restore_device); | 118 | INIT_WORK(&device->restore_device, do_restore_device); |
| 119 | INIT_WORK(&device->reload_device, do_reload_device); | ||
| 118 | device->state = DASD_STATE_NEW; | 120 | device->state = DASD_STATE_NEW; |
| 119 | device->target = DASD_STATE_NEW; | 121 | device->target = DASD_STATE_NEW; |
| 120 | mutex_init(&device->state_mutex); | 122 | mutex_init(&device->state_mutex); |
| @@ -521,6 +523,26 @@ void dasd_kick_device(struct dasd_device *device) | |||
| 521 | } | 523 | } |
| 522 | 524 | ||
| 523 | /* | 525 | /* |
| 526 | * dasd_reload_device will schedule a call do do_reload_device to the kernel | ||
| 527 | * event daemon. | ||
| 528 | */ | ||
| 529 | static void do_reload_device(struct work_struct *work) | ||
| 530 | { | ||
| 531 | struct dasd_device *device = container_of(work, struct dasd_device, | ||
| 532 | reload_device); | ||
| 533 | device->discipline->reload(device); | ||
| 534 | dasd_put_device(device); | ||
| 535 | } | ||
| 536 | |||
| 537 | void dasd_reload_device(struct dasd_device *device) | ||
| 538 | { | ||
| 539 | dasd_get_device(device); | ||
| 540 | /* queue call to dasd_reload_device to the kernel event daemon. */ | ||
| 541 | schedule_work(&device->reload_device); | ||
| 542 | } | ||
| 543 | EXPORT_SYMBOL(dasd_reload_device); | ||
| 544 | |||
| 545 | /* | ||
| 524 | * dasd_restore_device will schedule a call do do_restore_device to the kernel | 546 | * dasd_restore_device will schedule a call do do_restore_device to the kernel |
| 525 | * event daemon. | 547 | * event daemon. |
| 526 | */ | 548 | */ |
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 6632649dd6aa..85bfd8794856 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c | |||
| @@ -1418,9 +1418,29 @@ static struct dasd_ccw_req *dasd_3990_erp_inspect_alias( | |||
| 1418 | struct dasd_ccw_req *erp) | 1418 | struct dasd_ccw_req *erp) |
| 1419 | { | 1419 | { |
| 1420 | struct dasd_ccw_req *cqr = erp->refers; | 1420 | struct dasd_ccw_req *cqr = erp->refers; |
| 1421 | char *sense; | ||
| 1421 | 1422 | ||
| 1422 | if (cqr->block && | 1423 | if (cqr->block && |
| 1423 | (cqr->block->base != cqr->startdev)) { | 1424 | (cqr->block->base != cqr->startdev)) { |
| 1425 | |||
| 1426 | sense = dasd_get_sense(&erp->refers->irb); | ||
| 1427 | /* | ||
| 1428 | * dynamic pav may have changed base alias mapping | ||
| 1429 | */ | ||
| 1430 | if (!test_bit(DASD_FLAG_OFFLINE, &cqr->startdev->flags) && sense | ||
| 1431 | && (sense[0] == 0x10) && (sense[7] == 0x0F) | ||
| 1432 | && (sense[8] == 0x67)) { | ||
| 1433 | /* | ||
| 1434 | * remove device from alias handling to prevent new | ||
| 1435 | * requests from being scheduled on the | ||
| 1436 | * wrong alias device | ||
| 1437 | */ | ||
| 1438 | dasd_alias_remove_device(cqr->startdev); | ||
| 1439 | |||
| 1440 | /* schedule worker to reload device */ | ||
| 1441 | dasd_reload_device(cqr->startdev); | ||
| 1442 | } | ||
| 1443 | |||
| 1424 | if (cqr->startdev->features & DASD_FEATURE_ERPLOG) { | 1444 | if (cqr->startdev->features & DASD_FEATURE_ERPLOG) { |
| 1425 | DBF_DEV_EVENT(DBF_ERR, cqr->startdev, | 1445 | DBF_DEV_EVENT(DBF_ERR, cqr->startdev, |
| 1426 | "ERP on alias device for request %p," | 1446 | "ERP on alias device for request %p," |
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 8c4814258e93..4155805dcdff 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c | |||
| @@ -190,20 +190,21 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) | |||
| 190 | struct alias_server *server, *newserver; | 190 | struct alias_server *server, *newserver; |
| 191 | struct alias_lcu *lcu, *newlcu; | 191 | struct alias_lcu *lcu, *newlcu; |
| 192 | int is_lcu_known; | 192 | int is_lcu_known; |
| 193 | struct dasd_uid *uid; | 193 | struct dasd_uid uid; |
| 194 | 194 | ||
| 195 | private = (struct dasd_eckd_private *) device->private; | 195 | private = (struct dasd_eckd_private *) device->private; |
| 196 | uid = &private->uid; | 196 | |
| 197 | device->discipline->get_uid(device, &uid); | ||
| 197 | spin_lock_irqsave(&aliastree.lock, flags); | 198 | spin_lock_irqsave(&aliastree.lock, flags); |
| 198 | is_lcu_known = 1; | 199 | is_lcu_known = 1; |
| 199 | server = _find_server(uid); | 200 | server = _find_server(&uid); |
| 200 | if (!server) { | 201 | if (!server) { |
| 201 | spin_unlock_irqrestore(&aliastree.lock, flags); | 202 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| 202 | newserver = _allocate_server(uid); | 203 | newserver = _allocate_server(&uid); |
| 203 | if (IS_ERR(newserver)) | 204 | if (IS_ERR(newserver)) |
| 204 | return PTR_ERR(newserver); | 205 | return PTR_ERR(newserver); |
| 205 | spin_lock_irqsave(&aliastree.lock, flags); | 206 | spin_lock_irqsave(&aliastree.lock, flags); |
| 206 | server = _find_server(uid); | 207 | server = _find_server(&uid); |
| 207 | if (!server) { | 208 | if (!server) { |
| 208 | list_add(&newserver->server, &aliastree.serverlist); | 209 | list_add(&newserver->server, &aliastree.serverlist); |
| 209 | server = newserver; | 210 | server = newserver; |
| @@ -214,14 +215,14 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) | |||
| 214 | } | 215 | } |
| 215 | } | 216 | } |
| 216 | 217 | ||
| 217 | lcu = _find_lcu(server, uid); | 218 | lcu = _find_lcu(server, &uid); |
| 218 | if (!lcu) { | 219 | if (!lcu) { |
| 219 | spin_unlock_irqrestore(&aliastree.lock, flags); | 220 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| 220 | newlcu = _allocate_lcu(uid); | 221 | newlcu = _allocate_lcu(&uid); |
| 221 | if (IS_ERR(newlcu)) | 222 | if (IS_ERR(newlcu)) |
| 222 | return PTR_ERR(newlcu); | 223 | return PTR_ERR(newlcu); |
| 223 | spin_lock_irqsave(&aliastree.lock, flags); | 224 | spin_lock_irqsave(&aliastree.lock, flags); |
| 224 | lcu = _find_lcu(server, uid); | 225 | lcu = _find_lcu(server, &uid); |
| 225 | if (!lcu) { | 226 | if (!lcu) { |
| 226 | list_add(&newlcu->lcu, &server->lculist); | 227 | list_add(&newlcu->lcu, &server->lculist); |
| 227 | lcu = newlcu; | 228 | lcu = newlcu; |
| @@ -256,20 +257,20 @@ void dasd_alias_lcu_setup_complete(struct dasd_device *device) | |||
| 256 | unsigned long flags; | 257 | unsigned long flags; |
| 257 | struct alias_server *server; | 258 | struct alias_server *server; |
| 258 | struct alias_lcu *lcu; | 259 | struct alias_lcu *lcu; |
| 259 | struct dasd_uid *uid; | 260 | struct dasd_uid uid; |
| 260 | 261 | ||
| 261 | private = (struct dasd_eckd_private *) device->private; | 262 | private = (struct dasd_eckd_private *) device->private; |
| 262 | uid = &private->uid; | 263 | device->discipline->get_uid(device, &uid); |
| 263 | lcu = NULL; | 264 | lcu = NULL; |
| 264 | spin_lock_irqsave(&aliastree.lock, flags); | 265 | spin_lock_irqsave(&aliastree.lock, flags); |
| 265 | server = _find_server(uid); | 266 | server = _find_server(&uid); |
| 266 | if (server) | 267 | if (server) |
| 267 | lcu = _find_lcu(server, uid); | 268 | lcu = _find_lcu(server, &uid); |
| 268 | spin_unlock_irqrestore(&aliastree.lock, flags); | 269 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| 269 | if (!lcu) { | 270 | if (!lcu) { |
| 270 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, | 271 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, |
| 271 | "could not find lcu for %04x %02x", | 272 | "could not find lcu for %04x %02x", |
| 272 | uid->ssid, uid->real_unit_addr); | 273 | uid.ssid, uid.real_unit_addr); |
| 273 | WARN_ON(1); | 274 | WARN_ON(1); |
| 274 | return; | 275 | return; |
| 275 | } | 276 | } |
| @@ -282,20 +283,20 @@ void dasd_alias_wait_for_lcu_setup(struct dasd_device *device) | |||
| 282 | unsigned long flags; | 283 | unsigned long flags; |
| 283 | struct alias_server *server; | 284 | struct alias_server *server; |
| 284 | struct alias_lcu *lcu; | 285 | struct alias_lcu *lcu; |
| 285 | struct dasd_uid *uid; | 286 | struct dasd_uid uid; |
| 286 | 287 | ||
| 287 | private = (struct dasd_eckd_private *) device->private; | 288 | private = (struct dasd_eckd_private *) device->private; |
| 288 | uid = &private->uid; | 289 | device->discipline->get_uid(device, &uid); |
| 289 | lcu = NULL; | 290 | lcu = NULL; |
| 290 | spin_lock_irqsave(&aliastree.lock, flags); | 291 | spin_lock_irqsave(&aliastree.lock, flags); |
| 291 | server = _find_server(uid); | 292 | server = _find_server(&uid); |
| 292 | if (server) | 293 | if (server) |
| 293 | lcu = _find_lcu(server, uid); | 294 | lcu = _find_lcu(server, &uid); |
| 294 | spin_unlock_irqrestore(&aliastree.lock, flags); | 295 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| 295 | if (!lcu) { | 296 | if (!lcu) { |
| 296 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, | 297 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, |
| 297 | "could not find lcu for %04x %02x", | 298 | "could not find lcu for %04x %02x", |
| 298 | uid->ssid, uid->real_unit_addr); | 299 | uid.ssid, uid.real_unit_addr); |
| 299 | WARN_ON(1); | 300 | WARN_ON(1); |
| 300 | return; | 301 | return; |
| 301 | } | 302 | } |
| @@ -314,9 +315,11 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) | |||
| 314 | struct alias_lcu *lcu; | 315 | struct alias_lcu *lcu; |
| 315 | struct alias_server *server; | 316 | struct alias_server *server; |
| 316 | int was_pending; | 317 | int was_pending; |
| 318 | struct dasd_uid uid; | ||
| 317 | 319 | ||
| 318 | private = (struct dasd_eckd_private *) device->private; | 320 | private = (struct dasd_eckd_private *) device->private; |
| 319 | lcu = private->lcu; | 321 | lcu = private->lcu; |
| 322 | device->discipline->get_uid(device, &uid); | ||
| 320 | spin_lock_irqsave(&lcu->lock, flags); | 323 | spin_lock_irqsave(&lcu->lock, flags); |
| 321 | list_del_init(&device->alias_list); | 324 | list_del_init(&device->alias_list); |
| 322 | /* make sure that the workers don't use this device */ | 325 | /* make sure that the workers don't use this device */ |
| @@ -353,7 +356,7 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) | |||
| 353 | _schedule_lcu_update(lcu, NULL); | 356 | _schedule_lcu_update(lcu, NULL); |
| 354 | spin_unlock(&lcu->lock); | 357 | spin_unlock(&lcu->lock); |
| 355 | } | 358 | } |
| 356 | server = _find_server(&private->uid); | 359 | server = _find_server(&uid); |
| 357 | if (server && list_empty(&server->lculist)) { | 360 | if (server && list_empty(&server->lculist)) { |
| 358 | list_del(&server->server); | 361 | list_del(&server->server); |
| 359 | _free_server(server); | 362 | _free_server(server); |
| @@ -366,19 +369,30 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) | |||
| 366 | * in the lcu is up to date and will update the device uid before | 369 | * in the lcu is up to date and will update the device uid before |
| 367 | * adding it to a pav group. | 370 | * adding it to a pav group. |
| 368 | */ | 371 | */ |
| 372 | |||
| 369 | static int _add_device_to_lcu(struct alias_lcu *lcu, | 373 | static int _add_device_to_lcu(struct alias_lcu *lcu, |
| 370 | struct dasd_device *device) | 374 | struct dasd_device *device, |
| 375 | struct dasd_device *pos) | ||
| 371 | { | 376 | { |
| 372 | 377 | ||
| 373 | struct dasd_eckd_private *private; | 378 | struct dasd_eckd_private *private; |
| 374 | struct alias_pav_group *group; | 379 | struct alias_pav_group *group; |
| 375 | struct dasd_uid *uid; | 380 | struct dasd_uid uid; |
| 381 | unsigned long flags; | ||
| 376 | 382 | ||
| 377 | private = (struct dasd_eckd_private *) device->private; | 383 | private = (struct dasd_eckd_private *) device->private; |
| 378 | uid = &private->uid; | 384 | |
| 379 | uid->type = lcu->uac->unit[uid->real_unit_addr].ua_type; | 385 | /* only lock if not already locked */ |
| 380 | uid->base_unit_addr = lcu->uac->unit[uid->real_unit_addr].base_ua; | 386 | if (device != pos) |
| 381 | dasd_set_uid(device->cdev, &private->uid); | 387 | spin_lock_irqsave_nested(get_ccwdev_lock(device->cdev), flags, |
| 388 | CDEV_NESTED_SECOND); | ||
| 389 | private->uid.type = lcu->uac->unit[private->uid.real_unit_addr].ua_type; | ||
| 390 | private->uid.base_unit_addr = | ||
| 391 | lcu->uac->unit[private->uid.real_unit_addr].base_ua; | ||
| 392 | uid = private->uid; | ||
| 393 | |||
| 394 | if (device != pos) | ||
| 395 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 382 | 396 | ||
| 383 | /* if we have no PAV anyway, we don't need to bother with PAV groups */ | 397 | /* if we have no PAV anyway, we don't need to bother with PAV groups */ |
| 384 | if (lcu->pav == NO_PAV) { | 398 | if (lcu->pav == NO_PAV) { |
| @@ -386,25 +400,25 @@ static int _add_device_to_lcu(struct alias_lcu *lcu, | |||
| 386 | return 0; | 400 | return 0; |
| 387 | } | 401 | } |
| 388 | 402 | ||
| 389 | group = _find_group(lcu, uid); | 403 | group = _find_group(lcu, &uid); |
| 390 | if (!group) { | 404 | if (!group) { |
| 391 | group = kzalloc(sizeof(*group), GFP_ATOMIC); | 405 | group = kzalloc(sizeof(*group), GFP_ATOMIC); |
| 392 | if (!group) | 406 | if (!group) |
| 393 | return -ENOMEM; | 407 | return -ENOMEM; |
| 394 | memcpy(group->uid.vendor, uid->vendor, sizeof(uid->vendor)); | 408 | memcpy(group->uid.vendor, uid.vendor, sizeof(uid.vendor)); |
| 395 | memcpy(group->uid.serial, uid->serial, sizeof(uid->serial)); | 409 | memcpy(group->uid.serial, uid.serial, sizeof(uid.serial)); |
| 396 | group->uid.ssid = uid->ssid; | 410 | group->uid.ssid = uid.ssid; |
| 397 | if (uid->type == UA_BASE_DEVICE) | 411 | if (uid.type == UA_BASE_DEVICE) |
| 398 | group->uid.base_unit_addr = uid->real_unit_addr; | 412 | group->uid.base_unit_addr = uid.real_unit_addr; |
| 399 | else | 413 | else |
| 400 | group->uid.base_unit_addr = uid->base_unit_addr; | 414 | group->uid.base_unit_addr = uid.base_unit_addr; |
| 401 | memcpy(group->uid.vduit, uid->vduit, sizeof(uid->vduit)); | 415 | memcpy(group->uid.vduit, uid.vduit, sizeof(uid.vduit)); |
| 402 | INIT_LIST_HEAD(&group->group); | 416 | INIT_LIST_HEAD(&group->group); |
| 403 | INIT_LIST_HEAD(&group->baselist); | 417 | INIT_LIST_HEAD(&group->baselist); |
| 404 | INIT_LIST_HEAD(&group->aliaslist); | 418 | INIT_LIST_HEAD(&group->aliaslist); |
| 405 | list_add(&group->group, &lcu->grouplist); | 419 | list_add(&group->group, &lcu->grouplist); |
| 406 | } | 420 | } |
| 407 | if (uid->type == UA_BASE_DEVICE) | 421 | if (uid.type == UA_BASE_DEVICE) |
| 408 | list_move(&device->alias_list, &group->baselist); | 422 | list_move(&device->alias_list, &group->baselist); |
| 409 | else | 423 | else |
| 410 | list_move(&device->alias_list, &group->aliaslist); | 424 | list_move(&device->alias_list, &group->aliaslist); |
| @@ -525,7 +539,10 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) | |||
| 525 | if (rc) | 539 | if (rc) |
| 526 | return rc; | 540 | return rc; |
| 527 | 541 | ||
| 528 | spin_lock_irqsave(&lcu->lock, flags); | 542 | /* need to take cdev lock before lcu lock */ |
| 543 | spin_lock_irqsave_nested(get_ccwdev_lock(refdev->cdev), flags, | ||
| 544 | CDEV_NESTED_FIRST); | ||
| 545 | spin_lock(&lcu->lock); | ||
| 529 | lcu->pav = NO_PAV; | 546 | lcu->pav = NO_PAV; |
| 530 | for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) { | 547 | for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) { |
| 531 | switch (lcu->uac->unit[i].ua_type) { | 548 | switch (lcu->uac->unit[i].ua_type) { |
| @@ -542,9 +559,10 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) | |||
| 542 | 559 | ||
| 543 | list_for_each_entry_safe(device, tempdev, &lcu->active_devices, | 560 | list_for_each_entry_safe(device, tempdev, &lcu->active_devices, |
| 544 | alias_list) { | 561 | alias_list) { |
| 545 | _add_device_to_lcu(lcu, device); | 562 | _add_device_to_lcu(lcu, device, refdev); |
| 546 | } | 563 | } |
| 547 | spin_unlock_irqrestore(&lcu->lock, flags); | 564 | spin_unlock(&lcu->lock); |
| 565 | spin_unlock_irqrestore(get_ccwdev_lock(refdev->cdev), flags); | ||
| 548 | return 0; | 566 | return 0; |
| 549 | } | 567 | } |
| 550 | 568 | ||
| @@ -628,9 +646,12 @@ int dasd_alias_add_device(struct dasd_device *device) | |||
| 628 | private = (struct dasd_eckd_private *) device->private; | 646 | private = (struct dasd_eckd_private *) device->private; |
| 629 | lcu = private->lcu; | 647 | lcu = private->lcu; |
| 630 | rc = 0; | 648 | rc = 0; |
| 631 | spin_lock_irqsave(&lcu->lock, flags); | 649 | |
| 650 | /* need to take cdev lock before lcu lock */ | ||
| 651 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 652 | spin_lock(&lcu->lock); | ||
| 632 | if (!(lcu->flags & UPDATE_PENDING)) { | 653 | if (!(lcu->flags & UPDATE_PENDING)) { |
| 633 | rc = _add_device_to_lcu(lcu, device); | 654 | rc = _add_device_to_lcu(lcu, device, device); |
| 634 | if (rc) | 655 | if (rc) |
| 635 | lcu->flags |= UPDATE_PENDING; | 656 | lcu->flags |= UPDATE_PENDING; |
| 636 | } | 657 | } |
| @@ -638,10 +659,19 @@ int dasd_alias_add_device(struct dasd_device *device) | |||
| 638 | list_move(&device->alias_list, &lcu->active_devices); | 659 | list_move(&device->alias_list, &lcu->active_devices); |
| 639 | _schedule_lcu_update(lcu, device); | 660 | _schedule_lcu_update(lcu, device); |
| 640 | } | 661 | } |
| 641 | spin_unlock_irqrestore(&lcu->lock, flags); | 662 | spin_unlock(&lcu->lock); |
| 663 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 642 | return rc; | 664 | return rc; |
| 643 | } | 665 | } |
| 644 | 666 | ||
| 667 | int dasd_alias_update_add_device(struct dasd_device *device) | ||
| 668 | { | ||
| 669 | struct dasd_eckd_private *private; | ||
| 670 | private = (struct dasd_eckd_private *) device->private; | ||
| 671 | private->lcu->flags |= UPDATE_PENDING; | ||
| 672 | return dasd_alias_add_device(device); | ||
| 673 | } | ||
| 674 | |||
| 645 | int dasd_alias_remove_device(struct dasd_device *device) | 675 | int dasd_alias_remove_device(struct dasd_device *device) |
| 646 | { | 676 | { |
| 647 | struct dasd_eckd_private *private; | 677 | struct dasd_eckd_private *private; |
| @@ -740,19 +770,30 @@ static void _restart_all_base_devices_on_lcu(struct alias_lcu *lcu) | |||
| 740 | struct alias_pav_group *pavgroup; | 770 | struct alias_pav_group *pavgroup; |
| 741 | struct dasd_device *device; | 771 | struct dasd_device *device; |
| 742 | struct dasd_eckd_private *private; | 772 | struct dasd_eckd_private *private; |
| 773 | unsigned long flags; | ||
| 743 | 774 | ||
| 744 | /* active and inactive list can contain alias as well as base devices */ | 775 | /* active and inactive list can contain alias as well as base devices */ |
| 745 | list_for_each_entry(device, &lcu->active_devices, alias_list) { | 776 | list_for_each_entry(device, &lcu->active_devices, alias_list) { |
| 746 | private = (struct dasd_eckd_private *) device->private; | 777 | private = (struct dasd_eckd_private *) device->private; |
| 747 | if (private->uid.type != UA_BASE_DEVICE) | 778 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
| 779 | if (private->uid.type != UA_BASE_DEVICE) { | ||
| 780 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), | ||
| 781 | flags); | ||
| 748 | continue; | 782 | continue; |
| 783 | } | ||
| 784 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 749 | dasd_schedule_block_bh(device->block); | 785 | dasd_schedule_block_bh(device->block); |
| 750 | dasd_schedule_device_bh(device); | 786 | dasd_schedule_device_bh(device); |
| 751 | } | 787 | } |
| 752 | list_for_each_entry(device, &lcu->inactive_devices, alias_list) { | 788 | list_for_each_entry(device, &lcu->inactive_devices, alias_list) { |
| 753 | private = (struct dasd_eckd_private *) device->private; | 789 | private = (struct dasd_eckd_private *) device->private; |
| 754 | if (private->uid.type != UA_BASE_DEVICE) | 790 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
| 791 | if (private->uid.type != UA_BASE_DEVICE) { | ||
| 792 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), | ||
| 793 | flags); | ||
| 755 | continue; | 794 | continue; |
| 795 | } | ||
| 796 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 756 | dasd_schedule_block_bh(device->block); | 797 | dasd_schedule_block_bh(device->block); |
| 757 | dasd_schedule_device_bh(device); | 798 | dasd_schedule_device_bh(device); |
| 758 | } | 799 | } |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index eff9c812c5c2..34d51dd4c539 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
| @@ -49,7 +49,6 @@ struct dasd_devmap { | |||
| 49 | unsigned int devindex; | 49 | unsigned int devindex; |
| 50 | unsigned short features; | 50 | unsigned short features; |
| 51 | struct dasd_device *device; | 51 | struct dasd_device *device; |
| 52 | struct dasd_uid uid; | ||
| 53 | }; | 52 | }; |
| 54 | 53 | ||
| 55 | /* | 54 | /* |
| @@ -936,42 +935,46 @@ dasd_device_status_show(struct device *dev, struct device_attribute *attr, | |||
| 936 | 935 | ||
| 937 | static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL); | 936 | static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL); |
| 938 | 937 | ||
| 939 | static ssize_t | 938 | static ssize_t dasd_alias_show(struct device *dev, |
| 940 | dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf) | 939 | struct device_attribute *attr, char *buf) |
| 941 | { | 940 | { |
| 942 | struct dasd_devmap *devmap; | 941 | struct dasd_device *device; |
| 943 | int alias; | 942 | struct dasd_uid uid; |
| 944 | 943 | ||
| 945 | devmap = dasd_find_busid(dev_name(dev)); | 944 | device = dasd_device_from_cdev(to_ccwdev(dev)); |
| 946 | spin_lock(&dasd_devmap_lock); | 945 | if (IS_ERR(device)) |
| 947 | if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { | ||
| 948 | spin_unlock(&dasd_devmap_lock); | ||
| 949 | return sprintf(buf, "0\n"); | 946 | return sprintf(buf, "0\n"); |
| 947 | |||
| 948 | if (device->discipline && device->discipline->get_uid && | ||
| 949 | !device->discipline->get_uid(device, &uid)) { | ||
| 950 | if (uid.type == UA_BASE_PAV_ALIAS || | ||
| 951 | uid.type == UA_HYPER_PAV_ALIAS) | ||
| 952 | return sprintf(buf, "1\n"); | ||
| 950 | } | 953 | } |
| 951 | if (devmap->uid.type == UA_BASE_PAV_ALIAS || | 954 | dasd_put_device(device); |
| 952 | devmap->uid.type == UA_HYPER_PAV_ALIAS) | 955 | |
| 953 | alias = 1; | 956 | return sprintf(buf, "0\n"); |
| 954 | else | ||
| 955 | alias = 0; | ||
| 956 | spin_unlock(&dasd_devmap_lock); | ||
| 957 | return sprintf(buf, alias ? "1\n" : "0\n"); | ||
| 958 | } | 957 | } |
| 959 | 958 | ||
| 960 | static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL); | 959 | static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL); |
| 961 | 960 | ||
| 962 | static ssize_t | 961 | static ssize_t dasd_vendor_show(struct device *dev, |
| 963 | dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf) | 962 | struct device_attribute *attr, char *buf) |
| 964 | { | 963 | { |
| 965 | struct dasd_devmap *devmap; | 964 | struct dasd_device *device; |
| 965 | struct dasd_uid uid; | ||
| 966 | char *vendor; | 966 | char *vendor; |
| 967 | 967 | ||
| 968 | devmap = dasd_find_busid(dev_name(dev)); | 968 | device = dasd_device_from_cdev(to_ccwdev(dev)); |
| 969 | spin_lock(&dasd_devmap_lock); | 969 | vendor = ""; |
| 970 | if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0) | 970 | if (IS_ERR(device)) |
| 971 | vendor = devmap->uid.vendor; | 971 | return snprintf(buf, PAGE_SIZE, "%s\n", vendor); |
| 972 | else | 972 | |
| 973 | vendor = ""; | 973 | if (device->discipline && device->discipline->get_uid && |
| 974 | spin_unlock(&dasd_devmap_lock); | 974 | !device->discipline->get_uid(device, &uid)) |
| 975 | vendor = uid.vendor; | ||
| 976 | |||
| 977 | dasd_put_device(device); | ||
| 975 | 978 | ||
| 976 | return snprintf(buf, PAGE_SIZE, "%s\n", vendor); | 979 | return snprintf(buf, PAGE_SIZE, "%s\n", vendor); |
| 977 | } | 980 | } |
| @@ -985,48 +988,51 @@ static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL); | |||
| 985 | static ssize_t | 988 | static ssize_t |
| 986 | dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf) | 989 | dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf) |
| 987 | { | 990 | { |
| 988 | struct dasd_devmap *devmap; | 991 | struct dasd_device *device; |
| 992 | struct dasd_uid uid; | ||
| 989 | char uid_string[UID_STRLEN]; | 993 | char uid_string[UID_STRLEN]; |
| 990 | char ua_string[3]; | 994 | char ua_string[3]; |
| 991 | struct dasd_uid *uid; | ||
| 992 | 995 | ||
| 993 | devmap = dasd_find_busid(dev_name(dev)); | 996 | device = dasd_device_from_cdev(to_ccwdev(dev)); |
| 994 | spin_lock(&dasd_devmap_lock); | 997 | uid_string[0] = 0; |
| 995 | if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { | 998 | if (IS_ERR(device)) |
| 996 | spin_unlock(&dasd_devmap_lock); | 999 | return snprintf(buf, PAGE_SIZE, "%s\n", uid_string); |
| 997 | return sprintf(buf, "\n"); | 1000 | |
| 998 | } | 1001 | if (device->discipline && device->discipline->get_uid && |
| 999 | uid = &devmap->uid; | 1002 | !device->discipline->get_uid(device, &uid)) { |
| 1000 | switch (uid->type) { | 1003 | switch (uid.type) { |
| 1001 | case UA_BASE_DEVICE: | 1004 | case UA_BASE_DEVICE: |
| 1002 | sprintf(ua_string, "%02x", uid->real_unit_addr); | 1005 | snprintf(ua_string, sizeof(ua_string), "%02x", |
| 1003 | break; | 1006 | uid.real_unit_addr); |
| 1004 | case UA_BASE_PAV_ALIAS: | 1007 | break; |
| 1005 | sprintf(ua_string, "%02x", uid->base_unit_addr); | 1008 | case UA_BASE_PAV_ALIAS: |
| 1006 | break; | 1009 | snprintf(ua_string, sizeof(ua_string), "%02x", |
| 1007 | case UA_HYPER_PAV_ALIAS: | 1010 | uid.base_unit_addr); |
| 1008 | sprintf(ua_string, "xx"); | 1011 | break; |
| 1009 | break; | 1012 | case UA_HYPER_PAV_ALIAS: |
| 1010 | default: | 1013 | snprintf(ua_string, sizeof(ua_string), "xx"); |
| 1011 | /* should not happen, treat like base device */ | 1014 | break; |
| 1012 | sprintf(ua_string, "%02x", uid->real_unit_addr); | 1015 | default: |
| 1013 | break; | 1016 | /* should not happen, treat like base device */ |
| 1017 | snprintf(ua_string, sizeof(ua_string), "%02x", | ||
| 1018 | uid.real_unit_addr); | ||
| 1019 | break; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | if (strlen(uid.vduit) > 0) | ||
| 1023 | snprintf(uid_string, sizeof(uid_string), | ||
| 1024 | "%s.%s.%04x.%s.%s", | ||
| 1025 | uid.vendor, uid.serial, uid.ssid, ua_string, | ||
| 1026 | uid.vduit); | ||
| 1027 | else | ||
| 1028 | snprintf(uid_string, sizeof(uid_string), | ||
| 1029 | "%s.%s.%04x.%s", | ||
| 1030 | uid.vendor, uid.serial, uid.ssid, ua_string); | ||
| 1014 | } | 1031 | } |
| 1015 | if (strlen(uid->vduit) > 0) | 1032 | dasd_put_device(device); |
| 1016 | snprintf(uid_string, sizeof(uid_string), | 1033 | |
| 1017 | "%s.%s.%04x.%s.%s", | ||
| 1018 | uid->vendor, uid->serial, | ||
| 1019 | uid->ssid, ua_string, | ||
| 1020 | uid->vduit); | ||
| 1021 | else | ||
| 1022 | snprintf(uid_string, sizeof(uid_string), | ||
| 1023 | "%s.%s.%04x.%s", | ||
| 1024 | uid->vendor, uid->serial, | ||
| 1025 | uid->ssid, ua_string); | ||
| 1026 | spin_unlock(&dasd_devmap_lock); | ||
| 1027 | return snprintf(buf, PAGE_SIZE, "%s\n", uid_string); | 1034 | return snprintf(buf, PAGE_SIZE, "%s\n", uid_string); |
| 1028 | } | 1035 | } |
| 1029 | |||
| 1030 | static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL); | 1036 | static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL); |
| 1031 | 1037 | ||
| 1032 | /* | 1038 | /* |
| @@ -1094,50 +1100,6 @@ static struct attribute_group dasd_attr_group = { | |||
| 1094 | }; | 1100 | }; |
| 1095 | 1101 | ||
| 1096 | /* | 1102 | /* |
| 1097 | * Return copy of the device unique identifier. | ||
| 1098 | */ | ||
| 1099 | int | ||
| 1100 | dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) | ||
| 1101 | { | ||
| 1102 | struct dasd_devmap *devmap; | ||
| 1103 | |||
| 1104 | devmap = dasd_find_busid(dev_name(&cdev->dev)); | ||
| 1105 | if (IS_ERR(devmap)) | ||
| 1106 | return PTR_ERR(devmap); | ||
| 1107 | spin_lock(&dasd_devmap_lock); | ||
| 1108 | *uid = devmap->uid; | ||
| 1109 | spin_unlock(&dasd_devmap_lock); | ||
| 1110 | return 0; | ||
| 1111 | } | ||
| 1112 | EXPORT_SYMBOL_GPL(dasd_get_uid); | ||
| 1113 | |||
| 1114 | /* | ||
| 1115 | * Register the given device unique identifier into devmap struct. | ||
| 1116 | * In addition check if the related storage server subsystem ID is already | ||
| 1117 | * contained in the dasd_server_ssid_list. If subsystem ID is not contained, | ||
| 1118 | * create new entry. | ||
| 1119 | * Return 0 if server was already in serverlist, | ||
| 1120 | * 1 if the server was added successful | ||
| 1121 | * <0 in case of error. | ||
| 1122 | */ | ||
| 1123 | int | ||
| 1124 | dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) | ||
| 1125 | { | ||
| 1126 | struct dasd_devmap *devmap; | ||
| 1127 | |||
| 1128 | devmap = dasd_find_busid(dev_name(&cdev->dev)); | ||
| 1129 | if (IS_ERR(devmap)) | ||
| 1130 | return PTR_ERR(devmap); | ||
| 1131 | |||
| 1132 | spin_lock(&dasd_devmap_lock); | ||
| 1133 | devmap->uid = *uid; | ||
| 1134 | spin_unlock(&dasd_devmap_lock); | ||
| 1135 | |||
| 1136 | return 0; | ||
| 1137 | } | ||
| 1138 | EXPORT_SYMBOL_GPL(dasd_set_uid); | ||
| 1139 | |||
| 1140 | /* | ||
| 1141 | * Return value of the specified feature. | 1103 | * Return value of the specified feature. |
| 1142 | */ | 1104 | */ |
| 1143 | int | 1105 | int |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 0cb233116855..5b1cd8d6e971 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -692,18 +692,20 @@ dasd_eckd_cdl_reclen(int recid) | |||
| 692 | /* | 692 | /* |
| 693 | * Generate device unique id that specifies the physical device. | 693 | * Generate device unique id that specifies the physical device. |
| 694 | */ | 694 | */ |
| 695 | static int dasd_eckd_generate_uid(struct dasd_device *device, | 695 | static int dasd_eckd_generate_uid(struct dasd_device *device) |
| 696 | struct dasd_uid *uid) | ||
| 697 | { | 696 | { |
| 698 | struct dasd_eckd_private *private; | 697 | struct dasd_eckd_private *private; |
| 698 | struct dasd_uid *uid; | ||
| 699 | int count; | 699 | int count; |
| 700 | unsigned long flags; | ||
| 700 | 701 | ||
| 701 | private = (struct dasd_eckd_private *) device->private; | 702 | private = (struct dasd_eckd_private *) device->private; |
| 702 | if (!private) | 703 | if (!private) |
| 703 | return -ENODEV; | 704 | return -ENODEV; |
| 704 | if (!private->ned || !private->gneq) | 705 | if (!private->ned || !private->gneq) |
| 705 | return -ENODEV; | 706 | return -ENODEV; |
| 706 | 707 | uid = &private->uid; | |
| 708 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 707 | memset(uid, 0, sizeof(struct dasd_uid)); | 709 | memset(uid, 0, sizeof(struct dasd_uid)); |
| 708 | memcpy(uid->vendor, private->ned->HDA_manufacturer, | 710 | memcpy(uid->vendor, private->ned->HDA_manufacturer, |
| 709 | sizeof(uid->vendor) - 1); | 711 | sizeof(uid->vendor) - 1); |
| @@ -726,9 +728,25 @@ static int dasd_eckd_generate_uid(struct dasd_device *device, | |||
| 726 | private->vdsneq->uit[count]); | 728 | private->vdsneq->uit[count]); |
| 727 | } | 729 | } |
| 728 | } | 730 | } |
| 731 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 729 | return 0; | 732 | return 0; |
| 730 | } | 733 | } |
| 731 | 734 | ||
| 735 | static int dasd_eckd_get_uid(struct dasd_device *device, struct dasd_uid *uid) | ||
| 736 | { | ||
| 737 | struct dasd_eckd_private *private; | ||
| 738 | unsigned long flags; | ||
| 739 | |||
| 740 | if (device->private) { | ||
| 741 | private = (struct dasd_eckd_private *)device->private; | ||
| 742 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 743 | *uid = private->uid; | ||
| 744 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 745 | return 0; | ||
| 746 | } | ||
| 747 | return -EINVAL; | ||
| 748 | } | ||
| 749 | |||
| 732 | static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, | 750 | static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, |
| 733 | void *rcd_buffer, | 751 | void *rcd_buffer, |
| 734 | struct ciw *ciw, __u8 lpm) | 752 | struct ciw *ciw, __u8 lpm) |
| @@ -1088,6 +1106,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
| 1088 | { | 1106 | { |
| 1089 | struct dasd_eckd_private *private; | 1107 | struct dasd_eckd_private *private; |
| 1090 | struct dasd_block *block; | 1108 | struct dasd_block *block; |
| 1109 | struct dasd_uid temp_uid; | ||
| 1091 | int is_known, rc; | 1110 | int is_known, rc; |
| 1092 | int readonly; | 1111 | int readonly; |
| 1093 | 1112 | ||
| @@ -1124,13 +1143,13 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
| 1124 | if (rc) | 1143 | if (rc) |
| 1125 | goto out_err1; | 1144 | goto out_err1; |
| 1126 | 1145 | ||
| 1127 | /* Generate device unique id and register in devmap */ | 1146 | /* Generate device unique id */ |
| 1128 | rc = dasd_eckd_generate_uid(device, &private->uid); | 1147 | rc = dasd_eckd_generate_uid(device); |
| 1129 | if (rc) | 1148 | if (rc) |
| 1130 | goto out_err1; | 1149 | goto out_err1; |
| 1131 | dasd_set_uid(device->cdev, &private->uid); | ||
| 1132 | 1150 | ||
| 1133 | if (private->uid.type == UA_BASE_DEVICE) { | 1151 | dasd_eckd_get_uid(device, &temp_uid); |
| 1152 | if (temp_uid.type == UA_BASE_DEVICE) { | ||
| 1134 | block = dasd_alloc_block(); | 1153 | block = dasd_alloc_block(); |
| 1135 | if (IS_ERR(block)) { | 1154 | if (IS_ERR(block)) { |
| 1136 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", | 1155 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", |
| @@ -1451,6 +1470,7 @@ static int dasd_eckd_ready_to_online(struct dasd_device *device) | |||
| 1451 | 1470 | ||
| 1452 | static int dasd_eckd_online_to_ready(struct dasd_device *device) | 1471 | static int dasd_eckd_online_to_ready(struct dasd_device *device) |
| 1453 | { | 1472 | { |
| 1473 | cancel_work_sync(&device->reload_device); | ||
| 1454 | return dasd_alias_remove_device(device); | 1474 | return dasd_alias_remove_device(device); |
| 1455 | }; | 1475 | }; |
| 1456 | 1476 | ||
| @@ -1709,10 +1729,27 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, | |||
| 1709 | { | 1729 | { |
| 1710 | char mask; | 1730 | char mask; |
| 1711 | char *sense = NULL; | 1731 | char *sense = NULL; |
| 1732 | struct dasd_eckd_private *private; | ||
| 1712 | 1733 | ||
| 1734 | private = (struct dasd_eckd_private *) device->private; | ||
| 1713 | /* first of all check for state change pending interrupt */ | 1735 | /* first of all check for state change pending interrupt */ |
| 1714 | mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; | 1736 | mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; |
| 1715 | if ((scsw_dstat(&irb->scsw) & mask) == mask) { | 1737 | if ((scsw_dstat(&irb->scsw) & mask) == mask) { |
| 1738 | /* for alias only and not in offline processing*/ | ||
| 1739 | if (!device->block && private->lcu && | ||
| 1740 | !test_bit(DASD_FLAG_OFFLINE, &device->flags)) { | ||
| 1741 | /* | ||
| 1742 | * the state change could be caused by an alias | ||
| 1743 | * reassignment remove device from alias handling | ||
| 1744 | * to prevent new requests from being scheduled on | ||
| 1745 | * the wrong alias device | ||
| 1746 | */ | ||
| 1747 | dasd_alias_remove_device(device); | ||
| 1748 | |||
| 1749 | /* schedule worker to reload device */ | ||
| 1750 | dasd_reload_device(device); | ||
| 1751 | } | ||
| 1752 | |||
| 1716 | dasd_generic_handle_state_change(device); | 1753 | dasd_generic_handle_state_change(device); |
| 1717 | return; | 1754 | return; |
| 1718 | } | 1755 | } |
| @@ -3259,7 +3296,7 @@ static void dasd_eckd_dump_sense(struct dasd_device *device, | |||
| 3259 | dasd_eckd_dump_sense_ccw(device, req, irb); | 3296 | dasd_eckd_dump_sense_ccw(device, req, irb); |
| 3260 | } | 3297 | } |
| 3261 | 3298 | ||
| 3262 | int dasd_eckd_pm_freeze(struct dasd_device *device) | 3299 | static int dasd_eckd_pm_freeze(struct dasd_device *device) |
| 3263 | { | 3300 | { |
| 3264 | /* | 3301 | /* |
| 3265 | * the device should be disconnected from our LCU structure | 3302 | * the device should be disconnected from our LCU structure |
| @@ -3272,7 +3309,7 @@ int dasd_eckd_pm_freeze(struct dasd_device *device) | |||
| 3272 | return 0; | 3309 | return 0; |
| 3273 | } | 3310 | } |
| 3274 | 3311 | ||
| 3275 | int dasd_eckd_restore_device(struct dasd_device *device) | 3312 | static int dasd_eckd_restore_device(struct dasd_device *device) |
| 3276 | { | 3313 | { |
| 3277 | struct dasd_eckd_private *private; | 3314 | struct dasd_eckd_private *private; |
| 3278 | struct dasd_eckd_characteristics temp_rdc_data; | 3315 | struct dasd_eckd_characteristics temp_rdc_data; |
| @@ -3287,15 +3324,16 @@ int dasd_eckd_restore_device(struct dasd_device *device) | |||
| 3287 | if (rc) | 3324 | if (rc) |
| 3288 | goto out_err; | 3325 | goto out_err; |
| 3289 | 3326 | ||
| 3290 | /* Generate device unique id and register in devmap */ | 3327 | dasd_eckd_get_uid(device, &temp_uid); |
| 3291 | rc = dasd_eckd_generate_uid(device, &private->uid); | 3328 | /* Generate device unique id */ |
| 3292 | dasd_get_uid(device->cdev, &temp_uid); | 3329 | rc = dasd_eckd_generate_uid(device); |
| 3330 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 3293 | if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0) | 3331 | if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0) |
| 3294 | dev_err(&device->cdev->dev, "The UID of the DASD has " | 3332 | dev_err(&device->cdev->dev, "The UID of the DASD has " |
| 3295 | "changed\n"); | 3333 | "changed\n"); |
| 3334 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 3296 | if (rc) | 3335 | if (rc) |
| 3297 | goto out_err; | 3336 | goto out_err; |
| 3298 | dasd_set_uid(device->cdev, &private->uid); | ||
| 3299 | 3337 | ||
| 3300 | /* register lcu with alias handling, enable PAV if this is a new lcu */ | 3338 | /* register lcu with alias handling, enable PAV if this is a new lcu */ |
| 3301 | is_known = dasd_alias_make_device_known_to_lcu(device); | 3339 | is_known = dasd_alias_make_device_known_to_lcu(device); |
| @@ -3336,6 +3374,56 @@ out_err: | |||
| 3336 | return -1; | 3374 | return -1; |
| 3337 | } | 3375 | } |
| 3338 | 3376 | ||
| 3377 | static int dasd_eckd_reload_device(struct dasd_device *device) | ||
| 3378 | { | ||
| 3379 | struct dasd_eckd_private *private; | ||
| 3380 | int rc, old_base; | ||
| 3381 | char print_uid[60]; | ||
| 3382 | struct dasd_uid uid; | ||
| 3383 | unsigned long flags; | ||
| 3384 | |||
| 3385 | private = (struct dasd_eckd_private *) device->private; | ||
| 3386 | |||
| 3387 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 3388 | old_base = private->uid.base_unit_addr; | ||
| 3389 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 3390 | |||
| 3391 | /* Read Configuration Data */ | ||
| 3392 | rc = dasd_eckd_read_conf(device); | ||
| 3393 | if (rc) | ||
| 3394 | goto out_err; | ||
| 3395 | |||
| 3396 | rc = dasd_eckd_generate_uid(device); | ||
| 3397 | if (rc) | ||
| 3398 | goto out_err; | ||
| 3399 | /* | ||
| 3400 | * update unit address configuration and | ||
| 3401 | * add device to alias management | ||
| 3402 | */ | ||
| 3403 | dasd_alias_update_add_device(device); | ||
| 3404 | |||
| 3405 | dasd_eckd_get_uid(device, &uid); | ||
| 3406 | |||
| 3407 | if (old_base != uid.base_unit_addr) { | ||
| 3408 | if (strlen(uid.vduit) > 0) | ||
| 3409 | snprintf(print_uid, sizeof(print_uid), | ||
| 3410 | "%s.%s.%04x.%02x.%s", uid.vendor, uid.serial, | ||
| 3411 | uid.ssid, uid.base_unit_addr, uid.vduit); | ||
| 3412 | else | ||
| 3413 | snprintf(print_uid, sizeof(print_uid), | ||
| 3414 | "%s.%s.%04x.%02x", uid.vendor, uid.serial, | ||
| 3415 | uid.ssid, uid.base_unit_addr); | ||
| 3416 | |||
| 3417 | dev_info(&device->cdev->dev, | ||
| 3418 | "An Alias device was reassigned to a new base device " | ||
| 3419 | "with UID: %s\n", print_uid); | ||
| 3420 | } | ||
| 3421 | return 0; | ||
| 3422 | |||
| 3423 | out_err: | ||
| 3424 | return -1; | ||
| 3425 | } | ||
| 3426 | |||
| 3339 | static struct ccw_driver dasd_eckd_driver = { | 3427 | static struct ccw_driver dasd_eckd_driver = { |
| 3340 | .name = "dasd-eckd", | 3428 | .name = "dasd-eckd", |
| 3341 | .owner = THIS_MODULE, | 3429 | .owner = THIS_MODULE, |
| @@ -3389,6 +3477,8 @@ static struct dasd_discipline dasd_eckd_discipline = { | |||
| 3389 | .ioctl = dasd_eckd_ioctl, | 3477 | .ioctl = dasd_eckd_ioctl, |
| 3390 | .freeze = dasd_eckd_pm_freeze, | 3478 | .freeze = dasd_eckd_pm_freeze, |
| 3391 | .restore = dasd_eckd_restore_device, | 3479 | .restore = dasd_eckd_restore_device, |
| 3480 | .reload = dasd_eckd_reload_device, | ||
| 3481 | .get_uid = dasd_eckd_get_uid, | ||
| 3392 | }; | 3482 | }; |
| 3393 | 3483 | ||
| 3394 | static int __init | 3484 | static int __init |
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 864d53c04201..dd6385a5af14 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h | |||
| @@ -426,7 +426,6 @@ struct alias_pav_group { | |||
| 426 | struct dasd_device *next; | 426 | struct dasd_device *next; |
| 427 | }; | 427 | }; |
| 428 | 428 | ||
| 429 | |||
| 430 | struct dasd_eckd_private { | 429 | struct dasd_eckd_private { |
| 431 | struct dasd_eckd_characteristics rdc_data; | 430 | struct dasd_eckd_characteristics rdc_data; |
| 432 | u8 *conf_data; | 431 | u8 *conf_data; |
| @@ -463,4 +462,5 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *, struct irb *); | |||
| 463 | void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *); | 462 | void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *); |
| 464 | void dasd_alias_lcu_setup_complete(struct dasd_device *); | 463 | void dasd_alias_lcu_setup_complete(struct dasd_device *); |
| 465 | void dasd_alias_wait_for_lcu_setup(struct dasd_device *); | 464 | void dasd_alias_wait_for_lcu_setup(struct dasd_device *); |
| 465 | int dasd_alias_update_add_device(struct dasd_device *); | ||
| 466 | #endif /* DASD_ECKD_H */ | 466 | #endif /* DASD_ECKD_H */ |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index a91d4a97d4f2..32fac186ba3f 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
| @@ -81,6 +81,10 @@ struct dasd_block; | |||
| 81 | #define DASD_SIM_MSG_TO_OP 0x03 | 81 | #define DASD_SIM_MSG_TO_OP 0x03 |
| 82 | #define DASD_SIM_LOG 0x0C | 82 | #define DASD_SIM_LOG 0x0C |
| 83 | 83 | ||
| 84 | /* lock class for nested cdev lock */ | ||
| 85 | #define CDEV_NESTED_FIRST 1 | ||
| 86 | #define CDEV_NESTED_SECOND 2 | ||
| 87 | |||
| 84 | /* | 88 | /* |
| 85 | * SECTION: MACROs for klogd and s390 debug feature (dbf) | 89 | * SECTION: MACROs for klogd and s390 debug feature (dbf) |
| 86 | */ | 90 | */ |
| @@ -229,6 +233,24 @@ struct dasd_ccw_req { | |||
| 229 | typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *); | 233 | typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *); |
| 230 | 234 | ||
| 231 | /* | 235 | /* |
| 236 | * Unique identifier for dasd device. | ||
| 237 | */ | ||
| 238 | #define UA_NOT_CONFIGURED 0x00 | ||
| 239 | #define UA_BASE_DEVICE 0x01 | ||
| 240 | #define UA_BASE_PAV_ALIAS 0x02 | ||
| 241 | #define UA_HYPER_PAV_ALIAS 0x03 | ||
| 242 | |||
| 243 | struct dasd_uid { | ||
| 244 | __u8 type; | ||
| 245 | char vendor[4]; | ||
| 246 | char serial[15]; | ||
| 247 | __u16 ssid; | ||
| 248 | __u8 real_unit_addr; | ||
| 249 | __u8 base_unit_addr; | ||
| 250 | char vduit[33]; | ||
| 251 | }; | ||
| 252 | |||
| 253 | /* | ||
| 232 | * the struct dasd_discipline is | 254 | * the struct dasd_discipline is |
| 233 | * sth like a table of virtual functions, if you think of dasd_eckd | 255 | * sth like a table of virtual functions, if you think of dasd_eckd |
| 234 | * inheriting dasd... | 256 | * inheriting dasd... |
| @@ -312,28 +334,15 @@ struct dasd_discipline { | |||
| 312 | /* suspend/resume functions */ | 334 | /* suspend/resume functions */ |
| 313 | int (*freeze) (struct dasd_device *); | 335 | int (*freeze) (struct dasd_device *); |
| 314 | int (*restore) (struct dasd_device *); | 336 | int (*restore) (struct dasd_device *); |
| 315 | }; | ||
| 316 | 337 | ||
| 317 | extern struct dasd_discipline *dasd_diag_discipline_pointer; | 338 | /* reload device after state change */ |
| 318 | 339 | int (*reload) (struct dasd_device *); | |
| 319 | /* | ||
| 320 | * Unique identifier for dasd device. | ||
| 321 | */ | ||
| 322 | #define UA_NOT_CONFIGURED 0x00 | ||
| 323 | #define UA_BASE_DEVICE 0x01 | ||
| 324 | #define UA_BASE_PAV_ALIAS 0x02 | ||
| 325 | #define UA_HYPER_PAV_ALIAS 0x03 | ||
| 326 | 340 | ||
| 327 | struct dasd_uid { | 341 | int (*get_uid) (struct dasd_device *, struct dasd_uid *); |
| 328 | __u8 type; | ||
| 329 | char vendor[4]; | ||
| 330 | char serial[15]; | ||
| 331 | __u16 ssid; | ||
| 332 | __u8 real_unit_addr; | ||
| 333 | __u8 base_unit_addr; | ||
| 334 | char vduit[33]; | ||
| 335 | }; | 342 | }; |
| 336 | 343 | ||
| 344 | extern struct dasd_discipline *dasd_diag_discipline_pointer; | ||
| 345 | |||
| 337 | /* | 346 | /* |
| 338 | * Notification numbers for extended error reporting notifications: | 347 | * Notification numbers for extended error reporting notifications: |
| 339 | * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's | 348 | * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's |
| @@ -386,6 +395,7 @@ struct dasd_device { | |||
| 386 | struct tasklet_struct tasklet; | 395 | struct tasklet_struct tasklet; |
| 387 | struct work_struct kick_work; | 396 | struct work_struct kick_work; |
| 388 | struct work_struct restore_device; | 397 | struct work_struct restore_device; |
| 398 | struct work_struct reload_device; | ||
| 389 | struct timer_list timer; | 399 | struct timer_list timer; |
| 390 | 400 | ||
| 391 | debug_info_t *debug_area; | 401 | debug_info_t *debug_area; |
| @@ -582,6 +592,7 @@ void dasd_enable_device(struct dasd_device *); | |||
| 582 | void dasd_set_target_state(struct dasd_device *, int); | 592 | void dasd_set_target_state(struct dasd_device *, int); |
| 583 | void dasd_kick_device(struct dasd_device *); | 593 | void dasd_kick_device(struct dasd_device *); |
| 584 | void dasd_restore_device(struct dasd_device *); | 594 | void dasd_restore_device(struct dasd_device *); |
| 595 | void dasd_reload_device(struct dasd_device *); | ||
| 585 | 596 | ||
| 586 | void dasd_add_request_head(struct dasd_ccw_req *); | 597 | void dasd_add_request_head(struct dasd_ccw_req *); |
| 587 | void dasd_add_request_tail(struct dasd_ccw_req *); | 598 | void dasd_add_request_tail(struct dasd_ccw_req *); |
| @@ -629,8 +640,6 @@ void dasd_devmap_exit(void); | |||
| 629 | struct dasd_device *dasd_create_device(struct ccw_device *); | 640 | struct dasd_device *dasd_create_device(struct ccw_device *); |
| 630 | void dasd_delete_device(struct dasd_device *); | 641 | void dasd_delete_device(struct dasd_device *); |
| 631 | 642 | ||
| 632 | int dasd_get_uid(struct ccw_device *, struct dasd_uid *); | ||
| 633 | int dasd_set_uid(struct ccw_device *, struct dasd_uid *); | ||
| 634 | int dasd_get_feature(struct ccw_device *, int); | 643 | int dasd_get_feature(struct ccw_device *, int); |
| 635 | int dasd_set_feature(struct ccw_device *, int, int); | 644 | int dasd_set_feature(struct ccw_device *, int, int); |
| 636 | 645 | ||
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig index 4e34d3686c23..40834f18754c 100644 --- a/drivers/s390/char/Kconfig +++ b/drivers/s390/char/Kconfig | |||
| @@ -148,13 +148,12 @@ config VMLOGRDR | |||
| 148 | This driver depends on the IUCV support driver. | 148 | This driver depends on the IUCV support driver. |
| 149 | 149 | ||
| 150 | config VMCP | 150 | config VMCP |
| 151 | tristate "Support for the z/VM CP interface (VM only)" | 151 | bool "Support for the z/VM CP interface" |
| 152 | depends on S390 | 152 | depends on S390 |
| 153 | help | 153 | help |
| 154 | Select this option if you want to be able to interact with the control | 154 | Select this option if you want to be able to interact with the control |
| 155 | program on z/VM | 155 | program on z/VM |
| 156 | 156 | ||
| 157 | |||
| 158 | config MONREADER | 157 | config MONREADER |
| 159 | tristate "API for reading z/VM monitor service records" | 158 | tristate "API for reading z/VM monitor service records" |
| 160 | depends on IUCV | 159 | depends on IUCV |
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 0eabcca3c92d..857dfcb7b359 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c | |||
| @@ -484,6 +484,7 @@ fs3270_open(struct inode *inode, struct file *filp) | |||
| 484 | raw3270_del_view(&fp->view); | 484 | raw3270_del_view(&fp->view); |
| 485 | goto out; | 485 | goto out; |
| 486 | } | 486 | } |
| 487 | nonseekable_open(inode, filp); | ||
| 487 | filp->private_data = fp; | 488 | filp->private_data = fp; |
| 488 | out: | 489 | out: |
| 489 | mutex_unlock(&fs3270_mutex); | 490 | mutex_unlock(&fs3270_mutex); |
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index cb6bffe7141a..18d9a497863b 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c | |||
| @@ -49,7 +49,7 @@ static unsigned char ret_diacr[NR_DEAD] = { | |||
| 49 | struct kbd_data * | 49 | struct kbd_data * |
| 50 | kbd_alloc(void) { | 50 | kbd_alloc(void) { |
| 51 | struct kbd_data *kbd; | 51 | struct kbd_data *kbd; |
| 52 | int i, len; | 52 | int i; |
| 53 | 53 | ||
| 54 | kbd = kzalloc(sizeof(struct kbd_data), GFP_KERNEL); | 54 | kbd = kzalloc(sizeof(struct kbd_data), GFP_KERNEL); |
| 55 | if (!kbd) | 55 | if (!kbd) |
| @@ -59,12 +59,11 @@ kbd_alloc(void) { | |||
| 59 | goto out_kbd; | 59 | goto out_kbd; |
| 60 | for (i = 0; i < ARRAY_SIZE(key_maps); i++) { | 60 | for (i = 0; i < ARRAY_SIZE(key_maps); i++) { |
| 61 | if (key_maps[i]) { | 61 | if (key_maps[i]) { |
| 62 | kbd->key_maps[i] = | 62 | kbd->key_maps[i] = kmemdup(key_maps[i], |
| 63 | kmalloc(sizeof(u_short)*NR_KEYS, GFP_KERNEL); | 63 | sizeof(u_short) * NR_KEYS, |
| 64 | GFP_KERNEL); | ||
| 64 | if (!kbd->key_maps[i]) | 65 | if (!kbd->key_maps[i]) |
| 65 | goto out_maps; | 66 | goto out_maps; |
| 66 | memcpy(kbd->key_maps[i], key_maps[i], | ||
| 67 | sizeof(u_short)*NR_KEYS); | ||
| 68 | } | 67 | } |
| 69 | } | 68 | } |
| 70 | kbd->func_table = kzalloc(sizeof(func_table), GFP_KERNEL); | 69 | kbd->func_table = kzalloc(sizeof(func_table), GFP_KERNEL); |
| @@ -72,23 +71,21 @@ kbd_alloc(void) { | |||
| 72 | goto out_maps; | 71 | goto out_maps; |
| 73 | for (i = 0; i < ARRAY_SIZE(func_table); i++) { | 72 | for (i = 0; i < ARRAY_SIZE(func_table); i++) { |
| 74 | if (func_table[i]) { | 73 | if (func_table[i]) { |
| 75 | len = strlen(func_table[i]) + 1; | 74 | kbd->func_table[i] = kstrdup(func_table[i], |
| 76 | kbd->func_table[i] = kmalloc(len, GFP_KERNEL); | 75 | GFP_KERNEL); |
| 77 | if (!kbd->func_table[i]) | 76 | if (!kbd->func_table[i]) |
| 78 | goto out_func; | 77 | goto out_func; |
| 79 | memcpy(kbd->func_table[i], func_table[i], len); | ||
| 80 | } | 78 | } |
| 81 | } | 79 | } |
| 82 | kbd->fn_handler = | 80 | kbd->fn_handler = |
| 83 | kzalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL); | 81 | kzalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL); |
| 84 | if (!kbd->fn_handler) | 82 | if (!kbd->fn_handler) |
| 85 | goto out_func; | 83 | goto out_func; |
| 86 | kbd->accent_table = | 84 | kbd->accent_table = kmemdup(accent_table, |
| 87 | kmalloc(sizeof(struct kbdiacruc)*MAX_DIACR, GFP_KERNEL); | 85 | sizeof(struct kbdiacruc) * MAX_DIACR, |
| 86 | GFP_KERNEL); | ||
| 88 | if (!kbd->accent_table) | 87 | if (!kbd->accent_table) |
| 89 | goto out_fn_handler; | 88 | goto out_fn_handler; |
| 90 | memcpy(kbd->accent_table, accent_table, | ||
| 91 | sizeof(struct kbdiacruc)*MAX_DIACR); | ||
| 92 | kbd->accent_table_size = accent_table_size; | 89 | kbd->accent_table_size = accent_table_size; |
| 93 | return kbd; | 90 | return kbd; |
| 94 | 91 | ||
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index 5bb59d36a6d4..04e532eec032 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c | |||
| @@ -1,24 +1,20 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright IBM Corp. 2004,2007 | 2 | * Copyright IBM Corp. 2004,2010 |
| 3 | * Interface implementation for communication with the z/VM control program | 3 | * Interface implementation for communication with the z/VM control program |
| 4 | * Author(s): Christian Borntraeger <borntraeger@de.ibm.com> | ||
| 5 | * | 4 | * |
| 5 | * Author(s): Christian Borntraeger <borntraeger@de.ibm.com> | ||
| 6 | * | 6 | * |
| 7 | * z/VMs CP offers the possibility to issue commands via the diagnose code 8 | 7 | * z/VMs CP offers the possibility to issue commands via the diagnose code 8 |
| 8 | * this driver implements a character device that issues these commands and | 8 | * this driver implements a character device that issues these commands and |
| 9 | * returns the answer of CP. | 9 | * returns the answer of CP. |
| 10 | 10 | * | |
| 11 | * The idea of this driver is based on cpint from Neale Ferguson and #CP in CMS | 11 | * The idea of this driver is based on cpint from Neale Ferguson and #CP in CMS |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #define KMSG_COMPONENT "vmcp" | ||
| 15 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
| 16 | |||
| 17 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
| 18 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 19 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 20 | #include <linux/miscdevice.h> | 17 | #include <linux/miscdevice.h> |
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| 23 | #include <asm/compat.h> | 19 | #include <asm/compat.h> |
| 24 | #include <asm/cpcmd.h> | 20 | #include <asm/cpcmd.h> |
| @@ -26,10 +22,6 @@ | |||
| 26 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
| 27 | #include "vmcp.h" | 23 | #include "vmcp.h" |
| 28 | 24 | ||
| 29 | MODULE_LICENSE("GPL"); | ||
| 30 | MODULE_AUTHOR("Christian Borntraeger <borntraeger@de.ibm.com>"); | ||
| 31 | MODULE_DESCRIPTION("z/VM CP interface"); | ||
| 32 | |||
| 33 | static debug_info_t *vmcp_debug; | 25 | static debug_info_t *vmcp_debug; |
| 34 | 26 | ||
| 35 | static int vmcp_open(struct inode *inode, struct file *file) | 27 | static int vmcp_open(struct inode *inode, struct file *file) |
| @@ -197,11 +189,8 @@ static int __init vmcp_init(void) | |||
| 197 | { | 189 | { |
| 198 | int ret; | 190 | int ret; |
| 199 | 191 | ||
| 200 | if (!MACHINE_IS_VM) { | 192 | if (!MACHINE_IS_VM) |
| 201 | pr_warning("The z/VM CP interface device driver cannot be " | 193 | return 0; |
| 202 | "loaded without z/VM\n"); | ||
| 203 | return -ENODEV; | ||
| 204 | } | ||
| 205 | 194 | ||
| 206 | vmcp_debug = debug_register("vmcp", 1, 1, 240); | 195 | vmcp_debug = debug_register("vmcp", 1, 1, 240); |
| 207 | if (!vmcp_debug) | 196 | if (!vmcp_debug) |
| @@ -214,19 +203,8 @@ static int __init vmcp_init(void) | |||
| 214 | } | 203 | } |
| 215 | 204 | ||
| 216 | ret = misc_register(&vmcp_dev); | 205 | ret = misc_register(&vmcp_dev); |
| 217 | if (ret) { | 206 | if (ret) |
| 218 | debug_unregister(vmcp_debug); | 207 | debug_unregister(vmcp_debug); |
| 219 | return ret; | 208 | return ret; |
| 220 | } | ||
| 221 | |||
| 222 | return 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | static void __exit vmcp_exit(void) | ||
| 226 | { | ||
| 227 | misc_deregister(&vmcp_dev); | ||
| 228 | debug_unregister(vmcp_debug); | ||
| 229 | } | 209 | } |
| 230 | 210 | device_initcall(vmcp_init); | |
| 231 | module_init(vmcp_init); | ||
| 232 | module_exit(vmcp_exit); | ||
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 7217966f7d31..f5ea3384a4b9 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
| @@ -445,7 +445,7 @@ static int zcore_memmap_open(struct inode *inode, struct file *filp) | |||
| 445 | } | 445 | } |
| 446 | kfree(chunk_array); | 446 | kfree(chunk_array); |
| 447 | filp->private_data = buf; | 447 | filp->private_data = buf; |
| 448 | return 0; | 448 | return nonseekable_open(inode, filp); |
| 449 | } | 449 | } |
| 450 | 450 | ||
| 451 | static int zcore_memmap_release(struct inode *inode, struct file *filp) | 451 | static int zcore_memmap_release(struct inode *inode, struct file *filp) |
| @@ -473,7 +473,7 @@ static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf, | |||
| 473 | 473 | ||
| 474 | static int zcore_reipl_open(struct inode *inode, struct file *filp) | 474 | static int zcore_reipl_open(struct inode *inode, struct file *filp) |
| 475 | { | 475 | { |
| 476 | return 0; | 476 | return nonseekable_open(inode, filp); |
| 477 | } | 477 | } |
| 478 | 478 | ||
| 479 | static int zcore_reipl_release(struct inode *inode, struct file *filp) | 479 | static int zcore_reipl_release(struct inode *inode, struct file *filp) |
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 3b6f4adc5094..a83877c664a6 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c | |||
| @@ -803,6 +803,7 @@ static long chsc_ioctl(struct file *filp, unsigned int cmd, | |||
| 803 | 803 | ||
| 804 | static const struct file_operations chsc_fops = { | 804 | static const struct file_operations chsc_fops = { |
| 805 | .owner = THIS_MODULE, | 805 | .owner = THIS_MODULE, |
| 806 | .open = nonseekable_open, | ||
| 806 | .unlocked_ioctl = chsc_ioctl, | 807 | .unlocked_ioctl = chsc_ioctl, |
| 807 | .compat_ioctl = chsc_ioctl, | 808 | .compat_ioctl = chsc_ioctl, |
| 808 | }; | 809 | }; |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 5feea1a371e1..f4e6cf3aceb8 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
| @@ -616,7 +616,8 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
| 616 | struct pt_regs *old_regs; | 616 | struct pt_regs *old_regs; |
| 617 | 617 | ||
| 618 | old_regs = set_irq_regs(regs); | 618 | old_regs = set_irq_regs(regs); |
| 619 | s390_idle_check(); | 619 | s390_idle_check(regs, S390_lowcore.int_clock, |
| 620 | S390_lowcore.async_enter_timer); | ||
| 620 | irq_enter(); | 621 | irq_enter(); |
| 621 | __get_cpu_var(s390_idle).nohz_delay = 1; | 622 | __get_cpu_var(s390_idle).nohz_delay = 1; |
| 622 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) | 623 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 511649115bd7..ac94ac751459 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
| @@ -648,6 +648,8 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow) | |||
| 648 | static void __init | 648 | static void __init |
| 649 | css_generate_pgid(struct channel_subsystem *css, u32 tod_high) | 649 | css_generate_pgid(struct channel_subsystem *css, u32 tod_high) |
| 650 | { | 650 | { |
| 651 | struct cpuid cpu_id; | ||
| 652 | |||
| 651 | if (css_general_characteristics.mcss) { | 653 | if (css_general_characteristics.mcss) { |
| 652 | css->global_pgid.pgid_high.ext_cssid.version = 0x80; | 654 | css->global_pgid.pgid_high.ext_cssid.version = 0x80; |
| 653 | css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; | 655 | css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; |
| @@ -658,8 +660,9 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high) | |||
| 658 | css->global_pgid.pgid_high.cpu_addr = 0; | 660 | css->global_pgid.pgid_high.cpu_addr = 0; |
| 659 | #endif | 661 | #endif |
| 660 | } | 662 | } |
| 661 | css->global_pgid.cpu_id = S390_lowcore.cpu_id.ident; | 663 | get_cpu_id(&cpu_id); |
| 662 | css->global_pgid.cpu_model = S390_lowcore.cpu_id.machine; | 664 | css->global_pgid.cpu_id = cpu_id.ident; |
| 665 | css->global_pgid.cpu_model = cpu_id.machine; | ||
| 663 | css->global_pgid.tod_high = tod_high; | 666 | css->global_pgid.tod_high = tod_high; |
| 664 | 667 | ||
| 665 | } | 668 | } |
| @@ -1062,6 +1065,7 @@ static ssize_t cio_settle_write(struct file *file, const char __user *buf, | |||
| 1062 | } | 1065 | } |
| 1063 | 1066 | ||
| 1064 | static const struct file_operations cio_settle_proc_fops = { | 1067 | static const struct file_operations cio_settle_proc_fops = { |
| 1068 | .open = nonseekable_open, | ||
| 1065 | .write = cio_settle_write, | 1069 | .write = cio_settle_write, |
| 1066 | }; | 1070 | }; |
| 1067 | 1071 | ||
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 48aa0647432b..f0037eefd44e 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | #include <asm/debug.h> | 13 | #include <asm/debug.h> |
| 14 | #include "chsc.h" | 14 | #include "chsc.h" |
| 15 | 15 | ||
| 16 | #define QDIO_BUSY_BIT_PATIENCE 100 /* 100 microseconds */ | 16 | #define QDIO_BUSY_BIT_PATIENCE (100 << 12) /* 100 microseconds */ |
| 17 | #define QDIO_INPUT_THRESHOLD 500 /* 500 microseconds */ | 17 | #define QDIO_INPUT_THRESHOLD (500 << 12) /* 500 microseconds */ |
| 18 | 18 | ||
| 19 | /* | 19 | /* |
| 20 | * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait | 20 | * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait |
| @@ -296,10 +296,8 @@ struct qdio_q { | |||
| 296 | struct qdio_irq *irq_ptr; | 296 | struct qdio_irq *irq_ptr; |
| 297 | struct sl *sl; | 297 | struct sl *sl; |
| 298 | /* | 298 | /* |
| 299 | * Warning: Leave this member at the end so it won't be cleared in | 299 | * A page is allocated under this pointer and used for slib and sl. |
| 300 | * qdio_fill_qs. A page is allocated under this pointer and used for | 300 | * slib is 2048 bytes big and sl points to offset PAGE_SIZE / 2. |
| 301 | * slib and sl. slib is 2048 bytes big and sl points to offset | ||
| 302 | * PAGE_SIZE / 2. | ||
| 303 | */ | 301 | */ |
| 304 | struct slib *slib; | 302 | struct slib *slib; |
| 305 | } __attribute__ ((aligned(256))); | 303 | } __attribute__ ((aligned(256))); |
| @@ -372,11 +370,6 @@ static inline int multicast_outbound(struct qdio_q *q) | |||
| 372 | (q->nr == q->irq_ptr->nr_output_qs - 1); | 370 | (q->nr == q->irq_ptr->nr_output_qs - 1); |
| 373 | } | 371 | } |
| 374 | 372 | ||
| 375 | static inline unsigned long long get_usecs(void) | ||
| 376 | { | ||
| 377 | return monotonic_clock() >> 12; | ||
| 378 | } | ||
| 379 | |||
| 380 | #define pci_out_supported(q) \ | 373 | #define pci_out_supported(q) \ |
| 381 | (q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) | 374 | (q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) |
| 382 | #define is_qebsm(q) (q->irq_ptr->sch_token != 0) | 375 | #define is_qebsm(q) (q->irq_ptr->sch_token != 0) |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 88be7b9ea6e1..00520f9a7a8e 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
| @@ -336,10 +336,10 @@ again: | |||
| 336 | WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2); | 336 | WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2); |
| 337 | 337 | ||
| 338 | if (!start_time) { | 338 | if (!start_time) { |
| 339 | start_time = get_usecs(); | 339 | start_time = get_clock(); |
| 340 | goto again; | 340 | goto again; |
| 341 | } | 341 | } |
| 342 | if ((get_usecs() - start_time) < QDIO_BUSY_BIT_PATIENCE) | 342 | if ((get_clock() - start_time) < QDIO_BUSY_BIT_PATIENCE) |
| 343 | goto again; | 343 | goto again; |
| 344 | } | 344 | } |
| 345 | return cc; | 345 | return cc; |
| @@ -536,7 +536,7 @@ static int qdio_inbound_q_moved(struct qdio_q *q) | |||
| 536 | if ((bufnr != q->last_move) || q->qdio_error) { | 536 | if ((bufnr != q->last_move) || q->qdio_error) { |
| 537 | q->last_move = bufnr; | 537 | q->last_move = bufnr; |
| 538 | if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) | 538 | if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) |
| 539 | q->u.in.timestamp = get_usecs(); | 539 | q->u.in.timestamp = get_clock(); |
| 540 | return 1; | 540 | return 1; |
| 541 | } else | 541 | } else |
| 542 | return 0; | 542 | return 0; |
| @@ -567,7 +567,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q) | |||
| 567 | * At this point we know, that inbound first_to_check | 567 | * At this point we know, that inbound first_to_check |
| 568 | * has (probably) not moved (see qdio_inbound_processing). | 568 | * has (probably) not moved (see qdio_inbound_processing). |
| 569 | */ | 569 | */ |
| 570 | if (get_usecs() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { | 570 | if (get_clock() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { |
| 571 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x", | 571 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x", |
| 572 | q->first_to_check); | 572 | q->first_to_check); |
| 573 | return 1; | 573 | return 1; |
| @@ -606,7 +606,7 @@ static void qdio_kick_handler(struct qdio_q *q) | |||
| 606 | static void __qdio_inbound_processing(struct qdio_q *q) | 606 | static void __qdio_inbound_processing(struct qdio_q *q) |
| 607 | { | 607 | { |
| 608 | qperf_inc(q, tasklet_inbound); | 608 | qperf_inc(q, tasklet_inbound); |
| 609 | again: | 609 | |
| 610 | if (!qdio_inbound_q_moved(q)) | 610 | if (!qdio_inbound_q_moved(q)) |
| 611 | return; | 611 | return; |
| 612 | 612 | ||
| @@ -615,7 +615,10 @@ again: | |||
| 615 | if (!qdio_inbound_q_done(q)) { | 615 | if (!qdio_inbound_q_done(q)) { |
| 616 | /* means poll time is not yet over */ | 616 | /* means poll time is not yet over */ |
| 617 | qperf_inc(q, tasklet_inbound_resched); | 617 | qperf_inc(q, tasklet_inbound_resched); |
| 618 | goto again; | 618 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) { |
| 619 | tasklet_schedule(&q->tasklet); | ||
| 620 | return; | ||
| 621 | } | ||
| 619 | } | 622 | } |
| 620 | 623 | ||
| 621 | qdio_stop_polling(q); | 624 | qdio_stop_polling(q); |
| @@ -625,7 +628,8 @@ again: | |||
| 625 | */ | 628 | */ |
| 626 | if (!qdio_inbound_q_done(q)) { | 629 | if (!qdio_inbound_q_done(q)) { |
| 627 | qperf_inc(q, tasklet_inbound_resched2); | 630 | qperf_inc(q, tasklet_inbound_resched2); |
| 628 | goto again; | 631 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) |
| 632 | tasklet_schedule(&q->tasklet); | ||
| 629 | } | 633 | } |
| 630 | } | 634 | } |
| 631 | 635 | ||
| @@ -955,6 +959,9 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
| 955 | return; | 959 | return; |
| 956 | } | 960 | } |
| 957 | 961 | ||
| 962 | if (irq_ptr->perf_stat_enabled) | ||
| 963 | irq_ptr->perf_stat.qdio_int++; | ||
| 964 | |||
| 958 | if (IS_ERR(irb)) { | 965 | if (IS_ERR(irb)) { |
| 959 | switch (PTR_ERR(irb)) { | 966 | switch (PTR_ERR(irb)) { |
| 960 | case -EIO: | 967 | case -EIO: |
| @@ -1016,30 +1023,6 @@ int qdio_get_ssqd_desc(struct ccw_device *cdev, | |||
| 1016 | } | 1023 | } |
| 1017 | EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); | 1024 | EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); |
| 1018 | 1025 | ||
| 1019 | /** | ||
| 1020 | * qdio_cleanup - shutdown queues and free data structures | ||
| 1021 | * @cdev: associated ccw device | ||
| 1022 | * @how: use halt or clear to shutdown | ||
| 1023 | * | ||
| 1024 | * This function calls qdio_shutdown() for @cdev with method @how. | ||
| 1025 | * and qdio_free(). The qdio_free() return value is ignored since | ||
| 1026 | * !irq_ptr is already checked. | ||
| 1027 | */ | ||
| 1028 | int qdio_cleanup(struct ccw_device *cdev, int how) | ||
| 1029 | { | ||
| 1030 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | ||
| 1031 | int rc; | ||
| 1032 | |||
| 1033 | if (!irq_ptr) | ||
| 1034 | return -ENODEV; | ||
| 1035 | |||
| 1036 | rc = qdio_shutdown(cdev, how); | ||
| 1037 | |||
| 1038 | qdio_free(cdev); | ||
| 1039 | return rc; | ||
| 1040 | } | ||
| 1041 | EXPORT_SYMBOL_GPL(qdio_cleanup); | ||
| 1042 | |||
| 1043 | static void qdio_shutdown_queues(struct ccw_device *cdev) | 1026 | static void qdio_shutdown_queues(struct ccw_device *cdev) |
| 1044 | { | 1027 | { |
| 1045 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | 1028 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
| @@ -1157,28 +1140,6 @@ int qdio_free(struct ccw_device *cdev) | |||
| 1157 | EXPORT_SYMBOL_GPL(qdio_free); | 1140 | EXPORT_SYMBOL_GPL(qdio_free); |
| 1158 | 1141 | ||
| 1159 | /** | 1142 | /** |
| 1160 | * qdio_initialize - allocate and establish queues for a qdio subchannel | ||
| 1161 | * @init_data: initialization data | ||
| 1162 | * | ||
| 1163 | * This function first allocates queues via qdio_allocate() and on success | ||
| 1164 | * establishes them via qdio_establish(). | ||
| 1165 | */ | ||
| 1166 | int qdio_initialize(struct qdio_initialize *init_data) | ||
| 1167 | { | ||
| 1168 | int rc; | ||
| 1169 | |||
| 1170 | rc = qdio_allocate(init_data); | ||
| 1171 | if (rc) | ||
| 1172 | return rc; | ||
| 1173 | |||
| 1174 | rc = qdio_establish(init_data); | ||
| 1175 | if (rc) | ||
| 1176 | qdio_free(init_data->cdev); | ||
| 1177 | return rc; | ||
| 1178 | } | ||
| 1179 | EXPORT_SYMBOL_GPL(qdio_initialize); | ||
| 1180 | |||
| 1181 | /** | ||
| 1182 | * qdio_allocate - allocate qdio queues and associated data | 1143 | * qdio_allocate - allocate qdio queues and associated data |
| 1183 | * @init_data: initialization data | 1144 | * @init_data: initialization data |
| 1184 | */ | 1145 | */ |
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 7f4a75465140..6326b67c45d2 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c | |||
| @@ -106,10 +106,12 @@ int qdio_allocate_qs(struct qdio_irq *irq_ptr, int nr_input_qs, int nr_output_qs | |||
| 106 | static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr, | 106 | static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr, |
| 107 | qdio_handler_t *handler, int i) | 107 | qdio_handler_t *handler, int i) |
| 108 | { | 108 | { |
| 109 | /* must be cleared by every qdio_establish */ | 109 | struct slib *slib = q->slib; |
| 110 | memset(q, 0, ((char *)&q->slib) - ((char *)q)); | ||
| 111 | memset(q->slib, 0, PAGE_SIZE); | ||
| 112 | 110 | ||
| 111 | /* queue must be cleared for qdio_establish */ | ||
| 112 | memset(q, 0, sizeof(*q)); | ||
| 113 | memset(slib, 0, PAGE_SIZE); | ||
| 114 | q->slib = slib; | ||
| 113 | q->irq_ptr = irq_ptr; | 115 | q->irq_ptr = irq_ptr; |
| 114 | q->mask = 1 << (31 - i); | 116 | q->mask = 1 << (31 - i); |
| 115 | q->nr = i; | 117 | q->nr = i; |
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index ce5f8910ff83..8daf1b99f153 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c | |||
| @@ -95,7 +95,7 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr) | |||
| 95 | for_each_input_queue(irq_ptr, q, i) | 95 | for_each_input_queue(irq_ptr, q, i) |
| 96 | list_add_rcu(&q->entry, &tiq_list); | 96 | list_add_rcu(&q->entry, &tiq_list); |
| 97 | mutex_unlock(&tiq_list_lock); | 97 | mutex_unlock(&tiq_list_lock); |
| 98 | xchg(irq_ptr->dsci, 1); | 98 | xchg(irq_ptr->dsci, 1 << 7); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) | 101 | void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) |
| @@ -173,7 +173,7 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data) | |||
| 173 | 173 | ||
| 174 | /* prevent racing */ | 174 | /* prevent racing */ |
| 175 | if (*tiqdio_alsi) | 175 | if (*tiqdio_alsi) |
| 176 | xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1); | 176 | xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1 << 7); |
| 177 | } | 177 | } |
| 178 | } | 178 | } |
| 179 | 179 | ||
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 304caf549973..41e0aaefafd5 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c | |||
| @@ -302,7 +302,7 @@ static ssize_t zcrypt_write(struct file *filp, const char __user *buf, | |||
| 302 | static int zcrypt_open(struct inode *inode, struct file *filp) | 302 | static int zcrypt_open(struct inode *inode, struct file *filp) |
| 303 | { | 303 | { |
| 304 | atomic_inc(&zcrypt_open_count); | 304 | atomic_inc(&zcrypt_open_count); |
| 305 | return 0; | 305 | return nonseekable_open(inode, filp); |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | /** | 308 | /** |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3ba738b2e271..28f71349fdec 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
| @@ -1292,13 +1292,14 @@ int qeth_qdio_clear_card(struct qeth_card *card, int use_halt) | |||
| 1292 | QETH_QDIO_CLEANING)) { | 1292 | QETH_QDIO_CLEANING)) { |
| 1293 | case QETH_QDIO_ESTABLISHED: | 1293 | case QETH_QDIO_ESTABLISHED: |
| 1294 | if (card->info.type == QETH_CARD_TYPE_IQD) | 1294 | if (card->info.type == QETH_CARD_TYPE_IQD) |
| 1295 | rc = qdio_cleanup(CARD_DDEV(card), | 1295 | rc = qdio_shutdown(CARD_DDEV(card), |
| 1296 | QDIO_FLAG_CLEANUP_USING_HALT); | 1296 | QDIO_FLAG_CLEANUP_USING_HALT); |
| 1297 | else | 1297 | else |
| 1298 | rc = qdio_cleanup(CARD_DDEV(card), | 1298 | rc = qdio_shutdown(CARD_DDEV(card), |
| 1299 | QDIO_FLAG_CLEANUP_USING_CLEAR); | 1299 | QDIO_FLAG_CLEANUP_USING_CLEAR); |
| 1300 | if (rc) | 1300 | if (rc) |
| 1301 | QETH_DBF_TEXT_(TRACE, 3, "1err%d", rc); | 1301 | QETH_DBF_TEXT_(TRACE, 3, "1err%d", rc); |
| 1302 | qdio_free(CARD_DDEV(card)); | ||
| 1302 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); | 1303 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); |
| 1303 | break; | 1304 | break; |
| 1304 | case QETH_QDIO_CLEANING: | 1305 | case QETH_QDIO_CLEANING: |
| @@ -3810,10 +3811,18 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
| 3810 | 3811 | ||
| 3811 | if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED, | 3812 | if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED, |
| 3812 | QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) { | 3813 | QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) { |
| 3813 | rc = qdio_initialize(&init_data); | 3814 | rc = qdio_allocate(&init_data); |
| 3814 | if (rc) | 3815 | if (rc) { |
| 3816 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); | ||
| 3817 | goto out; | ||
| 3818 | } | ||
| 3819 | rc = qdio_establish(&init_data); | ||
| 3820 | if (rc) { | ||
| 3815 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); | 3821 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); |
| 3822 | qdio_free(CARD_DDEV(card)); | ||
| 3823 | } | ||
| 3816 | } | 3824 | } |
| 3825 | out: | ||
| 3817 | kfree(out_sbal_ptrs); | 3826 | kfree(out_sbal_ptrs); |
| 3818 | kfree(in_sbal_ptrs); | 3827 | kfree(in_sbal_ptrs); |
| 3819 | kfree(qib_param_field); | 3828 | kfree(qib_param_field); |
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index 25d9e0ae9c57..1a2db0a35737 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c | |||
| @@ -254,6 +254,7 @@ static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, | |||
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | static const struct file_operations zfcp_cfdc_fops = { | 256 | static const struct file_operations zfcp_cfdc_fops = { |
| 257 | .open = nonseekable_open, | ||
| 257 | .unlocked_ioctl = zfcp_cfdc_dev_ioctl, | 258 | .unlocked_ioctl = zfcp_cfdc_dev_ioctl, |
| 258 | #ifdef CONFIG_COMPAT | 259 | #ifdef CONFIG_COMPAT |
| 259 | .compat_ioctl = zfcp_cfdc_dev_ioctl | 260 | .compat_ioctl = zfcp_cfdc_dev_ioctl |
