lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <200712200238.07525.bzolnier@gmail.com>
Date:	Thu, 20 Dec 2007 02:38:07 +0100
From:	Bartlomiej Zolnierkiewicz <bzolnier@...il.com>
To:	linux-ide@...r.kernel.org
Cc:	linux-kernel@...r.kernel.org
Subject: [PATCH 60/63] ide-cd: merge cdrom_rw_intr() and cdrom_newpc_intr()


Add handling of fs read/write requests to cdrom_nepwc_intr()
and remove no longer needed cdrom_rw_intr().

There should be no functionality changes caused by this patch.

Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@...il.com>
---
-496 bytes
 drivers/ide/ide-cd.c |  272 +++++++++++++++++----------------------------------
 1 file changed, 94 insertions(+), 178 deletions(-)

Index: b/drivers/ide/ide-cd.c
===================================================================
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -797,7 +797,7 @@ static int cdrom_read_from_buffer (ide_d
 	return 0;
 }
 
-static ide_startstop_t cdrom_rw_intr(ide_drive_t *);
+static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
 
 /*
  * Routine to send a read/write packet command to the drive.
@@ -846,7 +846,7 @@ static ide_startstop_t cdrom_start_rw_co
 	rq->timeout = ATAPI_WAIT_PC;
 
 	/* Send the command to the drive and return. */
-	return cdrom_transfer_packet_command(drive, rq, cdrom_rw_intr);
+	return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
 }
 
 #define IDECD_SEEK_THRESHOLD	(1000)			/* 1000 blocks */
@@ -1013,17 +1013,12 @@ static int cdrom_write_check_ireason(ide
 	return 1;
 }
 
-/*
- * best way to deal with dma that is not sector aligned right now... note
- * that in this path we are not using ->data or ->buffer at all. this irs
- * can replace cdrom_rw_intr() in the future.
- */
 static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
 {
 	struct cdrom_info *info = drive->driver_data;
 	struct request *rq = HWGROUP(drive)->rq;
 	xfer_func_t *xferfunc;
-	ide_expiry_t *expiry;
+	ide_expiry_t *expiry = NULL;
 	int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0;
 	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
 	unsigned int timeout;
@@ -1051,6 +1046,10 @@ static ide_startstop_t cdrom_newpc_intr(
 		if (dma_error)
 			return ide_error(drive, "dma error", stat);
 
+		if (blk_fs_request(rq)) {
+			ide_end_request(drive, 1, rq->nr_sectors);
+			return ide_stopped;
+		}
 		end_that_request_chunk(rq, 1, rq->data_len);
 		rq->data_len = 0;
 		goto end_request;
@@ -1064,7 +1063,8 @@ static ide_startstop_t cdrom_newpc_intr(
 	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
 
 	len = lowcyl + (256 * highcyl);
-	thislen = rq->data_len;
+
+	thislen = blk_fs_request(rq) ? len : rq->data_len;
 	if (thislen > len)
 		thislen = len;
 
@@ -1072,7 +1072,24 @@ static ide_startstop_t cdrom_newpc_intr(
 	 * If DRQ is clear, the command has completed.
 	 */
 	if ((stat & DRQ_STAT) == 0) {
-		if (!blk_pc_request(rq)) {
+		if (blk_fs_request(rq)) {
+			/*
+			 * If we're not done reading/writing, complain.
+			 * Otherwise, complete the command normally.
+			 */
+			uptodate = 1;
+			if (rq->current_nr_sectors > 0) {
+				printk(KERN_ERR "%s: %s: data underrun "
+						"(%d blocks)\n",
+						drive->name, __FUNCTION__,
+						rq->current_nr_sectors);
+				if (!write)
+					rq->cmd_flags |= REQ_FAILED;
+				uptodate = 0;
+			}
+			cdrom_end_request(drive, uptodate);
+			return ide_stopped;
+		} else if (!blk_pc_request(rq)) {
 			ide_cd_request_sense_fixup(rq);
 			/* Complain if we still have data left to transfer. */
 			uptodate = rq->data_len ? 0 : 1;
@@ -1083,24 +1100,47 @@ static ide_startstop_t cdrom_newpc_intr(
 	/*
 	 * check which way to transfer data
 	 */
-	if (blk_pc_request(rq) && rq_data_dir(rq) == WRITE) {
+	if ((blk_fs_request(rq) || blk_pc_request(rq)) && write) {
 		/*
 		 * write to drive
 		 */
 		if (cdrom_write_check_ireason(drive, len, ireason))
 			return ide_stopped;
-	} else if (blk_pc_request(rq)) {
+	} else if (blk_fs_request(rq) || blk_pc_request(rq)) {
 		/*
 		 * read from drive
 		 */
 		if (cdrom_read_check_ireason(drive, len, ireason))
 			return ide_stopped;
+
+		if (blk_fs_request(rq)) {
+			int nskip;
+
+			if (ide_cd_check_transfer_size(drive, len)) {
+				cdrom_end_request(drive, 0);
+				return ide_stopped;
+			}
+
+			/*
+			 * First, figure out if we need to bit-bucket
+			 * any of the leading sectors.
+			 */
+			nskip = min_t(int, rq->current_nr_sectors
+					   - bio_cur_sectors(rq->bio),
+					   thislen >> 9);
+			if (nskip > 0) {
+				ide_cd_drain_data(drive, nskip);
+				rq->current_nr_sectors -= nskip;
+				thislen -= (nskip << 9);
+			}
+		}
 	}
 
 	if (ireason == 0) {
 		write = 1;
 		xferfunc = HWIF(drive)->atapi_output_bytes;
-	} else if (ireason == 2 || (ireason == 1 && blk_pc_request(rq))) {
+	} else if (ireason == 2 || (ireason == 1 &&
+		   (blk_fs_request(rq) || blk_pc_request(rq)))) {
 		write = 0;
 		xferfunc = HWIF(drive)->atapi_input_bytes;
 	} else {
@@ -1115,23 +1155,37 @@ static ide_startstop_t cdrom_newpc_intr(
 	 * transfer data
 	 */
 	while (thislen > 0) {
-		u8 *ptr = rq->data;
+		u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
 		int blen = rq->data_len;
 
 		/*
 		 * bio backed?
 		 */
 		if (rq->bio) {
-			ptr = bio_data(rq->bio);
-			blen = bio_iovec(rq->bio)->bv_len;
+			if (blk_fs_request(rq)) {
+				ptr = rq->buffer;
+				blen = rq->current_nr_sectors << 9;
+			} else {
+				ptr = bio_data(rq->bio);
+				blen = bio_iovec(rq->bio)->bv_len;
+			}
 		}
 
 		if (!ptr) {
-			printk(KERN_ERR "%s: confused, missing data\n",
-					drive->name);
-			blk_dump_rq_flags(rq, rq_data_dir(rq)
-					      ? "cdrom_newpc_intr, write"
-					      : "cdrom_newpc_intr, read");
+			if (blk_fs_request(rq) && !write)
+				/*
+				 * If the buffers are full, cache the rest
+				 * of the data in our internal buffer.
+				 */
+				cdrom_buffer_sectors(drive, rq->sector,
+						     thislen >> 9);
+			else {
+				printk(KERN_ERR "%s: confused, missing data\n",
+						drive->name);
+				blk_dump_rq_flags(rq, rq_data_dir(rq)
+						  ? "cdrom_newpc_intr, write"
+						  : "cdrom_newpc_intr, read");
+			}
 			break;
 		}
 
@@ -1142,12 +1196,23 @@ static ide_startstop_t cdrom_newpc_intr(
 
 		thislen -= blen;
 		len -= blen;
-		rq->data_len -= blen;
 
-		if (rq->bio)
-			end_that_request_chunk(rq, 1, blen);
-		else
-			rq->data += blen;
+		if (blk_fs_request(rq)) {
+			rq->buffer += blen;
+			rq->nr_sectors -= (blen >> 9);
+			rq->current_nr_sectors -= (blen >> 9);
+			rq->sector += (blen >> 9);
+
+			if (rq->current_nr_sectors == 0 && rq->nr_sectors)
+				cdrom_end_request(drive, 1);
+		} else {
+			rq->data_len -= blen;
+
+			if (rq->bio)
+				end_that_request_chunk(rq, 1, blen);
+			else
+				rq->data += blen;
+		}
 	}
 
 	if (write && blk_sense_request(rq))
@@ -1156,15 +1221,15 @@ static ide_startstop_t cdrom_newpc_intr(
 	/*
 	 * pad, if necessary
 	 */
-	if (len > 0)
+	if (!blk_fs_request(rq) && len > 0)
 		ide_cd_pad_transfer(drive, xferfunc, len);
 
 	if (blk_pc_request(rq)) {
 		timeout = rq->timeout;
-		expiry = NULL;
 	} else {
 		timeout = ATAPI_WAIT_PC;
-		expiry = cdrom_timer_expiry;
+		if (!blk_fs_request(rq))
+			expiry = cdrom_timer_expiry;
 	}
 
 	ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry);
@@ -1187,155 +1252,6 @@ end_request:
 	return ide_stopped;
 }
 
-static ide_startstop_t cdrom_rw_intr(ide_drive_t *drive)
-{
-	struct cdrom_info *info = drive->driver_data;
-	struct request *rq = HWGROUP(drive)->rq;
-	xfer_func_t *xferfunc;
-	int stat, ireason, len, thislen, uptodate, nskip;
-	int dma_error = 0, dma = info->dma, write = rq_data_dir(rq) == WRITE;
-	u8 lowcyl = 0, highcyl = 0;
-
-	/* Check for errors. */
-	if (dma) {
-		info->dma = 0;
-		dma_error = HWIF(drive)->ide_dma_end(drive);
-		if (dma_error) {
-			printk(KERN_ERR "%s: DMA %s error\n", drive->name,
-					write ? "write" : "read");
-			ide_dma_off(drive);
-		}
-	}
-
-	if (cdrom_decode_status(drive, 0, &stat))
-		return ide_stopped;
-
-	/*
-	 * using dma, transfer is complete now
-	 */
-	if (dma) {
-		if (dma_error)
-			return ide_error(drive, "dma error", stat);
-
-		ide_end_request(drive, 1, rq->nr_sectors);
-		return ide_stopped;
-	}
-
-	/* Read the interrupt reason and the transfer length. */
-	ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
-	lowcyl  = HWIF(drive)->INB(IDE_BCOUNTL_REG);
-	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
-
-	len = lowcyl + (256 * highcyl);
-
-	/* If DRQ is clear, the command has completed. */
-	if ((stat & DRQ_STAT) == 0) {
-		/*
-		 * If we're not done reading/writing, complain.
-		 * Otherwise, complete the command normally.
-		 */
-		uptodate = 1;
-		if (rq->current_nr_sectors > 0) {
-			printk(KERN_ERR "%s: %s: data underrun (%d blocks)\n",
-					drive->name, __FUNCTION__,
-					rq->current_nr_sectors);
-			if (!write)
-				rq->cmd_flags |= REQ_FAILED;
-			uptodate = 0;
-		}
-		cdrom_end_request(drive, uptodate);
-		return ide_stopped;
-	}
-
-	thislen = len;
-
-	/* Check that the drive is expecting to do the same thing we are. */
-	if (write) {
-		if (cdrom_write_check_ireason(drive, len, ireason))
-			return ide_stopped;
-
-		xferfunc = HWIF(drive)->atapi_output_bytes;
-	} else {
-		if (cdrom_read_check_ireason(drive, len, ireason))
-			return ide_stopped;
-
-		if (ide_cd_check_transfer_size(drive, len)) {
-			cdrom_end_request(drive, 0);
-			return ide_stopped;
-		}
-
-		/*
-		 * First, figure out if we need to bit-bucket
-		 * any of the leading sectors.
-		 */
-		nskip = min_t(int, rq->current_nr_sectors
-				   - bio_cur_sectors(rq->bio),
-				   thislen >> 9);
-
-		if (nskip > 0) {
-			ide_cd_drain_data(drive, nskip);
-			rq->current_nr_sectors -= nskip;
-			thislen -= (nskip << 9);
-		}
-
-		xferfunc = HWIF(drive)->atapi_input_bytes;
-	}
-
-	/*
-	 * now loop and read/write the data
-	 */
-	while (thislen > 0) {
-		u8 *ptr = NULL;
-		int blen;
-
-		if (rq->bio) {
-			ptr = rq->buffer;
-			blen = rq->current_nr_sectors << 9;
-		}
-
-		if (!ptr) {
-			if (!write)
-				/*
-				 * If the buffers are full, cache the rest
-				 * of the data in our internal buffer.
-				 */
-				cdrom_buffer_sectors(drive, rq->sector,
-						     thislen >> 9);
-			else {
-				printk(KERN_ERR "%s: %s: confused, missing "
-						"data\n",
-						drive->name, __FUNCTION__);
-				blk_dump_rq_flags(rq, "cdrom_rw_intr, write");
-			}
-			break;
-		}
-
-		/*
-		 * Figure out how many sectors we can transfer
-		 */
-		if (blen > thislen)
-			blen = thislen;
-
-		xferfunc(drive, ptr, blen);
-
-		thislen -= blen;
-		rq->buffer += blen;
-		rq->nr_sectors -= (blen >> 9);
-		rq->current_nr_sectors -= (blen >> 9);
-		rq->sector += (blen >> 9);
-
-		/*
-		 * current buffer complete, move on
-		 */
-		if (rq->current_nr_sectors == 0 && rq->nr_sectors)
-			cdrom_end_request(drive, 1);
-	}
-
-	/* re-arm handler */
-	ide_set_handler(drive, cdrom_rw_intr, ATAPI_WAIT_PC, NULL);
-	return ide_started;
-}
-
 static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
 {
 	struct cdrom_info *cd = drive->driver_data;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