All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ide-scsi changes for new mid level api and error handling in 2.5.52
@ 2002-12-21 22:46 Willem Riede
  2002-12-22  1:59 ` Douglas Gilbert
  0 siblings, 1 reply; 5+ messages in thread
From: Willem Riede @ 2002-12-21 22:46 UTC (permalink / raw
  To: linux-scsi

[-- Attachment #1: Type: text/plain, Size: 652 bytes --]

Here is my proposal for bringing ide-scsi in line with the current kernel.

The attached patch does:

1. Change from old style initialization to the new hotplug initialization model.
   It involves declaring both a parent device and bus kernel object, which feels
   a bit awkward, but hey, it works.

2. Make ide-scsi request sense itself when CHECK_CONDITION is asserted. This 
   change particularly makes ide-scsi run much smoother on my test box.

3. Implement eh_abort_handler and eh_device_reset_handler. I have no real way
   to thoroughly test these new routines, so for this part particularly I ask
   for peer review.

Thanks, Willem Riede.

[-- Attachment #2: ide-scsi.patch --]
[-- Type: text/plain, Size: 9598 bytes --]

--- drivers/scsi/ide-scsi.c	Mon Dec  9 21:46:12 2002
+++ /home/wriede/develop/ide-scsi.c	Sat Dec 21 17:32:48 2002
@@ -28,9 +28,10 @@
  * Ver 0.8   Feb 05 99   Optical media need translation too. Reverse 0.7.
  * Ver 0.9   Jul 04 99   Fix a bug in SG_SET_TRANSFORM.
  * Ver 0.91  Jun 10 02   Fix "off by one" error in transforms
+ * Ver 0.92  Dec 31 02   Implement new SCSI mid level API
  */
 
-#define IDESCSI_VERSION "0.9"
+#define IDESCSI_VERSION "0.92"
 
 #include <linux/module.h>
 #include <linux/config.h>
@@ -259,6 +260,42 @@
 	printk("]\n");
 }
 
+static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_command)
+{
+	idescsi_scsi_t *scsi = drive->driver_data;
+	idescsi_pc_t   *pc;
+	struct request *rq;
+	u8             *buf;
+
+	/* stuff a sense request in front of our current request */
+	pc = kmalloc (sizeof (idescsi_pc_t), GFP_ATOMIC);
+	rq = kmalloc (sizeof (struct request), GFP_ATOMIC);
+	buf = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC);
+	if (pc == NULL || rq == NULL || buf == NULL) {
+		if (pc) kfree(pc);
+		if (rq) kfree(rq);
+		if (buf) kfree(buf);
+		return -ENOMEM;
+	}
+	memset (pc, 0, sizeof (idescsi_pc_t));
+	memset (buf, 0, SCSI_SENSE_BUFFERSIZE);
+	ide_init_drive_cmd(rq);
+	rq->special = (char *) pc;
+	pc->rq = rq;
+	pc->buffer = buf;
+	pc->c[0] = REQUEST_SENSE;
+	pc->c[4] = pc->request_transfer = pc->buffer_size = SCSI_SENSE_BUFFERSIZE;
+	rq->flags = REQ_SENSE;
+	pc->timeout = jiffies + WAIT_READY;
+	/* NOTE! Save the failed packet command in "rq->buffer" */
+	rq->buffer = (void *) failed_command->special;
+	if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
+		printk ("ide-scsi: %s: queue cmd = ", drive->name);
+		hexdump(pc->c, 6);
+	}
+	return ide_do_drive_cmd(drive, rq, ide_preempt);
+}
+
 static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
 {
 	idescsi_scsi_t *scsi = drive->driver_data;
@@ -269,19 +306,35 @@
 	u8 *scsi_buf;
 	unsigned long flags;
 
-	if (!(rq->flags & REQ_SPECIAL)) {
+	if (!(rq->flags & (REQ_SPECIAL|REQ_SENSE))) {
 		ide_end_request(drive, uptodate, nrsecs);
 		return 0;
 	}
 	ide_end_drive_cmd (drive, 0, 0);
-	if (rq->errors >= ERROR_MAX) {
+	if (rq->flags & REQ_SENSE) {
+		idescsi_pc_t *opc = (idescsi_pc_t *) rq->buffer;
+		if (log) {
+			printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number);
+			hexdump(pc->buffer,16);
+		}
+		memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buffer, SCSI_SENSE_BUFFERSIZE);
+		kfree(pc->buffer);
+		kfree(pc);
+		kfree(rq);
+		pc = opc;
+		rq = pc->rq;
+		pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
+	} else if (rq->errors >= ERROR_MAX) {
 		pc->scsi_cmd->result = DID_ERROR << 16;
 		if (log)
 			printk ("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->scsi_cmd->serial_number);
 	} else if (rq->errors) {
-		pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
 		if (log)
 			printk ("ide-scsi: %s: check condition for %lu\n", drive->name, pc->scsi_cmd->serial_number);
+		if (!idescsi_check_condition(drive, rq))
+			/* we started a request sense, so we'll be back, exit for now */
+			return 0;
+		pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
 	} else {
 		pc->scsi_cmd->result = DID_OK << 16;
 		idescsi_transform_pc2 (drive, pc);
@@ -489,11 +542,11 @@
 static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *rq, sector_t block)
 {
 #if IDESCSI_DEBUG_LOG
-	printk (KERN_INFO "rq_status: %d, dev: %s, cmd: %d, errors: %d\n",rq->rq_status, rq->rq_disk->disk_name,rq->cmd,rq->errors);
-	printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
+	printk (KERN_INFO "rq_status: %d, dev: %s, cmd: %x, errors: %d\n",rq->rq_status, rq->rq_disk->disk_name,rq->cmd[0],rq->errors);
+	printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
 #endif /* IDESCSI_DEBUG_LOG */
 
-	if (rq->flags & REQ_SPECIAL) {
+	if (rq->flags & (REQ_SPECIAL|REQ_SENSE)) {
 		return idescsi_issue_pc (drive, (idescsi_pc_t *) rq->special);
 	}
 	blk_dump_rq_flags(rq, "ide-scsi: unsup command");
@@ -629,35 +682,10 @@
 	return 1;
 }
 
-int idescsi_detect (Scsi_Host_Template *host_template)
+int idescsi_slave_configure(Scsi_Device * sdp)
 {
-	struct Scsi_Host *host;
-	int id;
-	int last_lun = 0;
-
-	host_template->proc_name = "ide-scsi";
-	host = scsi_register(host_template, 0);
-	if(host == NULL)
-		return 0;
-		
-	for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++)
-		last_lun = IDE_MAX(last_lun, idescsi_drives[id]->last_lun);
-	host->max_id = id;
-	host->max_lun = last_lun + 1;
-	host->can_queue = host->cmd_per_lun * id;
-	return 1;
-}
-
-int idescsi_release (struct Scsi_Host *host)
-{
-	ide_drive_t *drive;
-	int id;
-
-	for (id = 0; id < MAX_HWIFS * MAX_DRIVES; id++) {
-		drive = idescsi_drives[id];
-		if (drive)
-			DRIVER(drive)->busy--;
-	}
+	/* Configure detected device */
+	scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, sdp->host->cmd_per_lun);
 	return 0;
 }
 
@@ -832,17 +860,67 @@
 	if (rq) kfree (rq);
 	cmd->result = DID_ERROR << 16;
 	done(cmd);
-	return 0;
+	return 1;
 }
 
 int idescsi_abort (Scsi_Cmnd *cmd)
 {
-	return SCSI_ABORT_SNOOZE;
+	int countdown = 8;
+	unsigned long flags;
+	ide_drive_t *drive = idescsi_drives[cmd->target];
+	idescsi_scsi_t *scsi;
+
+	printk (KERN_ERR "ide-scsi: abort called for %lu\n", cmd->serial_number);
+	if (drive && (scsi = drive->driver_data))
+		while (countdown--) {
+			/* is cmd active?
+			 *  need to lock so this stuff doesn't change under us */
+			spin_lock_irqsave(&ide_lock, flags);
+			if (scsi->pc && scsi->pc->scsi_cmd->serial_number == cmd->serial_number) {
+				/* yep - let's give it some more time - 
+				 * we can do that, we're in _our_ error kernel thread */
+				spin_unlock_irqrestore(&ide_lock, flags);
+				scsi_sleep(HZ);
+				continue;
+			}
+			/* no, but is it queued in the ide subsystem? */
+			if (elv_queue_empty(&drive->queue)) {
+				spin_unlock_irqrestore(&ide_lock, flags);
+				return SUCCESS;
+			}
+			spin_unlock_irqrestore(&ide_lock, flags);
+			schedule_timeout(HZ/10);
+		}
+	return FAILED;
 }
 
-int idescsi_reset (Scsi_Cmnd *cmd, unsigned int resetflags)
+int idescsi_reset (Scsi_Cmnd *cmd)
 {
-	return SCSI_RESET_SUCCESS;
+	unsigned long flags;
+	struct request *req;
+	ide_drive_t *drive = idescsi_drives[cmd->target];
+
+	printk (KERN_ERR "ide-scsi: reset called for %lu\n", cmd->serial_number);
+	/* first null the handler for the drive and let any process
+	 * doing IO (on another CPU) run to (partial) completion
+	 * the lock prevents processing new requests */
+	spin_lock_irqsave(&ide_lock, flags);
+	while (HWGROUP(drive)->handler) {
+		HWGROUP(drive)->handler = NULL;
+		schedule_timeout(1);
+	}
+	/* now nuke the drive queue */
+	while ((req = elv_next_request(&drive->queue))) {
+		blkdev_dequeue_request(req);
+		end_that_request_last(req);
+	}
+	/* FIXME - this will probably leak memory */
+	HWGROUP(drive)->rq = NULL;
+	if (drive->driver_data) ((idescsi_scsi_t *)drive->driver_data)->pc = NULL;
+	spin_unlock_irqrestore(&ide_lock, flags);
+	/* finally, reset the drive (and its partner on the bus...) */
+	ide_do_reset (drive);	
+	return SUCCESS;
 }
 
 static int idescsi_bios(struct scsi_device *sdev, struct block_device *bdev,
@@ -859,32 +937,69 @@
 }
 
 static Scsi_Host_Template idescsi_template = {
-	.module		= THIS_MODULE,
-	.name		= "idescsi",
-	.detect		= idescsi_detect,
-	.release	= idescsi_release,
-	.info		= idescsi_info,
-	.ioctl		= idescsi_ioctl,
-	.queuecommand	= idescsi_queue,
-	.bios_param	= idescsi_bios,
-	.can_queue	= 10,
-	.this_id	= -1,
-	.sg_tablesize	= 256,
-	.cmd_per_lun	= 5,
-	.use_clustering	= DISABLE_CLUSTERING,
-	.emulated	= 1,
+	.module			= THIS_MODULE,
+	.name			= "idescsi",
+	.info			= idescsi_info,
+	.slave_configure        = idescsi_slave_configure,
+	.ioctl			= idescsi_ioctl,
+	.queuecommand		= idescsi_queue,
+	.eh_abort_handler	= idescsi_abort,
+	.eh_device_reset_handler = idescsi_reset,
+	.bios_param		= idescsi_bios,
+	.can_queue		= 40,
+	.this_id		= -1,
+	.sg_tablesize		= 256,
+	.cmd_per_lun		= 5,
+	.max_sectors		= 128,
+	.use_clustering		= DISABLE_CLUSTERING,
+	.emulated		= 1,
+};
+
+static struct Scsi_Host *idescsi_host;
+
+static struct device     idescsi_primary = {
+	.name		= "Ide-scsi Parent",
+	.bus_id		= "ide-scsi",
+};
+static struct bus_type   idescsi_emu_bus = {
+	.name		= "ide-scsi",
 };
 
 static int __init init_idescsi_module(void)
 {
+	int id;
+	int last_lun = 0;
+
 	ide_register_driver(&idescsi_driver);
-	scsi_register_host(&idescsi_template);
+	device_register(&idescsi_primary);
+	bus_register   (&idescsi_emu_bus);
+	idescsi_template.proc_name = "ide-scsi";
+	idescsi_host = scsi_register(&idescsi_template, 0);
+	if(idescsi_host == NULL)
+		return 1;
+		
+	for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++)
+		last_lun = IDE_MAX(last_lun, idescsi_drives[id]->last_lun);
+	idescsi_host->max_id = id;
+	idescsi_host->max_lun = last_lun + 1;
+	scsi_add_host(idescsi_host, &idescsi_primary);
 	return 0;
 }
 
 static void __exit exit_idescsi_module(void)
 {
-	scsi_unregister_host(&idescsi_template);
+	ide_drive_t *drive;
+	int id;
+
+	scsi_remove_host(idescsi_host);
+	for (id = 0; id < MAX_HWIFS * MAX_DRIVES; id++) {
+		drive = idescsi_drives[id];
+		if (drive)
+			DRIVER(drive)->busy--;
+	}
+	scsi_unregister   (idescsi_host);
+	device_unregister(&idescsi_primary);
+	bus_unregister   (&idescsi_emu_bus);
 	ide_unregister_driver(&idescsi_driver);
 }
 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] ide-scsi changes for new mid level api and error handling in 2.5.52
  2002-12-21 22:46 [PATCH] ide-scsi changes for new mid level api and error handling in 2.5.52 Willem Riede
@ 2002-12-22  1:59 ` Douglas Gilbert
  2002-12-22 17:14   ` Willem Riede
  0 siblings, 1 reply; 5+ messages in thread
From: Douglas Gilbert @ 2002-12-22  1:59 UTC (permalink / raw
  To: wrlk; +Cc: linux-scsi, andmike

Willem Riede wrote:
> Here is my proposal for bringing ide-scsi in line with the current kernel.
> 
> The attached patch does:
> 
> 1. Change from old style initialization to the new hotplug initialization model.
>    It involves declaring both a parent device and bus kernel object, which feels
>    a bit awkward, but hey, it works.
> 
> 2. Make ide-scsi request sense itself when CHECK_CONDITION is asserted. This 
>    change particularly makes ide-scsi run much smoother on my test box.
> 
> 3. Implement eh_abort_handler and eh_device_reset_handler. I have no real way
>    to thoroughly test these new routines, so for this part particularly I ask
>    for peer review.

Willem,
Good work.

I tried it out with an ATAPI cdrom and it worked fine.
Tried a few error conditions (e.g. purposely reading
past the end of the cdrom) and it reacted properly.

The introduction of a new sysfs bus type: "ide-scsi" to
add to scsi_debug's "pseudo" seems a bit messy. It will
do for now; hopefully Mike Anderson will come up with
some coherent sysfs naming scheme for drivers
that bridge to another protocol stack (e.g. ide-scsi,
usb-storage and ieee1394/sbp2).

BTW Willem's patch is against lk 2.5.52 .

Doug Gilbert


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] ide-scsi changes for new mid level api and error handling in 2.5.52
  2002-12-22  1:59 ` Douglas Gilbert
@ 2002-12-22 17:14   ` Willem Riede
  2002-12-23 19:05     ` Andre Hedrick
  0 siblings, 1 reply; 5+ messages in thread
From: Willem Riede @ 2002-12-22 17:14 UTC (permalink / raw
  To: linux-scsi

On 2002.12.21 20:59 Douglas Gilbert wrote:
> Willem Riede wrote:
> > Here is my proposal for bringing ide-scsi in line with the current kernel.
> > 
> > The attached patch does:
> > 
> 
> Willem,
> Good work.
> 
Thanks.
> 
> BTW Willem's patch is against lk 2.5.52 .
> 
Right. And next to this ide-scsi patch, you will also want
the one line fix to ide.c I posted earlier.

http://marc.theaimsgroup.com/?l=linux-scsi&m=104017636631422&w=2

Regards, Willem Riede.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] ide-scsi changes for new mid level api and error handling in 2.5.52
  2002-12-22 17:14   ` Willem Riede
@ 2002-12-23 19:05     ` Andre Hedrick
  2002-12-25 21:30       ` Alan Cox
  0 siblings, 1 reply; 5+ messages in thread
From: Andre Hedrick @ 2002-12-23 19:05 UTC (permalink / raw
  To: Willem Riede; +Cc: linux-scsi


There are a few changes I have to fix the ordering of the driver for clean
DMA ATAPI.  These are test on ia64 Itanium 2 from HP.

I will look at the changes again but I agree w/ Doug about the nice job.

Cheers,

On Sun, 22 Dec 2002, Willem Riede wrote:

> On 2002.12.21 20:59 Douglas Gilbert wrote:
> > Willem Riede wrote:
> > > Here is my proposal for bringing ide-scsi in line with the current kernel.
> > > 
> > > The attached patch does:
> > > 
> > 
> > Willem,
> > Good work.
> > 
> Thanks.
> > 
> > BTW Willem's patch is against lk 2.5.52 .
> > 
> Right. And next to this ide-scsi patch, you will also want
> the one line fix to ide.c I posted earlier.
> 
> http://marc.theaimsgroup.com/?l=linux-scsi&m=104017636631422&w=2
> 
> Regards, Willem Riede.
> -
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

Andre Hedrick
LAD Storage Consulting Group


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] ide-scsi changes for new mid level api and error handling in 2.5.52
  2002-12-23 19:05     ` Andre Hedrick
@ 2002-12-25 21:30       ` Alan Cox
  0 siblings, 0 replies; 5+ messages in thread
From: Alan Cox @ 2002-12-25 21:30 UTC (permalink / raw
  To: Andre Hedrick; +Cc: Willem Riede, linux-scsi

On Mon, 2002-12-23 at 19:05, Andre Hedrick wrote:
> 
> There are a few changes I have to fix the ordering of the driver for clean
> DMA ATAPI.  These are test on ia64 Itanium 2 from HP.

Actually the fixes from HP have been in the base 2.4 and 2.5 IDE for
several weeks


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2002-12-25 21:30 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-12-21 22:46 [PATCH] ide-scsi changes for new mid level api and error handling in 2.5.52 Willem Riede
2002-12-22  1:59 ` Douglas Gilbert
2002-12-22 17:14   ` Willem Riede
2002-12-23 19:05     ` Andre Hedrick
2002-12-25 21:30       ` Alan Cox

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.