From 3d86739c6343fb9c45ba7c4171ff35f526a49b5f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 6 Apr 2021 08:17:55 +0200 Subject: floppy: always use the track buffer Always use the track buffer that is already used for addresses outside the 16MB address capability of the floppy controller. This allows to remove a lot of code that relies on kernel virtual addresses. With this gone there is just a single place left that looks at the bio, which can be converted to memcpy_{from,to}_page, thus removing the need for the extra block-layer bounce buffering for highmem pages. Signed-off-by: Christoph Hellwig Link: https://lore.kernel.org/r/20210406061755.811522-1-hch@lst.de Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 136 +++++++++---------------------------------------- 1 file changed, 25 insertions(+), 111 deletions(-) (limited to 'drivers/block/floppy.c') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 0b71292d9d5a..960e5791d6f5 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -2399,11 +2399,10 @@ static void rw_interrupt(void) probing = 0; } - if (CT(raw_cmd->cmd[COMMAND]) != FD_READ || - raw_cmd->kernel_data == bio_data(current_req->bio)) { + if (CT(raw_cmd->cmd[COMMAND]) != FD_READ) { /* transfer directly from buffer */ cont->done(1); - } else if (CT(raw_cmd->cmd[COMMAND]) == FD_READ) { + } else { buffer_track = raw_cmd->track; buffer_drive = current_drive; INFBOUND(buffer_max, nr_sectors + fsector_t); @@ -2411,27 +2410,6 @@ static void rw_interrupt(void) cont->redo(); } -/* Compute maximal contiguous buffer size. */ -static int buffer_chain_size(void) -{ - struct bio_vec bv; - int size; - struct req_iterator iter; - char *base; - - base = bio_data(current_req->bio); - size = 0; - - rq_for_each_segment(bv, current_req, iter) { - if (page_address(bv.bv_page) + bv.bv_offset != base + size) - break; - - size += bv.bv_len; - } - - return size >> 9; -} - /* Compute the maximal transfer size */ static int transfer_size(int ssize, int max_sector, int max_size) { @@ -2453,7 +2431,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) { int remaining; /* number of transferred 512-byte sectors */ struct bio_vec bv; - char *buffer; char *dma_buffer; int size; struct req_iterator iter; @@ -2492,8 +2469,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) size = bv.bv_len; SUPBOUND(size, remaining); - - buffer = page_address(bv.bv_page) + bv.bv_offset; if (dma_buffer + size > floppy_track_buffer + (max_buffer_sectors << 10) || dma_buffer < floppy_track_buffer) { @@ -2509,13 +2484,13 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) pr_info("write\n"); break; } - if (((unsigned long)buffer) % 512) - DPRINT("%p buffer not aligned\n", buffer); if (CT(raw_cmd->cmd[COMMAND]) == FD_READ) - memcpy(buffer, dma_buffer, size); + memcpy_to_page(bv.bv_page, bv.bv_offset, dma_buffer, + size); else - memcpy(dma_buffer, buffer, size); + memcpy_from_page(dma_buffer, bv.bv_page, bv.bv_offset, + size); remaining -= size; dma_buffer += size; @@ -2690,54 +2665,6 @@ static int make_raw_rw_request(void) raw_cmd->flags &= ~FD_RAW_WRITE; raw_cmd->flags |= FD_RAW_READ; raw_cmd->cmd[COMMAND] = FM_MODE(_floppy, FD_READ); - } else if ((unsigned long)bio_data(current_req->bio) < MAX_DMA_ADDRESS) { - unsigned long dma_limit; - int direct, indirect; - - indirect = - transfer_size(ssize, max_sector, - max_buffer_sectors * 2) - fsector_t; - - /* - * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide - * on a 64 bit machine! - */ - max_size = buffer_chain_size(); - dma_limit = (MAX_DMA_ADDRESS - - ((unsigned long)bio_data(current_req->bio))) >> 9; - if ((unsigned long)max_size > dma_limit) - max_size = dma_limit; - /* 64 kb boundaries */ - if (CROSS_64KB(bio_data(current_req->bio), max_size << 9)) - max_size = (K_64 - - ((unsigned long)bio_data(current_req->bio)) % - K_64) >> 9; - direct = transfer_size(ssize, max_sector, max_size) - fsector_t; - /* - * We try to read tracks, but if we get too many errors, we - * go back to reading just one sector at a time. - * - * This means we should be able to read a sector even if there - * are other bad sectors on this track. - */ - if (!direct || - (indirect * 2 > direct * 3 && - *errors < drive_params[current_drive].max_errors.read_track && - ((!probing || - (drive_params[current_drive].read_track & (1 << drive_state[current_drive].probed_format)))))) { - max_size = blk_rq_sectors(current_req); - } else { - raw_cmd->kernel_data = bio_data(current_req->bio); - raw_cmd->length = current_count_sectors << 9; - if (raw_cmd->length == 0) { - DPRINT("%s: zero dma transfer attempted\n", __func__); - DPRINT("indirect=%d direct=%d fsector_t=%d\n", - indirect, direct, fsector_t); - return 0; - } - virtualdmabug_workaround(); - return 2; - } } if (CT(raw_cmd->cmd[COMMAND]) == FD_READ) @@ -2781,19 +2708,17 @@ static int make_raw_rw_request(void) raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1; raw_cmd->length <<= 9; if ((raw_cmd->length < current_count_sectors << 9) || - (raw_cmd->kernel_data != bio_data(current_req->bio) && - CT(raw_cmd->cmd[COMMAND]) == FD_WRITE && + (CT(raw_cmd->cmd[COMMAND]) == FD_WRITE && (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max || aligned_sector_t < buffer_min)) || raw_cmd->length % (128 << raw_cmd->cmd[SIZECODE]) || raw_cmd->length <= 0 || current_count_sectors <= 0) { DPRINT("fractionary current count b=%lx s=%lx\n", raw_cmd->length, current_count_sectors); - if (raw_cmd->kernel_data != bio_data(current_req->bio)) - pr_info("addr=%d, length=%ld\n", - (int)((raw_cmd->kernel_data - - floppy_track_buffer) >> 9), - current_count_sectors); + pr_info("addr=%d, length=%ld\n", + (int)((raw_cmd->kernel_data - + floppy_track_buffer) >> 9), + current_count_sectors); pr_info("st=%d ast=%d mse=%d msi=%d\n", fsector_t, aligned_sector_t, max_sector, max_size); pr_info("ssize=%x SIZECODE=%d\n", ssize, raw_cmd->cmd[SIZECODE]); @@ -2807,31 +2732,21 @@ static int make_raw_rw_request(void) return 0; } - if (raw_cmd->kernel_data != bio_data(current_req->bio)) { - if (raw_cmd->kernel_data < floppy_track_buffer || - current_count_sectors < 0 || - raw_cmd->length < 0 || - raw_cmd->kernel_data + raw_cmd->length > - floppy_track_buffer + (max_buffer_sectors << 10)) { - DPRINT("buffer overrun in schedule dma\n"); - pr_info("fsector_t=%d buffer_min=%d current_count=%ld\n", - fsector_t, buffer_min, raw_cmd->length >> 9); - pr_info("current_count_sectors=%ld\n", - current_count_sectors); - if (CT(raw_cmd->cmd[COMMAND]) == FD_READ) - pr_info("read\n"); - if (CT(raw_cmd->cmd[COMMAND]) == FD_WRITE) - pr_info("write\n"); - return 0; - } - } else if (raw_cmd->length > blk_rq_bytes(current_req) || - current_count_sectors > blk_rq_sectors(current_req)) { - DPRINT("buffer overrun in direct transfer\n"); + if (raw_cmd->kernel_data < floppy_track_buffer || + current_count_sectors < 0 || + raw_cmd->length < 0 || + raw_cmd->kernel_data + raw_cmd->length > + floppy_track_buffer + (max_buffer_sectors << 10)) { + DPRINT("buffer overrun in schedule dma\n"); + pr_info("fsector_t=%d buffer_min=%d current_count=%ld\n", + fsector_t, buffer_min, raw_cmd->length >> 9); + pr_info("current_count_sectors=%ld\n", + current_count_sectors); + if (CT(raw_cmd->cmd[COMMAND]) == FD_READ) + pr_info("read\n"); + if (CT(raw_cmd->cmd[COMMAND]) == FD_WRITE) + pr_info("write\n"); return 0; - } else if (raw_cmd->length < current_count_sectors << 9) { - DPRINT("more sectors than bytes\n"); - pr_info("bytes=%ld\n", raw_cmd->length >> 9); - pr_info("sectors=%ld\n", current_count_sectors); } if (raw_cmd->length == 0) { DPRINT("zero dma transfer attempted from make_raw_request\n"); @@ -4597,7 +4512,6 @@ static int floppy_alloc_disk(unsigned int drive, unsigned int type) return err; } - blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH); blk_queue_max_hw_sectors(disk->queue, 64); disk->major = FLOPPY_MAJOR; disk->first_minor = TOMINOR(drive) | (type << 2); -- cgit v1.2.3 From 67c07161c5035a68eccd3922b11cb9839f28c8a3 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Fri, 16 Apr 2021 11:34:46 +0300 Subject: floppy: cleanups: use ST0 as reply_buffer index 0 Use ST0 as 0 index for reply_buffer array. get_fdc_version() is the only function that uses index 0 directly instead of the ST0 define. Signed-off-by: Denis Efremov Link: https://lore.kernel.org/r/20210416083449.72700-3-efremov@linux.com Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/block/floppy.c') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 960e5791d6f5..df5c32900539 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4232,7 +4232,7 @@ static char __init get_fdc_version(int fdc) r = result(fdc); if (r <= 0x00) return FDC_NONE; /* No FDC present ??? */ - if ((r == 1) && (reply_buffer[0] == 0x80)) { + if ((r == 1) && (reply_buffer[ST0] == 0x80)) { pr_info("FDC %d is an 8272A\n", fdc); return FDC_8272A; /* 8272a/765 don't know DUMPREGS */ } @@ -4257,12 +4257,12 @@ static char __init get_fdc_version(int fdc) output_byte(fdc, FD_UNLOCK); r = result(fdc); - if ((r == 1) && (reply_buffer[0] == 0x80)) { + if ((r == 1) && (reply_buffer[ST0] == 0x80)) { pr_info("FDC %d is a pre-1991 82077\n", fdc); return FDC_82077_ORIG; /* Pre-1991 82077, doesn't know * LOCK/UNLOCK */ } - if ((r != 1) || (reply_buffer[0] != 0x00)) { + if ((r != 1) || (reply_buffer[ST0] != 0x00)) { pr_info("FDC %d init: UNLOCK: unexpected return of %d bytes.\n", fdc, r); return FDC_UNKNOWN; @@ -4274,11 +4274,11 @@ static char __init get_fdc_version(int fdc) fdc, r); return FDC_UNKNOWN; } - if (reply_buffer[0] == 0x80) { + if (reply_buffer[ST0] == 0x80) { pr_info("FDC %d is a post-1991 82077\n", fdc); return FDC_82077; /* Revised 82077AA passes all the tests */ } - switch (reply_buffer[0] >> 5) { + switch (reply_buffer[ST0] >> 5) { case 0x0: /* Either a 82078-1 or a 82078SL running at 5Volt */ pr_info("FDC %d is an 82078.\n", fdc); @@ -4294,7 +4294,7 @@ static char __init get_fdc_version(int fdc) return FDC_87306; default: pr_info("FDC %d init: 82078 variant with unknown PARTID=%d.\n", - fdc, reply_buffer[0] >> 5); + fdc, reply_buffer[ST0] >> 5); return FDC_82078_UNKN; } } /* get_fdc_version */ -- cgit v1.2.3 From f6df18f20d5bd496c4c2cb7564853cb60543332a Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Fri, 16 Apr 2021 11:34:47 +0300 Subject: floppy: cleanups: use memset() to zero reply_buffer Use memset() to zero reply buffer in raw_cmd_copyin() instead of a for loop. Signed-off-by: Denis Efremov Link: https://lore.kernel.org/r/20210416083449.72700-4-efremov@linux.com Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/block/floppy.c') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index df5c32900539..c58b0b079afc 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3090,7 +3090,6 @@ static int raw_cmd_copyin(int cmd, void __user *param, { struct floppy_raw_cmd *ptr; int ret; - int i; *rcmd = NULL; @@ -3109,8 +3108,7 @@ loop: if (ptr->cmd_count > FD_RAW_CMD_FULLSIZE) return -EINVAL; - for (i = 0; i < FD_RAW_REPLY_SIZE; i++) - ptr->reply[i] = 0; + memset(ptr->reply, 0, FD_RAW_REPLY_SIZE); ptr->resultcode = 0; if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { -- cgit v1.2.3 From fa6b885e876ed4d29d1513fcf2d8bdc5c4b3b527 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Fri, 16 Apr 2021 11:34:48 +0300 Subject: floppy: cleanups: use memcpy() to copy reply_buffer Use memcpy() in raw_cmd_done() to copy reply_buffer instead of a for loop. Signed-off-by: Denis Efremov Link: https://lore.kernel.org/r/20210416083449.72700-5-efremov@linux.com Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/block/floppy.c') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index c58b0b079afc..c584657bacab 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -2988,8 +2988,6 @@ static const char *drive_name(int type, int drive) /* raw commands */ static void raw_cmd_done(int flag) { - int i; - if (!flag) { raw_cmd->flags |= FD_RAW_FAILURE; raw_cmd->flags |= FD_RAW_HARDFAILURE; @@ -2997,8 +2995,7 @@ static void raw_cmd_done(int flag) raw_cmd->reply_count = inr; if (raw_cmd->reply_count > FD_RAW_REPLY_SIZE) raw_cmd->reply_count = 0; - for (i = 0; i < raw_cmd->reply_count; i++) - raw_cmd->reply[i] = reply_buffer[i]; + memcpy(raw_cmd->reply, reply_buffer, raw_cmd->reply_count); if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE)) { unsigned long flags; -- cgit v1.2.3 From a720e11f0a9a016266c8757f06e72622bea86a54 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Fri, 16 Apr 2021 11:34:49 +0300 Subject: floppy: cleanups: remove FLOPPY_SILENT_DCL_CLEAR undef FLOPPY_SILENT_DCL_CLEAR is not defined anywhere and comes from pre-git era. Just drop this undef. There is FD_SILENT_DCL_CLEAR which is really used. Signed-off-by: Denis Efremov Link: https://lore.kernel.org/r/20210416083449.72700-6-efremov@linux.com Signed-off-by: Jens Axboe --- drivers/block/floppy.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/block/floppy.c') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index c584657bacab..678ea45f2388 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -145,8 +145,6 @@ * Better audit of register_blkdev. */ -#undef FLOPPY_SILENT_DCL_CLEAR - #define REALLY_SLOW_IO #define DEBUGT 2 -- cgit v1.2.3