[PATCH, RFC] st: start using scsi_execute

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch updates st to use scsi_execute instead of scsi_execute_async
for all scsi commands except the main I/O path.  The advantage is that
these helpers do all the request tracking for these synchronous I/Os so
that there is no need for st_request structures.  It also decouples
these helper scsi commands from the main tape buffer, allowing for an
easier switchover to the generic block request mapping routines for the
main I/O path later on.

Note that I don't have a scsi tape, so this is totally untested and
probably needs some tweaking before it's ready..


Index: scsi-misc-2.6/drivers/scsi/st.c
===================================================================
--- scsi-misc-2.6.orig/drivers/scsi/st.c	2006-01-30 19:14:34.000000000 +0100
+++ scsi-misc-2.6/drivers/scsi/st.c	2006-01-30 19:14:39.000000000 +0100
@@ -308,12 +308,11 @@
 }
 
 
-static void st_analyze_sense(struct st_request *SRpnt, struct st_cmdstatus *s)
+static void st_analyze_sense(const u8 *sense, struct st_cmdstatus *s)
 {
 	const u8 *ucp;
-	const u8 *sense = SRpnt->sense;
 
-	s->have_sense = scsi_normalize_sense(SRpnt->sense,
+	s->have_sense = scsi_normalize_sense(sense,
 				SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
 	s->flags = 0;
 
@@ -341,9 +340,8 @@
 
 
 /* Convert the result to success code */
-static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
+static int st_chk_result(struct scsi_tape *STp, u8 *cmd, u8 *sense, int result)
 {
-	int result = SRpnt->result;
 	u8 scode;
 	DEB(const char *stp;)
 	char *name = tape_name(STp);
@@ -353,7 +351,7 @@
 		return 0;
 
 	cmdstatp = &STp->buffer->cmdstat;
-	st_analyze_sense(SRpnt, cmdstatp);
+	st_analyze_sense(sense, cmdstatp);
 
 	if (cmdstatp->have_sense)
 		scode = STp->buffer->cmdstat.sense_hdr.sense_key;
@@ -364,10 +362,9 @@
         if (debugging) {
                 printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x\n",
 		       name, result,
-		       SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
-		       SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
+		       cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]);
 		if (cmdstatp->have_sense)
-			 __scsi_print_sense("st", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
+			 __scsi_print_sense("st", sense, SCSI_SENSE_BUFFERSIZE);
 	} ) /* end DEB */
 	if (!debugging) { /* Abnormal conditions for tape */
 		if (!cmdstatp->have_sense)
@@ -381,10 +378,10 @@
 			 /* scode != UNIT_ATTENTION && */
 			 scode != BLANK_CHECK &&
 			 scode != VOLUME_OVERFLOW &&
-			 SRpnt->cmd[0] != MODE_SENSE &&
-			 SRpnt->cmd[0] != TEST_UNIT_READY) {
+			 cmd[0] != MODE_SENSE &&
+			 cmd[0] != TEST_UNIT_READY) {
 				printk(KERN_WARNING "%s: Error with sense data: ", name);
-				__scsi_print_sense("st", SRpnt->sense,
+				__scsi_print_sense("st", sense,
 						   SCSI_SENSE_BUFFERSIZE);
 		}
 	}
@@ -392,10 +389,10 @@
 	if (cmdstatp->fixed_format &&
 	    STp->cln_mode >= EXTENDED_SENSE_START) {  /* Only fixed format sense */
 		if (STp->cln_sense_value)
-			STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
+			STp->cleaning_req |= ((sense[STp->cln_mode] &
 					       STp->cln_sense_mask) == STp->cln_sense_value);
 		else
-			STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
+			STp->cleaning_req |= ((sense[STp->cln_mode] &
 					       STp->cln_sense_mask) != 0);
 	}
 	if (cmdstatp->have_sense &&
@@ -407,8 +404,8 @@
 	if (cmdstatp->have_sense &&
 	    scode == RECOVERED_ERROR
 #if ST_RECOVERED_WRITE_FATAL
-	    && SRpnt->cmd[0] != WRITE_6
-	    && SRpnt->cmd[0] != WRITE_FILEMARKS
+	    && cmd[0] != WRITE_6
+	    && cmd[0] != WRITE_FILEMARKS
 #endif
 	    ) {
 		STp->recover_count++;
@@ -416,9 +413,9 @@
 
                 DEB(
 		if (debugging) {
-			if (SRpnt->cmd[0] == READ_6)
+			if (cmd[0] == READ_6)
 				stp = "read";
-			else if (SRpnt->cmd[0] == WRITE_6)
+			else if (cmd[0] == WRITE_6)
 				stp = "write";
 			else
 				stp = "ioctl";
@@ -517,12 +514,48 @@
 	else if (do_wait) {
 		wait_for_completion(waiting);
 		SRpnt->waiting = NULL;
-		(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
+		(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt->cmd,
+							      SRpnt->sense,
+							      SRpnt->result);
 	}
 
 	return SRpnt;
 }
 
+static int
+st_scsi_execute(struct scsi_tape *st, u8 *cmd, int direction, void *buffer,
+		unsigned int buflen, int timeout, int retries)
+{
+	char *sense;
+
+	sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+	if (!sense) {
+		/*
+		 * Slightly odd errno values for memory allocation failure.
+		 * But for now we follow the scheme introduced by st_do_scsi
+		 * long ago.
+		 */
+		st->buffer->syscall_result =
+			signal_pending(current) ? -EINTR : -EBUSY;
+		return 0;
+	}
+
+	st->buffer->cmdstat.have_sense = 0;
+	st->buffer->cmdstat.midlevel_result =
+		scsi_execute(st->device, cmd, direction, NULL, 0,
+				sense, timeout, retries, 0);
+
+	DEB(st->write_pending = 0;)
+
+	if (st->buffer->cmdstat.midlevel_result != (DRIVER_ERROR << 24)) {
+		st->buffer->syscall_result = st_chk_result(st, cmd, sense,
+				st->buffer->cmdstat.midlevel_result);
+	} else
+		st->buffer->syscall_result = -EBUSY;
+
+	kfree(sense);
+	return 1;
+}
 
 /* Handle the write-behind checking (waits for completion). Returns -ENOSPC if
    write has been correct but EOM early warning reached, -EIO if write ended in
@@ -552,7 +585,9 @@
 	STbuffer->last_SRpnt = NULL;
 	SRpnt->waiting = NULL;
 
-	(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
+	(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt->cmd,
+						      SRpnt->sense,
+						      SRpnt->result);
 	st_release_request(SRpnt);
 
 	STbuffer->buffer_bytes -= STbuffer->writing;
@@ -593,7 +628,6 @@
    it messes up the block number). */
 static int cross_eof(struct scsi_tape * STp, int forward)
 {
-	struct st_request *SRpnt;
 	unsigned char cmd[MAX_COMMAND_SIZE];
 
 	cmd[0] = SPACE;
@@ -608,13 +642,10 @@
         DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n",
 		   tape_name(STp), forward ? "forward" : "backward"));
 
-	SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
-			   STp->device->timeout, MAX_RETRIES, 1);
-	if (!SRpnt)
+	if (!st_scsi_execute(STp, cmd, DMA_NONE, NULL, 0,
+			   STp->device->timeout, MAX_RETRIES))
 		return (STp->buffer)->syscall_result;
 
-	st_release_request(SRpnt);
-	SRpnt = NULL;
 
 	if ((STp->buffer)->cmdstat.midlevel_result != 0)
 		printk(KERN_ERR "%s: Stepping over filemark %s failed.\n",
@@ -646,7 +677,8 @@
                 DEBC(printk(ST_DEB_MSG "%s: Flushing %d bytes.\n",
                                tape_name(STp), transfer));
 
-		memset((STp->buffer)->b_data + offset, 0, transfer - offset);
+		memset(page_address(STp->buffer->frp[0].page) + offset,
+				0, transfer - offset);
 
 		memset(cmd, 0, MAX_COMMAND_SIZE);
 		cmd[0] = WRITE_6;
@@ -844,7 +876,6 @@
 	int attentions, waits, max_wait, scode;
 	int retval = CHKRES_READY, new_session = 0;
 	unsigned char cmd[MAX_COMMAND_SIZE];
-	struct st_request *SRpnt = NULL;
 	struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
 
 	max_wait = do_wait ? ST_BLOCK_SECONDS : 0;
@@ -852,10 +883,8 @@
 	for (attentions=waits=0; ; ) {
 		memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
 		cmd[0] = TEST_UNIT_READY;
-		SRpnt = st_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
-				   STp->long_timeout, MAX_READY_RETRIES, 1);
-
-		if (!SRpnt) {
+		if (!st_scsi_execute(STp, cmd, DMA_NONE, NULL, 0,
+				   STp->long_timeout, MAX_READY_RETRIES)) {
 			retval = (STp->buffer)->syscall_result;
 			break;
 		}
@@ -902,11 +931,100 @@
 		break;
 	}
 
-	if (SRpnt != NULL)
-		st_release_request(SRpnt);
 	return retval;
 }
 
+static int
+st_get_block_limits(struct scsi_tape *st)
+{
+	u8 cmd[MAX_COMMAND_SIZE];
+	u8 *buf;
+
+	memset(cmd, 0, MAX_COMMAND_SIZE);
+	cmd[0] = READ_BLOCK_LIMITS;
+
+	buf = kmalloc(6, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (!st_scsi_execute(st, cmd, DMA_FROM_DEVICE, buf, 6,
+				st->device->timeout, MAX_READY_RETRIES))
+		goto fail;
+
+	if (!st->buffer->cmdstat.midlevel_result &&
+	    !st->buffer->cmdstat.have_sense) {
+		st->max_block = (buf[1] << 16) | (buf[2] << 8) | buf[3];
+		st->min_block = (buf[4] << 8) | buf[5];
+		if (DEB(debugging ||) !st->inited) {
+			printk(KERN_WARNING "%s: Block limits %d - %d bytes.\n",
+			       tape_name(st), st->min_block, st->max_block);
+		}
+	} else {
+		st->min_block = st->max_block = -1;
+		DEBC(printk(ST_DEB_MSG "%s: Can't read block limits.\n",
+			    tape_name(st)));
+	}
+
+	kfree(buf);
+	return 0;
+ fail:
+	kfree(buf);
+	return st->buffer->syscall_result;
+}
+
+static int
+st_get_mode_sense(struct scsi_tape *st)
+{
+	u8 cmd[MAX_COMMAND_SIZE];
+	u8 *buf;
+
+	memset(cmd, 0, MAX_COMMAND_SIZE);
+	cmd[0] = MODE_SENSE;
+	cmd[4] = 12;
+
+	buf = kmalloc(12, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (!st_scsi_execute(st, cmd, DMA_FROM_DEVICE, buf, 12,
+				st->device->timeout, MAX_READY_RETRIES))
+		goto fail;
+
+	if (st->buffer->syscall_result) {
+		DEBC(printk(ST_DEB_MSG "%s: No Mode Sense.\n", tape_name(st)));
+		st->block_size = ST_DEFAULT_BLOCK;	/* Educated guess (?) */
+		st->buffer->syscall_result = 0;	 /* Prevent error propagation */
+		st->drv_write_prot = 0;
+		goto out;
+	}
+
+	DEBC(printk(ST_DEB_MSG
+		    "%s: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n",
+		    tape_name(st), buf[0], buf[1], buf[2], buf[3]));
+
+	if (buf[3] >= 8) {
+		st->drv_buffer = (buf[2] >> 4) & 7;
+		st->density = buf[4];
+		st->block_size = buf[9] * 65536 +
+				 buf[10] * 256 +
+				 buf[11];
+
+		DEBC(printk(ST_DEB_MSG
+			    "%s: Density %x, tape length: %x, drv buffer: %d\n",
+			    tape_name(st), STp->density, buf[5] * 65536 +
+			    buf[6] * 256 + buf[7], st->drv_buffer));
+	}
+
+	st->drv_write_prot = (buf[2] & 0x80) != 0;
+
+ out:
+	kfree(buf);
+	return 0;
+
+ fail:
+	kfree(buf);
+	return st->buffer->syscall_result;
+}
 
 /* See if the drive is ready and gather information about the tape. Return values:
    < 0   negative error code from errno.h
@@ -916,9 +1034,8 @@
 static int check_tape(struct scsi_tape *STp, struct file *filp)
 {
 	int i, retval, new_session = 0, do_wait;
-	unsigned char cmd[MAX_COMMAND_SIZE], saved_cleaning;
+	unsigned char saved_cleaning;
 	unsigned short st_flags = filp->f_flags;
-	struct st_request *SRpnt = NULL;
 	struct st_modedef *STm;
 	struct st_partstat *STps;
 	char *name = tape_name(STp);
@@ -980,73 +1097,17 @@
 		}
 	}
 
-	if (STp->omit_blklims)
-		STp->min_block = STp->max_block = (-1);
-	else {
-		memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
-		cmd[0] = READ_BLOCK_LIMITS;
-
-		SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, DMA_FROM_DEVICE,
-				   STp->device->timeout, MAX_READY_RETRIES, 1);
-		if (!SRpnt) {
-			retval = (STp->buffer)->syscall_result;
+	if (!STp->omit_blklims) {
+		retval = st_get_block_limits(STp);
+		if (retval)
 			goto err_out;
-		}
-
-		if (!SRpnt->result && !STp->buffer->cmdstat.have_sense) {
-			STp->max_block = ((STp->buffer)->b_data[1] << 16) |
-			    ((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];
-			STp->min_block = ((STp->buffer)->b_data[4] << 8) |
-			    (STp->buffer)->b_data[5];
-			if ( DEB( debugging || ) !STp->inited)
-				printk(KERN_WARNING
-                                       "%s: Block limits %d - %d bytes.\n", name,
-                                       STp->min_block, STp->max_block);
-		} else {
-			STp->min_block = STp->max_block = (-1);
-                        DEBC(printk(ST_DEB_MSG "%s: Can't read block limits.\n",
-                                       name));
-		}
-	}
-
-	memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
-	cmd[0] = MODE_SENSE;
-	cmd[4] = 12;
+	} else
+		STp->min_block = STp->max_block = -1;
 
-	SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, DMA_FROM_DEVICE,
-			STp->device->timeout, MAX_READY_RETRIES, 1);
-	if (!SRpnt) {
-		retval = (STp->buffer)->syscall_result;
+	retval = st_get_mode_sense(STp);
+	if (retval)
 		goto err_out;
-	}
 
-	if ((STp->buffer)->syscall_result != 0) {
-                DEBC(printk(ST_DEB_MSG "%s: No Mode Sense.\n", name));
-		STp->block_size = ST_DEFAULT_BLOCK;	/* Educated guess (?) */
-		(STp->buffer)->syscall_result = 0;	/* Prevent error propagation */
-		STp->drv_write_prot = 0;
-	} else {
-                DEBC(printk(ST_DEB_MSG
-                            "%s: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n",
-                            name,
-                            (STp->buffer)->b_data[0], (STp->buffer)->b_data[1],
-                            (STp->buffer)->b_data[2], (STp->buffer)->b_data[3]));
-
-		if ((STp->buffer)->b_data[3] >= 8) {
-			STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7;
-			STp->density = (STp->buffer)->b_data[4];
-			STp->block_size = (STp->buffer)->b_data[9] * 65536 +
-			    (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11];
-                        DEBC(printk(ST_DEB_MSG
-                                    "%s: Density %x, tape length: %x, drv buffer: %d\n",
-                                    name, STp->density, (STp->buffer)->b_data[5] * 65536 +
-                                    (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],
-                                    STp->drv_buffer));
-		}
-		STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;
-	}
-	st_release_request(SRpnt);
-	SRpnt = NULL;
         STp->inited = 1;
 
 	if (STp->block_size > 0)
@@ -1196,7 +1257,6 @@
 {
 	int result = 0, result2;
 	unsigned char cmd[MAX_COMMAND_SIZE];
-	struct st_request *SRpnt;
 	struct scsi_tape *STp = filp->private_data;
 	struct st_modedef *STm = &(STp->modes[STp->current_mode]);
 	struct st_partstat *STps = &(STp->ps[STp->partition]);
@@ -1235,9 +1295,8 @@
 		cmd[0] = WRITE_FILEMARKS;
 		cmd[4] = 1 + STp->two_fm;
 
-		SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
-				   STp->device->timeout, MAX_WRITE_RETRIES, 1);
-		if (!SRpnt) {
+		if (!st_scsi_execute(STp, cmd, DMA_NONE, NULL, 0,
+				   STp->device->timeout, MAX_WRITE_RETRIES)) {
 			result = (STp->buffer)->syscall_result;
 			goto out;
 		}
@@ -1249,8 +1308,6 @@
 		      cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
 		     (!cmdstatp->remainder_valid || cmdstatp->uremainder64 == 0))) {
 			/* Write successful at EOM */
-			st_release_request(SRpnt);
-			SRpnt = NULL;
 			if (STps->drv_file >= 0)
 				STps->drv_file++;
 			STps->drv_block = 0;
@@ -1259,8 +1316,6 @@
 			STps->eof = ST_FM;
 		}
 		else { /* Write error */
-			st_release_request(SRpnt);
-			SRpnt = NULL;
 			printk(KERN_ERR "%s: Error on write filemark.\n", name);
 			if (result == 0)
 				result = (-EIO);
@@ -2282,10 +2337,10 @@
 /* Read a mode page into the tape buffer. The block descriptors are included
    if incl_block_descs is true. The page control is ored to the page number
    parameter, if necessary. */
-static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
+static int read_mode_page(struct scsi_tape *STp, u8 *buf, int page,
+		int omit_block_descs)
 {
 	unsigned char cmd[MAX_COMMAND_SIZE];
-	struct st_request *SRpnt = NULL;
 
 	memset(cmd, 0, MAX_COMMAND_SIZE);
 	cmd[0] = MODE_SENSE;
@@ -2294,44 +2349,33 @@
 	cmd[2] = page;
 	cmd[4] = 255;
 
-	SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE,
-			   STp->device->timeout, 0, 1);
-	if (SRpnt == NULL)
-		return (STp->buffer)->syscall_result;
-
-	st_release_request(SRpnt);
-
+	st_scsi_execute(STp, cmd, DMA_FROM_DEVICE, buf, cmd[4],
+				STp->device->timeout, 0);
 	return (STp->buffer)->syscall_result;
 }
 
 
 /* Send the mode page in the tape buffer to the drive. Assumes that the mode data
    in the buffer is correctly formatted. The long timeout is used if slow is non-zero. */
-static int write_mode_page(struct scsi_tape *STp, int page, int slow)
+static int write_mode_page(struct scsi_tape *STp, u8 *buf, int page, int slow)
 {
 	int pgo;
 	unsigned char cmd[MAX_COMMAND_SIZE];
-	struct st_request *SRpnt = NULL;
+	int timeout = (slow ? STp->long_timeout : STp->device->timeout);
 
 	memset(cmd, 0, MAX_COMMAND_SIZE);
 	cmd[0] = MODE_SELECT;
 	cmd[1] = MODE_SELECT_PAGE_FORMAT;
-	pgo = MODE_HEADER_LENGTH + (STp->buffer)->b_data[MH_OFF_BDESCS_LENGTH];
-	cmd[4] = pgo + (STp->buffer)->b_data[pgo + MP_OFF_PAGE_LENGTH] + 2;
+	pgo = MODE_HEADER_LENGTH + buf[MH_OFF_BDESCS_LENGTH];
+	cmd[4] = pgo + buf[pgo + MP_OFF_PAGE_LENGTH] + 2;
 
 	/* Clear reserved fields */
-	(STp->buffer)->b_data[MH_OFF_DATA_LENGTH] = 0;
-	(STp->buffer)->b_data[MH_OFF_MEDIUM_TYPE] = 0;
-	(STp->buffer)->b_data[MH_OFF_DEV_SPECIFIC] &= ~MH_BIT_WP;
-	(STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR;
-
-	SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE,
-			   (slow ? STp->long_timeout : STp->device->timeout), 0, 1);
-	if (SRpnt == NULL)
-		return (STp->buffer)->syscall_result;
-
-	st_release_request(SRpnt);
+	buf[MH_OFF_DATA_LENGTH] = 0;
+	buf[MH_OFF_MEDIUM_TYPE] = 0;
+	buf[MH_OFF_DEV_SPECIFIC] &= ~MH_BIT_WP;
+	buf[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR;
 
+	st_scsi_execute(STp, cmd, DMA_TO_DEVICE, buf, cmd[4], timeout, 0);
 	return (STp->buffer)->syscall_result;
 }
 
@@ -2357,14 +2401,19 @@
 {
 	int retval;
 	int mpoffs;  /* Offset to mode page start */
-	unsigned char *b_data = (STp->buffer)->b_data;
+	unsigned char *b_data;
+	int rval = EIO;
 	DEB( char *name = tape_name(STp); )
 
 	if (STp->ready != ST_READY)
 		return (-EIO);
 
+	b_data = (u8 *)get_zeroed_page(GFP_KERNEL);
+	if (!b_data)
+		return -ENOMEM;
+
 	/* Read the current page contents */
-	retval = read_mode_page(STp, COMPRESSION_PAGE, 0);
+	retval = read_mode_page(STp, b_data, COMPRESSION_PAGE, 0);
 	if (retval) {
                 DEBC(printk(ST_DEB_MSG "%s: Compression mode page not supported.\n",
                             name));
@@ -2378,7 +2427,7 @@
 	/* Check if compression can be changed */
 	if ((b_data[mpoffs + CP_OFF_DCE_DCC] & DCC_MASK) == 0) {
                 DEBC(printk(ST_DEB_MSG "%s: Compression not supported.\n", name));
-		return (-EIO);
+		goto out;
 	}
 
 	/* Do the change */
@@ -2393,16 +2442,20 @@
 			b_data[mpoffs + CP_OFF_C_ALGO] = 0; /* no compression */
 	}
 
-	retval = write_mode_page(STp, COMPRESSION_PAGE, 0);
+	retval = write_mode_page(STp, b_data, COMPRESSION_PAGE, 0);
 	if (retval) {
                 DEBC(printk(ST_DEB_MSG "%s: Compression change failed.\n", name));
-		return (-EIO);
+		goto out;
 	}
         DEBC(printk(ST_DEB_MSG "%s: Compression state changed to %d.\n",
 		       name, state));
 
 	STp->compression_changed = 1;
-	return 0;
+
+	rval = 0;
+ out:
+	free_page((unsigned long)b_data);
+	return rval;
 }
 
 
@@ -2413,7 +2466,6 @@
 	DEB( char *name = tape_name(STp); )
 	unsigned char cmd[MAX_COMMAND_SIZE];
 	struct st_partstat *STps;
-	struct st_request *SRpnt;
 
 	if (STp->ready != ST_READY && !load_code) {
 		if (STp->ready == ST_NO_TAPE)
@@ -2450,13 +2502,10 @@
 		printk(ST_DEB_MSG "%s: Loading tape.\n", name);
 		);
 
-	SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
-			   timeout, MAX_RETRIES, 1);
-	if (!SRpnt)
+	if (!st_scsi_execute(STp, cmd, DMA_NONE, NULL, 0, timeout, MAX_RETRIES))
 		return (STp->buffer)->syscall_result;
 
 	retval = (STp->buffer)->syscall_result;
-	st_release_request(SRpnt);
 
 	if (!retval) {	/* SCSI command successful */
 
@@ -2504,11 +2553,11 @@
 	int ioctl_result;
 	int chg_eof = 1;
 	unsigned char cmd[MAX_COMMAND_SIZE];
-	struct st_request *SRpnt;
 	struct st_partstat *STps;
 	int fileno, blkno, at_sm, undone;
 	int datalen = 0, direction = DMA_NONE;
 	char *name = tape_name(STp);
+	u8 *buf = NULL;
 
 	WARN_ON(STp->buffer->do_dio != 0);
 	if (STp->ready != ST_READY) {
@@ -2705,61 +2754,64 @@
 		cmd[4] = datalen = 12;
 		direction = DMA_TO_DEVICE;
 
-		memset((STp->buffer)->b_data, 0, 12);
+		buf = kzalloc(datalen, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+
 		if (cmd_in == MTSETDRVBUFFER)
-			(STp->buffer)->b_data[2] = (arg & 7) << 4;
+			buf[2] = (arg & 7) << 4;
 		else
-			(STp->buffer)->b_data[2] =
-			    STp->drv_buffer << 4;
-		(STp->buffer)->b_data[3] = 8;	/* block descriptor length */
+			buf[2] = STp->drv_buffer << 4;
+		buf[3] = 8;	/* block descriptor length */
 		if (cmd_in == MTSETDENSITY) {
-			(STp->buffer)->b_data[4] = arg;
+			buf[4] = arg;
 			STp->density_changed = 1;	/* At least we tried ;-) */
-		} else if (cmd_in == SET_DENS_AND_BLK)
-			(STp->buffer)->b_data[4] = arg >> 24;
-		else
-			(STp->buffer)->b_data[4] = STp->density;
+		} else if (cmd_in == SET_DENS_AND_BLK) {
+			buf[4] = arg >> 24;
+		} else {
+			buf[4] = STp->density;
+		}
 		if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
 			ltmp = arg & MT_ST_BLKSIZE_MASK;
 			if (cmd_in == MTSETBLK)
 				STp->blksize_changed = 1; /* At least we tried ;-) */
 		} else
 			ltmp = STp->block_size;
-		(STp->buffer)->b_data[9] = (ltmp >> 16);
-		(STp->buffer)->b_data[10] = (ltmp >> 8);
-		(STp->buffer)->b_data[11] = ltmp;
+		buf[9] = (ltmp >> 16);
+		buf[10] = (ltmp >> 8);
+		buf[11] = ltmp;
 		timeout = STp->device->timeout;
                 DEBC(
 			if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK)
 				printk(ST_DEB_MSG
                                        "%s: Setting block size to %d bytes.\n", name,
-				       (STp->buffer)->b_data[9] * 65536 +
-				       (STp->buffer)->b_data[10] * 256 +
-				       (STp->buffer)->b_data[11]);
+				       buf[9] * 65536 +
+				       buf[10] * 256 +
+				       buf[11]);
 			if (cmd_in == MTSETDENSITY || cmd_in == SET_DENS_AND_BLK)
 				printk(ST_DEB_MSG
                                        "%s: Setting density code to %x.\n", name,
-				       (STp->buffer)->b_data[4]);
+				       buf[4]);
 			if (cmd_in == MTSETDRVBUFFER)
 				printk(ST_DEB_MSG
                                        "%s: Setting drive buffer code to %d.\n", name,
-				    ((STp->buffer)->b_data[2] >> 4) & 7);
+				    (buf[2] >> 4) & 7);
 		)
 		break;
 	default:
 		return (-ENOSYS);
 	}
 
