From: Greg Kroah-Hartman Date: Tue, 27 Feb 2024 09:17:54 +0000 (+0100) Subject: 5.10-stable patches X-Git-Tag: v4.19.308~26 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=18421aba6e617aee1ec38acbf0e26a81a9dfbfd4;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: block-ataflop-more-blk-mq-refactoring-fixes.patch --- diff --git a/queue-5.10/block-ataflop-more-blk-mq-refactoring-fixes.patch b/queue-5.10/block-ataflop-more-blk-mq-refactoring-fixes.patch new file mode 100644 index 00000000000..e86d384ede4 --- /dev/null +++ b/queue-5.10/block-ataflop-more-blk-mq-refactoring-fixes.patch @@ -0,0 +1,210 @@ +From d28e4dff085c5a87025c9a0a85fb798bd8e9ca17 Mon Sep 17 00:00:00 2001 +From: Michael Schmitz +Date: Sun, 24 Oct 2021 13:20:13 +1300 +Subject: block: ataflop: more blk-mq refactoring fixes + +From: Michael Schmitz + +commit d28e4dff085c5a87025c9a0a85fb798bd8e9ca17 upstream. + +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 +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 +[MSch: v5.10 backport merge conflict fix] +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/ataflop.c | 42 +++++++++++++++++++++++++++++++++++++----- + 1 file changed, 37 insertions(+), 5 deletions(-) + +--- a/drivers/block/ataflop.c ++++ b/drivers/block/ataflop.c +@@ -456,10 +456,20 @@ static DEFINE_TIMER(fd_timer, check_chan + + static void fd_end_request_cur(blk_status_t err) + { ++ DPRINT(("fd_end_request_cur(), bytes %d of %d\n", ++ blk_rq_cur_bytes(fd_request), ++ blk_rq_bytes(fd_request))); ++ + if (!blk_update_request(fd_request, err, + blk_rq_cur_bytes(fd_request))) { ++ DPRINT(("calling __blk_mq_end_request()\n")); + __blk_mq_end_request(fd_request, err); + fd_request = NULL; ++ } else { ++ /* requeue rest of request */ ++ DPRINT(("calling blk_mq_requeue_request()\n")); ++ blk_mq_requeue_request(fd_request, true); ++ fd_request = NULL; + } + } + +@@ -697,12 +707,21 @@ static void fd_error( void ) + if (fd_request->error_count >= MAX_ERRORS) { + printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive ); + fd_end_request_cur(BLK_STS_IOERR); ++ finish_fdc(); ++ return; + } + else if (fd_request->error_count == RECALIBRATE_ERRORS) { + printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive ); + if (SelectedDrive != -1) + SUD.track = -1; + } ++ /* need to re-run request to recalibrate */ ++ atari_disable_irq( IRQ_MFP_FDC ); ++ ++ setup_req_params( SelectedDrive ); ++ do_fd_action( SelectedDrive ); ++ ++ atari_enable_irq( IRQ_MFP_FDC ); + } + + +@@ -737,6 +756,7 @@ static int do_format(int drive, int type + if (type) { + if (--type >= NUM_DISK_MINORS || + minor2disktype[type].drive_types > DriveType) { ++ finish_fdc(); + ret = -EINVAL; + goto out; + } +@@ -745,6 +765,7 @@ static int do_format(int drive, int type + } + + if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) { ++ finish_fdc(); + ret = -EINVAL; + goto out; + } +@@ -785,6 +806,7 @@ static int do_format(int drive, int type + + wait_for_completion(&format_wait); + ++ finish_fdc(); + ret = FormatError ? -EIO : 0; + out: + blk_mq_unquiesce_queue(q); +@@ -819,6 +841,7 @@ static void do_fd_action( int drive ) + else { + /* all sectors finished */ + fd_end_request_cur(BLK_STS_OK); ++ finish_fdc(); + return; + } + } +@@ -1222,8 +1245,8 @@ static void fd_rwsec_done1(int status) + } + else { + /* all sectors finished */ +- finish_fdc(); + fd_end_request_cur(BLK_STS_OK); ++ finish_fdc(); + } + return; + +@@ -1345,7 +1368,7 @@ static void fd_times_out(struct timer_li + + static void finish_fdc( void ) + { +- if (!NeedSeek) { ++ if (!NeedSeek || !stdma_is_locked_by(floppy_irq)) { + finish_fdc_done( 0 ); + } + else { +@@ -1380,7 +1403,8 @@ static void finish_fdc_done( int dummy ) + start_motor_off_timer(); + + local_irq_save(flags); +- stdma_release(); ++ if (stdma_is_locked_by(floppy_irq)) ++ stdma_release(); + local_irq_restore(flags); + + DPRINT(("finish_fdc() finished\n")); +@@ -1477,7 +1501,9 @@ static blk_status_t ataflop_queue_rq(str + int drive = floppy - unit; + int type = floppy->type; + +- DPRINT(("Queue request: drive %d type %d last %d\n", drive, type, bd->last)); ++ DPRINT(("Queue request: drive %d type %d sectors %d of %d last %d\n", ++ drive, type, blk_rq_cur_sectors(bd->rq), ++ blk_rq_sectors(bd->rq), bd->last)); + + spin_lock_irq(&ataflop_lock); + if (fd_request) { +@@ -1499,6 +1525,7 @@ static blk_status_t ataflop_queue_rq(str + /* drive not connected */ + printk(KERN_ERR "Unknown Device: fd%d\n", drive ); + fd_end_request_cur(BLK_STS_IOERR); ++ stdma_release(); + goto out; + } + +@@ -1515,11 +1542,13 @@ static blk_status_t ataflop_queue_rq(str + if (--type >= NUM_DISK_MINORS) { + printk(KERN_WARNING "fd%d: invalid disk format", drive ); + fd_end_request_cur(BLK_STS_IOERR); ++ stdma_release(); + goto out; + } + if (minor2disktype[type].drive_types > DriveType) { + printk(KERN_WARNING "fd%d: unsupported disk format", drive ); + fd_end_request_cur(BLK_STS_IOERR); ++ stdma_release(); + goto out; + } + type = minor2disktype[type].index; +@@ -1620,6 +1649,7 @@ static int fd_locked_ioctl(struct block_ + /* what if type > 0 here? Overwrite specified entry ? */ + if (type) { + /* refuse to re-set a predefined type for now */ ++ finish_fdc(); + return -EINVAL; + } + +@@ -1687,8 +1717,10 @@ static int fd_locked_ioctl(struct block_ + + /* sanity check */ + if (setprm.track != dtp->blocks/dtp->spt/2 || +- setprm.head != 2) ++ setprm.head != 2) { ++ finish_fdc(); + return -EINVAL; ++ } + + UDT = dtp; + set_capacity(floppy->disk, UDT->blocks); diff --git a/queue-5.10/series b/queue-5.10/series index 7d210bdace4..fdd4222ed42 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -116,3 +116,4 @@ netfilter-nf_tables-set-dormant-flag-on-hook-registe.patch drm-syncobj-make-lockdep-complain-on-wait_for_submit.patch drm-syncobj-call-drm_syncobj_fence_add_wait-when-wai.patch drm-amd-display-fix-memory-leak-in-dm_sw_fini.patch +block-ataflop-more-blk-mq-refactoring-fixes.patch