Commit 3d86739c authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe

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: default avatarChristoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20210406061755.811522-1-hch@lst.deSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 4c6e5bc8
...@@ -2399,11 +2399,10 @@ static void rw_interrupt(void) ...@@ -2399,11 +2399,10 @@ static void rw_interrupt(void)
probing = 0; probing = 0;
} }
if (CT(raw_cmd->cmd[COMMAND]) != FD_READ || if (CT(raw_cmd->cmd[COMMAND]) != FD_READ) {
raw_cmd->kernel_data == bio_data(current_req->bio)) {
/* transfer directly from buffer */ /* transfer directly from buffer */
cont->done(1); cont->done(1);
} else if (CT(raw_cmd->cmd[COMMAND]) == FD_READ) { } else {
buffer_track = raw_cmd->track; buffer_track = raw_cmd->track;
buffer_drive = current_drive; buffer_drive = current_drive;
INFBOUND(buffer_max, nr_sectors + fsector_t); INFBOUND(buffer_max, nr_sectors + fsector_t);
...@@ -2411,27 +2410,6 @@ static void rw_interrupt(void) ...@@ -2411,27 +2410,6 @@ static void rw_interrupt(void)
cont->redo(); 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 */ /* Compute the maximal transfer size */
static int transfer_size(int ssize, int max_sector, int max_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) ...@@ -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 */ int remaining; /* number of transferred 512-byte sectors */
struct bio_vec bv; struct bio_vec bv;
char *buffer;
char *dma_buffer; char *dma_buffer;
int size; int size;
struct req_iterator iter; struct req_iterator iter;
...@@ -2492,8 +2469,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) ...@@ -2492,8 +2469,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
size = bv.bv_len; size = bv.bv_len;
SUPBOUND(size, remaining); SUPBOUND(size, remaining);
buffer = page_address(bv.bv_page) + bv.bv_offset;
if (dma_buffer + size > if (dma_buffer + size >
floppy_track_buffer + (max_buffer_sectors << 10) || floppy_track_buffer + (max_buffer_sectors << 10) ||
dma_buffer < floppy_track_buffer) { dma_buffer < floppy_track_buffer) {
...@@ -2509,13 +2484,13 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) ...@@ -2509,13 +2484,13 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
pr_info("write\n"); pr_info("write\n");
break; break;
} }
if (((unsigned long)buffer) % 512)
DPRINT("%p buffer not aligned\n", buffer);
if (CT(raw_cmd->cmd[COMMAND]) == FD_READ) 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 else
memcpy(dma_buffer, buffer, size); memcpy_from_page(dma_buffer, bv.bv_page, bv.bv_offset,
size);
remaining -= size; remaining -= size;
dma_buffer += size; dma_buffer += size;
...@@ -2690,54 +2665,6 @@ static int make_raw_rw_request(void) ...@@ -2690,54 +2665,6 @@ static int make_raw_rw_request(void)
raw_cmd->flags &= ~FD_RAW_WRITE; raw_cmd->flags &= ~FD_RAW_WRITE;
raw_cmd->flags |= FD_RAW_READ; raw_cmd->flags |= FD_RAW_READ;
raw_cmd->cmd[COMMAND] = FM_MODE(_floppy, FD_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) if (CT(raw_cmd->cmd[COMMAND]) == FD_READ)
...@@ -2781,19 +2708,17 @@ static int make_raw_rw_request(void) ...@@ -2781,19 +2708,17 @@ static int make_raw_rw_request(void)
raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1; raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1;
raw_cmd->length <<= 9; raw_cmd->length <<= 9;
if ((raw_cmd->length < current_count_sectors << 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 + (raw_cmd->length >> 9) > buffer_max ||
aligned_sector_t < buffer_min)) || aligned_sector_t < buffer_min)) ||
raw_cmd->length % (128 << raw_cmd->cmd[SIZECODE]) || raw_cmd->length % (128 << raw_cmd->cmd[SIZECODE]) ||
raw_cmd->length <= 0 || current_count_sectors <= 0) { raw_cmd->length <= 0 || current_count_sectors <= 0) {
DPRINT("fractionary current count b=%lx s=%lx\n", DPRINT("fractionary current count b=%lx s=%lx\n",
raw_cmd->length, current_count_sectors); raw_cmd->length, current_count_sectors);
if (raw_cmd->kernel_data != bio_data(current_req->bio)) pr_info("addr=%d, length=%ld\n",
pr_info("addr=%d, length=%ld\n", (int)((raw_cmd->kernel_data -
(int)((raw_cmd->kernel_data - floppy_track_buffer) >> 9),
floppy_track_buffer) >> 9), current_count_sectors);
current_count_sectors);
pr_info("st=%d ast=%d mse=%d msi=%d\n", pr_info("st=%d ast=%d mse=%d msi=%d\n",
fsector_t, aligned_sector_t, max_sector, max_size); fsector_t, aligned_sector_t, max_sector, max_size);
pr_info("ssize=%x SIZECODE=%d\n", ssize, raw_cmd->cmd[SIZECODE]); pr_info("ssize=%x SIZECODE=%d\n", ssize, raw_cmd->cmd[SIZECODE]);
...@@ -2807,31 +2732,21 @@ static int make_raw_rw_request(void) ...@@ -2807,31 +2732,21 @@ static int make_raw_rw_request(void)
return 0; return 0;
} }
if (raw_cmd->kernel_data != bio_data(current_req->bio)) { if (raw_cmd->kernel_data < floppy_track_buffer ||
if (raw_cmd->kernel_data < floppy_track_buffer || current_count_sectors < 0 ||
current_count_sectors < 0 || raw_cmd->length < 0 ||
raw_cmd->length < 0 || raw_cmd->kernel_data + raw_cmd->length >
raw_cmd->kernel_data + raw_cmd->length > floppy_track_buffer + (max_buffer_sectors << 10)) {
floppy_track_buffer + (max_buffer_sectors << 10)) { DPRINT("buffer overrun in schedule dma\n");
DPRINT("buffer overrun in schedule dma\n"); pr_info("fsector_t=%d buffer_min=%d current_count=%ld\n",
pr_info("fsector_t=%d buffer_min=%d current_count=%ld\n", fsector_t, buffer_min, raw_cmd->length >> 9);
fsector_t, buffer_min, raw_cmd->length >> 9); pr_info("current_count_sectors=%ld\n",
pr_info("current_count_sectors=%ld\n", current_count_sectors);
current_count_sectors); if (CT(raw_cmd->cmd[COMMAND]) == FD_READ)
if (CT(raw_cmd->cmd[COMMAND]) == FD_READ) pr_info("read\n");
pr_info("read\n"); if (CT(raw_cmd->cmd[COMMAND]) == FD_WRITE)
if (CT(raw_cmd->cmd[COMMAND]) == FD_WRITE) pr_info("write\n");
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");
return 0; 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) { if (raw_cmd->length == 0) {
DPRINT("zero dma transfer attempted from make_raw_request\n"); 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) ...@@ -4597,7 +4512,6 @@ static int floppy_alloc_disk(unsigned int drive, unsigned int type)
return err; return err;
} }
blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
blk_queue_max_hw_sectors(disk->queue, 64); blk_queue_max_hw_sectors(disk->queue, 64);
disk->major = FLOPPY_MAJOR; disk->major = FLOPPY_MAJOR;
disk->first_minor = TOMINOR(drive) | (type << 2); disk->first_minor = TOMINOR(drive) | (type << 2);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment