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

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.de


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 4c6e5bc8
Loading
Loading
Loading
Loading
+25 −111
Original line number Diff line number Diff line
@@ -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,15 +2708,13 @@ 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),
@@ -2807,7 +2732,6 @@ 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 ||
@@ -2824,15 +2748,6 @@ static int make_raw_rw_request(void)
			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;
	} 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");
		return 0;
@@ -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);