diff options
| -rw-r--r-- | drivers/s390/block/xpram.c | 4 | ||||
| -rw-r--r-- | drivers/s390/char/keyboard.c | 3 | ||||
| -rw-r--r-- | drivers/s390/char/tape.h | 8 | ||||
| -rw-r--r-- | drivers/s390/char/tape_34xx.c | 59 | ||||
| -rw-r--r-- | drivers/s390/char/tape_3590.c | 83 |
5 files changed, 120 insertions, 37 deletions
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index c881a14fa5dd..1f6a4d894e73 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c | |||
| @@ -62,8 +62,8 @@ static int xpram_devs; | |||
| 62 | /* | 62 | /* |
| 63 | * Parameter parsing functions. | 63 | * Parameter parsing functions. |
| 64 | */ | 64 | */ |
| 65 | static int __initdata devs = XPRAM_DEVS; | 65 | static int devs = XPRAM_DEVS; |
| 66 | static char __initdata *sizes[XPRAM_MAX_DEVS]; | 66 | static char *sizes[XPRAM_MAX_DEVS]; |
| 67 | 67 | ||
| 68 | module_param(devs, int, 0); | 68 | module_param(devs, int, 0); |
| 69 | module_param_array(sizes, charp, NULL, 0); | 69 | module_param_array(sizes, charp, NULL, 0); |
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index 8cd58e412b5e..5ad44daef73b 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c | |||
| @@ -460,7 +460,8 @@ kbd_ioctl(struct kbd_data *kbd, struct file *file, | |||
| 460 | unsigned int cmd, unsigned long arg) | 460 | unsigned int cmd, unsigned long arg) |
| 461 | { | 461 | { |
| 462 | void __user *argp; | 462 | void __user *argp; |
| 463 | int ct, perm; | 463 | unsigned int ct; |
| 464 | int perm; | ||
| 464 | 465 | ||
| 465 | argp = (void __user *)arg; | 466 | argp = (void __user *)arg; |
| 466 | 467 | ||
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h index 7a242f073632..267b54e8ff5a 100644 --- a/drivers/s390/char/tape.h +++ b/drivers/s390/char/tape.h | |||
| @@ -280,6 +280,14 @@ tape_do_io_free(struct tape_device *device, struct tape_request *request) | |||
| 280 | return rc; | 280 | return rc; |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | static inline void | ||
| 284 | tape_do_io_async_free(struct tape_device *device, struct tape_request *request) | ||
| 285 | { | ||
| 286 | request->callback = (void *) tape_free_request; | ||
| 287 | request->callback_data = NULL; | ||
| 288 | tape_do_io_async(device, request); | ||
| 289 | } | ||
| 290 | |||
| 283 | extern int tape_oper_handler(int irq, int status); | 291 | extern int tape_oper_handler(int irq, int status); |
| 284 | extern void tape_noper_handler(int irq, int status); | 292 | extern void tape_noper_handler(int irq, int status); |
| 285 | extern int tape_open(struct tape_device *); | 293 | extern int tape_open(struct tape_device *); |
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index c17f35b6136a..c26511171ffe 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c | |||
| @@ -53,23 +53,11 @@ static void tape_34xx_delete_sbid_from(struct tape_device *, int); | |||
| 53 | * Medium sense for 34xx tapes. There is no 'real' medium sense call. | 53 | * Medium sense for 34xx tapes. There is no 'real' medium sense call. |
| 54 | * So we just do a normal sense. | 54 | * So we just do a normal sense. |
| 55 | */ | 55 | */ |
| 56 | static int | 56 | static void __tape_34xx_medium_sense(struct tape_request *request) |
| 57 | tape_34xx_medium_sense(struct tape_device *device) | ||
| 58 | { | 57 | { |
| 59 | struct tape_request *request; | 58 | struct tape_device *device = request->device; |
| 60 | unsigned char *sense; | 59 | unsigned char *sense; |
| 61 | int rc; | ||
| 62 | |||
| 63 | request = tape_alloc_request(1, 32); | ||
| 64 | if (IS_ERR(request)) { | ||
| 65 | DBF_EXCEPTION(6, "MSEN fail\n"); | ||
| 66 | return PTR_ERR(request); | ||
| 67 | } | ||
| 68 | |||
| 69 | request->op = TO_MSEN; | ||
| 70 | tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata); | ||
| 71 | 60 | ||
| 72 | rc = tape_do_io_interruptible(device, request); | ||
| 73 | if (request->rc == 0) { | 61 | if (request->rc == 0) { |
| 74 | sense = request->cpdata; | 62 | sense = request->cpdata; |
| 75 | 63 | ||
| @@ -88,15 +76,47 @@ tape_34xx_medium_sense(struct tape_device *device) | |||
| 88 | device->tape_generic_status |= GMT_WR_PROT(~0); | 76 | device->tape_generic_status |= GMT_WR_PROT(~0); |
| 89 | else | 77 | else |
| 90 | device->tape_generic_status &= ~GMT_WR_PROT(~0); | 78 | device->tape_generic_status &= ~GMT_WR_PROT(~0); |
| 91 | } else { | 79 | } else |
| 92 | DBF_EVENT(4, "tape_34xx: medium sense failed with rc=%d\n", | 80 | DBF_EVENT(4, "tape_34xx: medium sense failed with rc=%d\n", |
| 93 | request->rc); | 81 | request->rc); |
| 94 | } | ||
| 95 | tape_free_request(request); | 82 | tape_free_request(request); |
| 83 | } | ||
| 84 | |||
| 85 | static int tape_34xx_medium_sense(struct tape_device *device) | ||
| 86 | { | ||
| 87 | struct tape_request *request; | ||
| 88 | int rc; | ||
| 89 | |||
| 90 | request = tape_alloc_request(1, 32); | ||
| 91 | if (IS_ERR(request)) { | ||
| 92 | DBF_EXCEPTION(6, "MSEN fail\n"); | ||
| 93 | return PTR_ERR(request); | ||
| 94 | } | ||
| 96 | 95 | ||
| 96 | request->op = TO_MSEN; | ||
| 97 | tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata); | ||
| 98 | rc = tape_do_io_interruptible(device, request); | ||
| 99 | __tape_34xx_medium_sense(request); | ||
| 97 | return rc; | 100 | return rc; |
| 98 | } | 101 | } |
| 99 | 102 | ||
| 103 | static void tape_34xx_medium_sense_async(struct tape_device *device) | ||
| 104 | { | ||
| 105 | struct tape_request *request; | ||
| 106 | |||
| 107 | request = tape_alloc_request(1, 32); | ||
| 108 | if (IS_ERR(request)) { | ||
| 109 | DBF_EXCEPTION(6, "MSEN fail\n"); | ||
| 110 | return; | ||
| 111 | } | ||
| 112 | |||
| 113 | request->op = TO_MSEN; | ||
| 114 | tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata); | ||
| 115 | request->callback = (void *) __tape_34xx_medium_sense; | ||
| 116 | request->callback_data = NULL; | ||
| 117 | tape_do_io_async(device, request); | ||
| 118 | } | ||
| 119 | |||
| 100 | struct tape_34xx_work { | 120 | struct tape_34xx_work { |
| 101 | struct tape_device *device; | 121 | struct tape_device *device; |
| 102 | enum tape_op op; | 122 | enum tape_op op; |
| @@ -109,6 +129,9 @@ struct tape_34xx_work { | |||
| 109 | * is inserted but cannot call tape_do_io* from an interrupt context. | 129 | * is inserted but cannot call tape_do_io* from an interrupt context. |
| 110 | * Maybe that's useful for other actions we want to start from the | 130 | * Maybe that's useful for other actions we want to start from the |
| 111 | * interrupt handler. | 131 | * interrupt handler. |
| 132 | * Note: the work handler is called by the system work queue. The tape | ||
| 133 | * commands started by the handler need to be asynchrounous, otherwise | ||
| 134 | * a deadlock can occur e.g. in case of a deferred cc=1 (see __tape_do_irq). | ||
| 112 | */ | 135 | */ |
| 113 | static void | 136 | static void |
| 114 | tape_34xx_work_handler(struct work_struct *work) | 137 | tape_34xx_work_handler(struct work_struct *work) |
| @@ -119,7 +142,7 @@ tape_34xx_work_handler(struct work_struct *work) | |||
| 119 | 142 | ||
| 120 | switch(p->op) { | 143 | switch(p->op) { |
| 121 | case TO_MSEN: | 144 | case TO_MSEN: |
| 122 | tape_34xx_medium_sense(device); | 145 | tape_34xx_medium_sense_async(device); |
| 123 | break; | 146 | break; |
| 124 | default: | 147 | default: |
| 125 | DBF_EVENT(3, "T34XX: internal error: unknown work\n"); | 148 | DBF_EVENT(3, "T34XX: internal error: unknown work\n"); |
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index fbe361fcd2c0..de2e99e0a71b 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
| @@ -329,17 +329,17 @@ out: | |||
| 329 | /* | 329 | /* |
| 330 | * Enable encryption | 330 | * Enable encryption |
| 331 | */ | 331 | */ |
| 332 | static int tape_3592_enable_crypt(struct tape_device *device) | 332 | static struct tape_request *__tape_3592_enable_crypt(struct tape_device *device) |
| 333 | { | 333 | { |
| 334 | struct tape_request *request; | 334 | struct tape_request *request; |
| 335 | char *data; | 335 | char *data; |
| 336 | 336 | ||
| 337 | DBF_EVENT(6, "tape_3592_enable_crypt\n"); | 337 | DBF_EVENT(6, "tape_3592_enable_crypt\n"); |
| 338 | if (!crypt_supported(device)) | 338 | if (!crypt_supported(device)) |
| 339 | return -ENOSYS; | 339 | return ERR_PTR(-ENOSYS); |
| 340 | request = tape_alloc_request(2, 72); | 340 | request = tape_alloc_request(2, 72); |
| 341 | if (IS_ERR(request)) | 341 | if (IS_ERR(request)) |
| 342 | return PTR_ERR(request); | 342 | return request; |
| 343 | data = request->cpdata; | 343 | data = request->cpdata; |
| 344 | memset(data,0,72); | 344 | memset(data,0,72); |
| 345 | 345 | ||
| @@ -354,23 +354,42 @@ static int tape_3592_enable_crypt(struct tape_device *device) | |||
| 354 | request->op = TO_CRYPT_ON; | 354 | request->op = TO_CRYPT_ON; |
| 355 | tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data); | 355 | tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data); |
| 356 | tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36); | 356 | tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36); |
| 357 | return request; | ||
| 358 | } | ||
| 359 | |||
| 360 | static int tape_3592_enable_crypt(struct tape_device *device) | ||
| 361 | { | ||
| 362 | struct tape_request *request; | ||
| 363 | |||
| 364 | request = __tape_3592_enable_crypt(device); | ||
| 365 | if (IS_ERR(request)) | ||
| 366 | return PTR_ERR(request); | ||
| 357 | return tape_do_io_free(device, request); | 367 | return tape_do_io_free(device, request); |
| 358 | } | 368 | } |
| 359 | 369 | ||
| 370 | static void tape_3592_enable_crypt_async(struct tape_device *device) | ||
| 371 | { | ||
| 372 | struct tape_request *request; | ||
| 373 | |||
| 374 | request = __tape_3592_enable_crypt(device); | ||
| 375 | if (!IS_ERR(request)) | ||
| 376 | tape_do_io_async_free(device, request); | ||
| 377 | } | ||
| 378 | |||
| 360 | /* | 379 | /* |
| 361 | * Disable encryption | 380 | * Disable encryption |
| 362 | */ | 381 | */ |
| 363 | static int tape_3592_disable_crypt(struct tape_device *device) | 382 | static struct tape_request *__tape_3592_disable_crypt(struct tape_device *device) |
| 364 | { | 383 | { |
| 365 | struct tape_request *request; | 384 | struct tape_request *request; |
| 366 | char *data; | 385 | char *data; |
| 367 | 386 | ||
| 368 | DBF_EVENT(6, "tape_3592_disable_crypt\n"); | 387 | DBF_EVENT(6, "tape_3592_disable_crypt\n"); |
| 369 | if (!crypt_supported(device)) | 388 | if (!crypt_supported(device)) |
| 370 | return -ENOSYS; | 389 | return ERR_PTR(-ENOSYS); |
| 371 | request = tape_alloc_request(2, 72); | 390 | request = tape_alloc_request(2, 72); |
| 372 | if (IS_ERR(request)) | 391 | if (IS_ERR(request)) |
| 373 | return PTR_ERR(request); | 392 | return request; |
| 374 | data = request->cpdata; | 393 | data = request->cpdata; |
| 375 | memset(data,0,72); | 394 | memset(data,0,72); |
| 376 | 395 | ||
| @@ -383,9 +402,28 @@ static int tape_3592_disable_crypt(struct tape_device *device) | |||
| 383 | tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data); | 402 | tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data); |
| 384 | tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36); | 403 | tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36); |
| 385 | 404 | ||
| 405 | return request; | ||
| 406 | } | ||
| 407 | |||
| 408 | static int tape_3592_disable_crypt(struct tape_device *device) | ||
| 409 | { | ||
| 410 | struct tape_request *request; | ||
| 411 | |||
| 412 | request = __tape_3592_disable_crypt(device); | ||
| 413 | if (IS_ERR(request)) | ||
| 414 | return PTR_ERR(request); | ||
| 386 | return tape_do_io_free(device, request); | 415 | return tape_do_io_free(device, request); |
| 387 | } | 416 | } |
| 388 | 417 | ||
| 418 | static void tape_3592_disable_crypt_async(struct tape_device *device) | ||
| 419 | { | ||
| 420 | struct tape_request *request; | ||
| 421 | |||
| 422 | request = __tape_3592_disable_crypt(device); | ||
| 423 | if (!IS_ERR(request)) | ||
| 424 | tape_do_io_async_free(device, request); | ||
| 425 | } | ||
| 426 | |||
| 389 | /* | 427 | /* |
| 390 | * IOCTL: Set encryption status | 428 | * IOCTL: Set encryption status |
| 391 | */ | 429 | */ |
| @@ -457,8 +495,7 @@ tape_3590_ioctl(struct tape_device *device, unsigned int cmd, unsigned long arg) | |||
| 457 | /* | 495 | /* |
| 458 | * SENSE Medium: Get Sense data about medium state | 496 | * SENSE Medium: Get Sense data about medium state |
| 459 | */ | 497 | */ |
| 460 | static int | 498 | static int tape_3590_sense_medium(struct tape_device *device) |
| 461 | tape_3590_sense_medium(struct tape_device *device) | ||
| 462 | { | 499 | { |
| 463 | struct tape_request *request; | 500 | struct tape_request *request; |
| 464 | 501 | ||
| @@ -470,6 +507,18 @@ tape_3590_sense_medium(struct tape_device *device) | |||
| 470 | return tape_do_io_free(device, request); | 507 | return tape_do_io_free(device, request); |
| 471 | } | 508 | } |
| 472 | 509 | ||
| 510 | static void tape_3590_sense_medium_async(struct tape_device *device) | ||
| 511 | { | ||
| 512 | struct tape_request *request; | ||
| 513 | |||
| 514 | request = tape_alloc_request(1, 128); | ||
| 515 | if (IS_ERR(request)) | ||
| 516 | return; | ||
| 517 | request->op = TO_MSEN; | ||
| 518 | tape_ccw_end(request->cpaddr, MEDIUM_SENSE, 128, request->cpdata); | ||
| 519 | tape_do_io_async_free(device, request); | ||
| 520 | } | ||
| 521 | |||
| 473 | /* | 522 | /* |
| 474 | * MTTELL: Tell block. Return the number of block relative to current file. | 523 | * MTTELL: Tell block. Return the number of block relative to current file. |
| 475 | */ | 524 | */ |
| @@ -546,15 +595,14 @@ tape_3590_read_opposite(struct tape_device *device, | |||
| 546 | * 2. The attention msg is written to the "read subsystem data" buffer. | 595 | * 2. The attention msg is written to the "read subsystem data" buffer. |
| 547 | * In this case we probably should print it to the console. | 596 | * In this case we probably should print it to the console. |
| 548 | */ | 597 | */ |
| 549 | static int | 598 | static void tape_3590_read_attmsg_async(struct tape_device *device) |
| 550 | tape_3590_read_attmsg(struct tape_device *device) | ||
| 551 | { | 599 | { |
| 552 | struct tape_request *request; | 600 | struct tape_request *request; |
| 553 | char *buf; | 601 | char *buf; |
| 554 | 602 | ||
| 555 | request = tape_alloc_request(3, 4096); | 603 | request = tape_alloc_request(3, 4096); |
| 556 | if (IS_ERR(request)) | 604 | if (IS_ERR(request)) |
| 557 | return PTR_ERR(request); | 605 | return; |
| 558 | request->op = TO_READ_ATTMSG; | 606 | request->op = TO_READ_ATTMSG; |
| 559 | buf = request->cpdata; | 607 | buf = request->cpdata; |
| 560 | buf[0] = PREP_RD_SS_DATA; | 608 | buf[0] = PREP_RD_SS_DATA; |
| @@ -562,12 +610,15 @@ tape_3590_read_attmsg(struct tape_device *device) | |||
| 562 | tape_ccw_cc(request->cpaddr, PERFORM_SS_FUNC, 12, buf); | 610 | tape_ccw_cc(request->cpaddr, PERFORM_SS_FUNC, 12, buf); |
| 563 | tape_ccw_cc(request->cpaddr + 1, READ_SS_DATA, 4096 - 12, buf + 12); | 611 | tape_ccw_cc(request->cpaddr + 1, READ_SS_DATA, 4096 - 12, buf + 12); |
| 564 | tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL); | 612 | tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL); |
| 565 | return tape_do_io_free(device, request); | 613 | tape_do_io_async_free(device, request); |
| 566 | } | 614 | } |
| 567 | 615 | ||
| 568 | /* | 616 | /* |
| 569 | * These functions are used to schedule follow-up actions from within an | 617 | * These functions are used to schedule follow-up actions from within an |
| 570 | * interrupt context (like unsolicited interrupts). | 618 | * interrupt context (like unsolicited interrupts). |
| 619 | * Note: the work handler is called by the system work queue. The tape | ||
| 620 | * commands started by the handler need to be asynchrounous, otherwise | ||
| 621 | * a deadlock can occur e.g. in case of a deferred cc=1 (see __tape_do_irq). | ||
| 571 | */ | 622 | */ |
| 572 | struct work_handler_data { | 623 | struct work_handler_data { |
| 573 | struct tape_device *device; | 624 | struct tape_device *device; |
| @@ -583,16 +634,16 @@ tape_3590_work_handler(struct work_struct *work) | |||
| 583 | 634 | ||
| 584 | switch (p->op) { | 635 | switch (p->op) { |
| 585 | case TO_MSEN: | 636 | case TO_MSEN: |
| 586 | tape_3590_sense_medium(p->device); | 637 | tape_3590_sense_medium_async(p->device); |
| 587 | break; | 638 | break; |
| 588 | case TO_READ_ATTMSG: | 639 | case TO_READ_ATTMSG: |
| 589 | tape_3590_read_attmsg(p->device); | 640 | tape_3590_read_attmsg_async(p->device); |
| 590 | break; | 641 | break; |
| 591 | case TO_CRYPT_ON: | 642 | case TO_CRYPT_ON: |
| 592 | tape_3592_enable_crypt(p->device); | 643 | tape_3592_enable_crypt_async(p->device); |
| 593 | break; | 644 | break; |
| 594 | case TO_CRYPT_OFF: | 645 | case TO_CRYPT_OFF: |
| 595 | tape_3592_disable_crypt(p->device); | 646 | tape_3592_disable_crypt_async(p->device); |
| 596 | break; | 647 | break; |
| 597 | default: | 648 | default: |
| 598 | DBF_EVENT(3, "T3590: work handler undefined for " | 649 | DBF_EVENT(3, "T3590: work handler undefined for " |