-	SRpnt = st_do_scsi(NULL, STp, cmd, datalen, direction,
-			   timeout, MAX_RETRIES, 1);
-	if (!SRpnt)
+	if (!st_scsi_execute(STp, cmd, direction, buf, datalen,
+				timeout, MAX_RETRIES)) {
+		kfree(buf);
 		return (STp->buffer)->syscall_result;
+	}
 
-	ioctl_result = (STp->buffer)->syscall_result;
+	kfree(buf);
 
+	ioctl_result = (STp->buffer)->syscall_result;
 	if (!ioctl_result) {	/* SCSI command successful */
-		st_release_request(SRpnt);
-		SRpnt = NULL;
 		STps->drv_block = blkno;
 		STps->drv_file = fileno;
 		STps->at_sm = at_sm;
@@ -2873,8 +2925,6 @@
 				/* Try the other possible state of Page Format if not
 				   already tried */
 				STp->use_pf = !STp->use_pf | PF_TESTED;
-				st_release_request(SRpnt);
-				SRpnt = NULL;
 				return st_int_ioctl(STp, cmd_in, arg);
 			}
 		} else if (chg_eof)
@@ -2882,9 +2932,6 @@
 
 		if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
 			STps->eof = ST_EOD;
-
-		st_release_request(SRpnt);
-		SRpnt = NULL;
 	}
 
 	return ioctl_result;
