* [PATCH] block: ataflop: more blk-mq refactoring fixes
@ 2024-02-27 1:37 Michael Schmitz
2024-02-27 9:06 ` Greg KH
0 siblings, 1 reply; 2+ messages in thread
From: Michael Schmitz @ 2024-02-27 1:37 UTC (permalink / raw)
To: stable; +Cc: linux-m68k, gregkh, geert, Michael Schmitz, Jens Axboe
[ 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)
Fixes: 86d46fdaa12a (block: ataflop: fix breakage introduced at blk-mq refactoring)
CC: stable@vger.kernel.org # 5.10.x
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]
---
drivers/block/ataflop.c | 42 ++++++++++++++++++++++++++++++++++++-----
1 file changed, 37 insertions(+), 5 deletions(-)
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index cd612cd04767..224450c90e45 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -456,10 +456,20 @@ static DEFINE_TIMER(fd_timer, check_change);
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, struct atari_format_descr *desc)
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, struct atari_format_descr *desc)
}
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, struct atari_format_descr *desc)
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_list *unused)
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(struct blk_mq_hw_ctx *hctx,
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(struct blk_mq_hw_ctx *hctx,
/* 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(struct blk_mq_hw_ctx *hctx,
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_device *bdev, fmode_t mode,
/* 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_device *bdev, fmode_t mode,
/* 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);
--
2.17.1
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH] block: ataflop: more blk-mq refactoring fixes
2024-02-27 1:37 [PATCH] block: ataflop: more blk-mq refactoring fixes Michael Schmitz
@ 2024-02-27 9:06 ` Greg KH
0 siblings, 0 replies; 2+ messages in thread
From: Greg KH @ 2024-02-27 9:06 UTC (permalink / raw)
To: Michael Schmitz; +Cc: stable, linux-m68k, geert, Jens Axboe
On Tue, Feb 27, 2024 at 02:37:28PM +1300, Michael Schmitz wrote:
> [ 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)
> Fixes: 86d46fdaa12a (block: ataflop: fix breakage introduced at blk-mq refactoring)
> CC: stable@vger.kernel.org # 5.10.x
> 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]
Now queued up, thanks.
greg k-h
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2024-02-27 9:06 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-27 1:37 [PATCH] block: ataflop: more blk-mq refactoring fixes Michael Schmitz
2024-02-27 9:06 ` Greg KH
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox