[S390] tape: deadlock on system work queue

The 34xx and 3590 tape driver uses the system work queue to defer work
from the interrupt function to process context, e.g. a medium sense
after an unsolicited interrupt. The tape commands started by the work
handler need to be asynchronous, otherwise a deadlock on the system
work queue can occur.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by Martin Schwidefsky and committed by Martin Schwidefsky 0c2bd9b2 b652277b

+116 -34
+8
drivers/s390/char/tape.h
··· 280 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 291 extern int tape_oper_handler(int irq, int status); 284 292 extern void tape_noper_handler(int irq, int status); 285 293 extern int tape_open(struct tape_device *);
+41 -18
drivers/s390/char/tape_34xx.c
··· 53 53 * Medium sense for 34xx tapes. There is no 'real' medium sense call. 54 54 * So we just do a normal sense. 55 55 */ 56 - static int 57 - tape_34xx_medium_sense(struct tape_device *device) 56 + static void __tape_34xx_medium_sense(struct tape_request *request) 58 57 { 59 - struct tape_request *request; 60 - unsigned char *sense; 61 - int rc; 58 + struct tape_device *device = request->device; 59 + unsigned char *sense; 62 60 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 - 72 - rc = tape_do_io_interruptible(device, request); 73 61 if (request->rc == 0) { 74 62 sense = request->cpdata; 75 63 ··· 76 88 device->tape_generic_status |= GMT_WR_PROT(~0); 77 89 else 78 90 device->tape_generic_status &= ~GMT_WR_PROT(~0); 79 - } else { 91 + } else 80 92 DBF_EVENT(4, "tape_34xx: medium sense failed with rc=%d\n", 81 93 request->rc); 82 - } 83 94 tape_free_request(request); 95 + } 84 96 97 + static int tape_34xx_medium_sense(struct tape_device *device) 98 + { 99 + struct tape_request *request; 100 + int rc; 101 + 102 + request = tape_alloc_request(1, 32); 103 + if (IS_ERR(request)) { 104 + DBF_EXCEPTION(6, "MSEN fail\n"); 105 + return PTR_ERR(request); 106 + } 107 + 108 + request->op = TO_MSEN; 109 + tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata); 110 + rc = tape_do_io_interruptible(device, request); 111 + __tape_34xx_medium_sense(request); 85 112 return rc; 113 + } 114 + 115 + static void tape_34xx_medium_sense_async(struct tape_device *device) 116 + { 117 + struct tape_request *request; 118 + 119 + request = tape_alloc_request(1, 32); 120 + if (IS_ERR(request)) { 121 + DBF_EXCEPTION(6, "MSEN fail\n"); 122 + return; 123 + } 124 + 125 + request->op = TO_MSEN; 126 + tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata); 127 + request->callback = (void *) __tape_34xx_medium_sense; 128 + request->callback_data = NULL; 129 + tape_do_io_async(device, request); 86 130 } 87 131 88 132 struct tape_34xx_work { ··· 129 109 * is inserted but cannot call tape_do_io* from an interrupt context. 130 110 * Maybe that's useful for other actions we want to start from the 131 111 * interrupt handler. 112 + * Note: the work handler is called by the system work queue. The tape 113 + * commands started by the handler need to be asynchrounous, otherwise 114 + * a deadlock can occur e.g. in case of a deferred cc=1 (see __tape_do_irq). 132 115 */ 133 116 static void 134 117 tape_34xx_work_handler(struct work_struct *work) ··· 142 119 143 120 switch(p->op) { 144 121 case TO_MSEN: 145 - tape_34xx_medium_sense(device); 122 + tape_34xx_medium_sense_async(device); 146 123 break; 147 124 default: 148 125 DBF_EVENT(3, "T34XX: internal error: unknown work\n");
+67 -16
drivers/s390/char/tape_3590.c
··· 329 329 /* 330 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 334 struct tape_request *request; 335 335 char *data; 336 336 337 337 DBF_EVENT(6, "tape_3592_enable_crypt\n"); 338 338 if (!crypt_supported(device)) 339 - return -ENOSYS; 339 + return ERR_PTR(-ENOSYS); 340 340 request = tape_alloc_request(2, 72); 341 341 if (IS_ERR(request)) 342 - return PTR_ERR(request); 342 + return request; 343 343 data = request->cpdata; 344 344 memset(data,0,72); 345 345 ··· 354 354 request->op = TO_CRYPT_ON; 355 355 tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data); 356 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 367 return tape_do_io_free(device, request); 368 + } 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); 358 377 } 359 378 360 379 /* 361 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 384 struct tape_request *request; 366 385 char *data; 367 386 368 387 DBF_EVENT(6, "tape_3592_disable_crypt\n"); 369 388 if (!crypt_supported(device)) 370 - return -ENOSYS; 389 + return ERR_PTR(-ENOSYS); 371 390 request = tape_alloc_request(2, 72); 372 391 if (IS_ERR(request)) 373 - return PTR_ERR(request); 392 + return request; 374 393 data = request->cpdata; 375 394 memset(data,0,72); 376 395 ··· 402 383 tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data); 403 384 tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36); 404 385 386 + return request; 387 + } 388 + 389 + static int tape_3592_disable_crypt(struct tape_device *device) 390 + { 391 + struct tape_request *request; 392 + 393 + request = __tape_3592_disable_crypt(device); 394 + if (IS_ERR(request)) 395 + return PTR_ERR(request); 405 396 return tape_do_io_free(device, request); 397 + } 398 + 399 + static void tape_3592_disable_crypt_async(struct tape_device *device) 400 + { 401 + struct tape_request *request; 402 + 403 + request = __tape_3592_disable_crypt(device); 404 + if (!IS_ERR(request)) 405 + tape_do_io_async_free(device, request); 406 406 } 407 407 408 408 /* ··· 495 457 /* 496 458 * SENSE Medium: Get Sense data about medium state 497 459 */ 498 - static int 499 - tape_3590_sense_medium(struct tape_device *device) 460 + static int tape_3590_sense_medium(struct tape_device *device) 500 461 { 501 462 struct tape_request *request; 502 463 ··· 505 468 request->op = TO_MSEN; 506 469 tape_ccw_end(request->cpaddr, MEDIUM_SENSE, 128, request->cpdata); 507 470 return tape_do_io_free(device, request); 471 + } 472 + 473 + static void tape_3590_sense_medium_async(struct tape_device *device) 474 + { 475 + struct tape_request *request; 476 + 477 + request = tape_alloc_request(1, 128); 478 + if (IS_ERR(request)) 479 + return; 480 + request->op = TO_MSEN; 481 + tape_ccw_end(request->cpaddr, MEDIUM_SENSE, 128, request->cpdata); 482 + tape_do_io_async_free(device, request); 508 483 } 509 484 510 485 /* ··· 595 546 * 2. The attention msg is written to the "read subsystem data" buffer. 596 547 * In this case we probably should print it to the console. 597 548 */ 598 - static int 599 - tape_3590_read_attmsg(struct tape_device *device) 549 + static void tape_3590_read_attmsg_async(struct tape_device *device) 600 550 { 601 551 struct tape_request *request; 602 552 char *buf; 603 553 604 554 request = tape_alloc_request(3, 4096); 605 555 if (IS_ERR(request)) 606 - return PTR_ERR(request); 556 + return; 607 557 request->op = TO_READ_ATTMSG; 608 558 buf = request->cpdata; 609 559 buf[0] = PREP_RD_SS_DATA; ··· 610 562 tape_ccw_cc(request->cpaddr, PERFORM_SS_FUNC, 12, buf); 611 563 tape_ccw_cc(request->cpaddr + 1, READ_SS_DATA, 4096 - 12, buf + 12); 612 564 tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL); 613 - return tape_do_io_free(device, request); 565 + tape_do_io_async_free(device, request); 614 566 } 615 567 616 568 /* 617 569 * These functions are used to schedule follow-up actions from within an 618 570 * interrupt context (like unsolicited interrupts). 571 + * Note: the work handler is called by the system work queue. The tape 572 + * commands started by the handler need to be asynchrounous, otherwise 573 + * a deadlock can occur e.g. in case of a deferred cc=1 (see __tape_do_irq). 619 574 */ 620 575 struct work_handler_data { 621 576 struct tape_device *device; ··· 634 583 635 584 switch (p->op) { 636 585 case TO_MSEN: 637 - tape_3590_sense_medium(p->device); 586 + tape_3590_sense_medium_async(p->device); 638 587 break; 639 588 case TO_READ_ATTMSG: 640 - tape_3590_read_attmsg(p->device); 589 + tape_3590_read_attmsg_async(p->device); 641 590 break; 642 591 case TO_CRYPT_ON: 643 - tape_3592_enable_crypt(p->device); 592 + tape_3592_enable_crypt_async(p->device); 644 593 break; 645 594 case TO_CRYPT_OFF: 646 - tape_3592_disable_crypt(p->device); 595 + tape_3592_disable_crypt_async(p->device); 647 596 break; 648 597 default: 649 598 DBF_EVENT(3, "T3590: work handler undefined for "