@@ -2897,9 +2944,8 @@
 static int get_location(struct scsi_tape *STp, unsigned int *block, int *partition,
 			int logical)
 {
-	int result;
 	unsigned char scmd[MAX_COMMAND_SIZE];
-	struct st_request *SRpnt;
+	u8 *buf;
 	DEB( char *name = tape_name(STp); )
 
 	if (STp->ready != ST_READY)
@@ -2914,41 +2960,45 @@
 		if (!logical && !STp->scsi2_logical)
 			scmd[1] = 1;
 	}
-	SRpnt = st_do_scsi(NULL, STp, scmd, 20, DMA_FROM_DEVICE,
-			STp->device->timeout, MAX_READY_RETRIES, 1);
-	if (!SRpnt)
-		return (STp->buffer)->syscall_result;
 
-	if ((STp->buffer)->syscall_result != 0 ||
-	    (STp->device->scsi_level >= SCSI_2 &&
-	     ((STp->buffer)->b_data[0] & 4) != 0)) {
+	buf = kmalloc(20, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (!st_scsi_execute(STp, scmd, DMA_FROM_DEVICE, buf, 20,
+				STp->device->timeout, MAX_READY_RETRIES)) {
+		kfree(buf);
+		return STp->buffer->syscall_result;
+	}
+
+	if (STp->buffer->syscall_result != 0 ||
+	    (STp->device->scsi_level >= SCSI_2 && (buf[0] & 4) != 0)) {
 		*block = *partition = 0;
-                DEBC(printk(ST_DEB_MSG "%s: Can't read tape position.\n", name));
-		result = (-EIO);
+                DEBC(printk(ST_DEB_MSG "%s: Can't read tape position.\n",
+			    name));
+		kfree(buf);
+		return -EIO;
+	}
+
+	if (STp->device->scsi_level < SCSI_2) {
+		*block = (buf[0] << 16) +
+			 (buf[1] << 8) +
+			  buf[2];
+		*partition = 0;
 	} else {
-		result = 0;
-		if ((STp->device)->scsi_level < SCSI_2) {
-			*block = ((STp->buffer)->b_data[0] << 16)
-			    + ((STp->buffer)->b_data[1] << 8)
-			    + (STp->buffer)->b_data[2];
-			*partition = 0;
-		} else {
-			*block = ((STp->buffer)->b_data[4] << 24)
-			    + ((STp->buffer)->b_data[5] << 16)
-			    + ((STp->buffer)->b_data[6] << 8)
-			    + (STp->buffer)->b_data[7];
-			*partition = (STp->buffer)->b_data[1];
-			if (((STp->buffer)->b_data[0] & 0x80) &&
-			    (STp->buffer)->b_data[1] == 0)	/* BOP of partition 0 */
-				STp->ps[0].drv_block = STp->ps[0].drv_file = 0;
-		}
-                DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name,
-                            *block, *partition));
+		*block = (buf[4] << 24) +
+			 (buf[5] << 16) +
+			 (buf[6] << 8) +
+			  buf[7];
+		*partition = buf[1];
+		if ((buf[0] & 0x80) && buf[1] == 0)	/* BOP of partition 0 */
+			STp->ps[0].drv_block = STp->ps[0].drv_file = 0;
 	}
-	st_release_request(SRpnt);
-	SRpnt = NULL;
 
-	return result;
+	DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n",
+		    name, *block, *partition));
+	kfree(buf);
+	return 0;
 }
 
 
@@ -2962,7 +3012,6 @@
 	unsigned int blk;
 	int timeout;
 	unsigned char scmd[MAX_COMMAND_SIZE];
-	struct st_request *SRpnt;
 	DEB( char *name = tape_name(STp); )
 
 	if (STp->ready != ST_READY)
@@ -3019,9 +3068,8 @@
 		timeout = STp->device->timeout;
 	}
 
-	SRpnt = st_do_scsi(NULL, STp, scmd, 0, DMA_NONE,
-			   timeout, MAX_READY_RETRIES, 1);
-	if (!SRpnt)
+	if (!st_scsi_execute(STp, scmd, DMA_NONE, NULL, 0,
+			   timeout, MAX_READY_RETRIES))
 		return (STp->buffer)->syscall_result;
 
 	STps->drv_block = STps->drv_file = (-1);
@@ -3048,9 +3096,6 @@
 		result = 0;
 	}
 
-	st_release_request(SRpnt);
-	SRpnt = NULL;
-
 	return result;
 }
 
@@ -3102,23 +3147,28 @@
 static int nbr_partitions(struct scsi_tape *STp)
 {
 	int result;
+	u8 *buf;
 	DEB( char *name = tape_name(STp); )
 
 	if (STp->ready != ST_READY)
 		return (-EIO);
 
-	result = read_mode_page(STp, PART_PAGE, 1);
+	buf = (u8 *)get_zeroed_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	result = read_mode_page(STp, buf, PART_PAGE, 1);
 
 	if (result) {
                 DEBC(printk(ST_DEB_MSG "%s: Can't read medium partition page.\n",
                             name));
 		result = (-EIO);
 	} else {
-		result = (STp->buffer)->b_data[MODE_HEADER_LENGTH +
-					      PP_OFF_NBR_ADD_PARTS] + 1;
+		result = buf[MODE_HEADER_LENGTH + PP_OFF_NBR_ADD_PARTS] + 1;
                 DEBC(printk(ST_DEB_MSG "%s: Number of partitions %d.\n", name, result));
 	}
 
+	free_page((unsigned long)buf);
 	return result;
 }
 
