Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

block: ataflop: more blk-mq refactoring fixes

As it turns out, my earlier patch in commit 86d46fdaa12a (block:
ataflop: fix breakage introduced at blk-mq refactoring) was
incomplete. This patch fixes any remaining issues found during
more testing and code review.

Requests exceeding 4 k are handled in 4k segments but
__blk_mq_end_request() is never called on these (still
sectors outstanding on the request). With redo_fd_request()
removed, there is no provision to kick off processing of the
next segment, causing requests exceeding 4k to hang. (By
setting /sys/block/fd0/queue/max_sectors_k <= 4 as workaround,
this behaviour can be avoided).

Instead of reintroducing redo_fd_request(), requeue the remainder
of the request by calling blk_mq_requeue_request() on incomplete
requests (i.e. when blk_update_request() still returns true), and
rely on the block layer to queue the residual as new request.

Both error handling and formatting needs to release the
ST-DMA lock, so call finish_fdc() on these (this was previously
handled by redo_fd_request()). finish_fdc() may be called
legitimately without the ST-DMA lock held - make sure we only
release the lock if we actually held it. In a similar way,
early exit due to errors in ataflop_queue_rq() must release
the lock.

After minor errors, fd_error sets up to recalibrate the drive
but never re-runs the current operation (another task handled by
redo_fd_request() before). Call do_fd_action() to get the next
steps (seek, retry read/write) underway.

Signed-off-by: Michael Schmitz <schmitzmic@gmail.com>
Fixes: 6ec3938cff95f (ataflop: convert to blk-mq)
CC: linux-block@vger.kernel.org
Link: https://lore.kernel.org/r/20211024002013.9332-1-schmitzmic@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Michael Schmitz and committed by
Jens Axboe
d28e4dff 47e96246

+39 -6
+39 -6
drivers/block/ataflop.c
··· 458 458 459 459 static void fd_end_request_cur(blk_status_t err) 460 460 { 461 + DPRINT(("fd_end_request_cur(), bytes %d of %d\n", 462 + blk_rq_cur_bytes(fd_request), 463 + blk_rq_bytes(fd_request))); 464 + 461 465 if (!blk_update_request(fd_request, err, 462 466 blk_rq_cur_bytes(fd_request))) { 467 + DPRINT(("calling __blk_mq_end_request()\n")); 463 468 __blk_mq_end_request(fd_request, err); 469 + fd_request = NULL; 470 + } else { 471 + /* requeue rest of request */ 472 + DPRINT(("calling blk_mq_requeue_request()\n")); 473 + blk_mq_requeue_request(fd_request, true); 464 474 fd_request = NULL; 465 475 } 466 476 } ··· 709 699 if (fd_request->error_count >= MAX_ERRORS) { 710 700 printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive ); 711 701 fd_end_request_cur(BLK_STS_IOERR); 702 + finish_fdc(); 703 + return; 712 704 } 713 705 else if (fd_request->error_count == RECALIBRATE_ERRORS) { 714 706 printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive ); 715 707 if (SelectedDrive != -1) 716 708 SUD.track = -1; 717 709 } 710 + /* need to re-run request to recalibrate */ 711 + atari_disable_irq( IRQ_MFP_FDC ); 712 + 713 + setup_req_params( SelectedDrive ); 714 + do_fd_action( SelectedDrive ); 715 + 716 + atari_enable_irq( IRQ_MFP_FDC ); 718 717 } 719 718 720 719 ··· 750 731 if (type) { 751 732 type--; 752 733 if (type >= NUM_DISK_MINORS || 753 - minor2disktype[type].drive_types > DriveType) 734 + minor2disktype[type].drive_types > DriveType) { 735 + finish_fdc(); 754 736 return -EINVAL; 737 + } 755 738 } 756 739 757 740 q = unit[drive].disk[type]->queue; ··· 771 750 } 772 751 773 752 if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) { 753 + finish_fdc(); 774 754 ret = -EINVAL; 775 755 goto out; 776 756 } ··· 812 790 813 791 wait_for_completion(&format_wait); 814 792 793 + finish_fdc(); 815 794 ret = FormatError ? -EIO : 0; 816 795 out: 817 796 blk_mq_unquiesce_queue(q); ··· 847 824 else { 848 825 /* all sectors finished */ 849 826 fd_end_request_cur(BLK_STS_OK); 827 + finish_fdc(); 850 828 return; 851 829 } 852 830 } ··· 1251 1227 } 1252 1228 else { 1253 1229 /* all sectors finished */ 1254 - finish_fdc(); 1255 1230 fd_end_request_cur(BLK_STS_OK); 1231 + finish_fdc(); 1256 1232 } 1257 1233 return; 1258 1234 ··· 1374 1350 1375 1351 static void finish_fdc( void ) 1376 1352 { 1377 - if (!NeedSeek) { 1353 + if (!NeedSeek || !stdma_is_locked_by(floppy_irq)) { 1378 1354 finish_fdc_done( 0 ); 1379 1355 } 1380 1356 else { ··· 1409 1385 start_motor_off_timer(); 1410 1386 1411 1387 local_irq_save(flags); 1412 - stdma_release(); 1388 + if (stdma_is_locked_by(floppy_irq)) 1389 + stdma_release(); 1413 1390 local_irq_restore(flags); 1414 1391 1415 1392 DPRINT(("finish_fdc() finished\n")); ··· 1507 1482 int drive = floppy - unit; 1508 1483 int type = floppy->type; 1509 1484 1510 - DPRINT(("Queue request: drive %d type %d last %d\n", drive, type, bd->last)); 1485 + DPRINT(("Queue request: drive %d type %d sectors %d of %d last %d\n", 1486 + drive, type, blk_rq_cur_sectors(bd->rq), 1487 + blk_rq_sectors(bd->rq), bd->last)); 1511 1488 1512 1489 spin_lock_irq(&ataflop_lock); 1513 1490 if (fd_request) { ··· 1531 1504 /* drive not connected */ 1532 1505 printk(KERN_ERR "Unknown Device: fd%d\n", drive ); 1533 1506 fd_end_request_cur(BLK_STS_IOERR); 1507 + stdma_release(); 1534 1508 goto out; 1535 1509 } 1536 1510 ··· 1548 1520 if (--type >= NUM_DISK_MINORS) { 1549 1521 printk(KERN_WARNING "fd%d: invalid disk format", drive ); 1550 1522 fd_end_request_cur(BLK_STS_IOERR); 1523 + stdma_release(); 1551 1524 goto out; 1552 1525 } 1553 1526 if (minor2disktype[type].drive_types > DriveType) { 1554 1527 printk(KERN_WARNING "fd%d: unsupported disk format", drive ); 1555 1528 fd_end_request_cur(BLK_STS_IOERR); 1529 + stdma_release(); 1556 1530 goto out; 1557 1531 } 1558 1532 type = minor2disktype[type].index; ··· 1655 1625 /* what if type > 0 here? Overwrite specified entry ? */ 1656 1626 if (type) { 1657 1627 /* refuse to re-set a predefined type for now */ 1628 + finish_fdc(); 1658 1629 return -EINVAL; 1659 1630 } 1660 1631 ··· 1723 1692 1724 1693 /* sanity check */ 1725 1694 if (setprm.track != dtp->blocks/dtp->spt/2 || 1726 - setprm.head != 2) 1695 + setprm.head != 2) { 1696 + finish_fdc(); 1727 1697 return -EINVAL; 1698 + } 1728 1699 1729 1700 UDT = dtp; 1730 1701 set_capacity(disk, UDT->blocks);