]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 27 Feb 2024 09:17:54 +0000 (10:17 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 27 Feb 2024 09:17:54 +0000 (10:17 +0100)
added patches:
block-ataflop-more-blk-mq-refactoring-fixes.patch

queue-5.10/block-ataflop-more-blk-mq-refactoring-fixes.patch [new file with mode: 0644]
queue-5.10/series

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 (file)
index 0000000..e86d384
--- /dev/null
@@ -0,0 +1,210 @@
+From d28e4dff085c5a87025c9a0a85fb798bd8e9ca17 Mon Sep 17 00:00:00 2001
+From: Michael Schmitz <schmitzmic@gmail.com>
+Date: Sun, 24 Oct 2021 13:20:13 +1300
+Subject: block: ataflop: more blk-mq refactoring fixes
+
+From: Michael Schmitz <schmitzmic@gmail.com>
+
+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 <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>
+[MSch: v5.10 backport merge conflict fix]
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
index 7d210bdace4ffcdd053a7ad399166c6e7eb4cbed..fdd4222ed42657c5f0ed7367197b928bb7c62bee 100644 (file)
@@ -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