@@ -3149,13 +3199,17 @@
 	int pgo, psd_cnt, psdo;
 	unsigned char *bp;
 
-	result = read_mode_page(STp, PART_PAGE, 0);
+	bp = (u8 *)get_zeroed_page(GFP_KERNEL);
+	if (!bp)
+		return -ENOMEM;
+
+	result = read_mode_page(STp, bp, PART_PAGE, 0);
 	if (result) {
 		DEBC(printk(ST_DEB_MSG "%s: Can't read partition mode page.\n", name));
-		return result;
+		goto out;
 	}
 	/* The mode page is in the buffer. Let's modify it and write it. */
-	bp = (STp->buffer)->b_data;
+
 	pgo = MODE_HEADER_LENGTH + bp[MH_OFF_BDESCS_LENGTH];
 	DEBC(printk(ST_DEB_MSG "%s: Partition page length is %d bytes.\n",
 		    name, bp[pgo + MP_OFF_PAGE_LENGTH] + 2));
@@ -3192,12 +3246,14 @@
 	bp[pgo + PP_OFF_RESERVED] = 0;
 	bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | PP_MSK_PSUM_MB;
 
-	result = write_mode_page(STp, PART_PAGE, 1);
+	result = write_mode_page(STp, bp, PART_PAGE, 1);
 	if (result) {
 		printk(KERN_INFO "%s: Partitioning of tape failed.\n", name);
 		result = (-EIO);
 	}
 
+ out:
+	free_page((unsigned long)bp);
 	return result;
 }
 
@@ -3643,7 +3699,6 @@
 		STbuffer->buffer_size = got;
 		segs++;
 	}
-	STbuffer->b_data = page_address(STbuffer->frp[0].page);
 
 	return 1;
 }
Index: scsi-misc-2.6/drivers/scsi/st.h
===================================================================
--- scsi-misc-2.6.orig/drivers/scsi/st.h	2006-01-30 19:14:29.000000000 +0100
+++ scsi-misc-2.6/drivers/scsi/st.h	2006-01-30 19:14:39.000000000 +0100
@@ -42,7 +42,6 @@
 	int syscall_result;
 	struct st_request *last_SRpnt;
 	struct st_cmdstatus cmdstat;
-	unsigned char *b_data;
 	unsigned short use_sg;	/* zero or max number of s/g segments for this adapter */
 	unsigned short sg_segs;		/* number of segments in s/g list */
 	unsigned short orig_frp_segs;	/* number of segments allocated at first try */
-
: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux