[PATCH] [7/21] Remove unchecked_isa_dma in aha152x/wd7000/sym53c416/u14-34f/NCR53c406a

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

 



I lumped these all together because these old ISA only drivers all look 
very unmaintained and the changes were relatively simple.

I audited them for possible use of unchecked_isa_dma and fixed the cases
who needed them:
- Allocate separate dma'able hostdata when needed
- Checked that they all always copy ->cmnd
- Checked if they need sense_buffer bouncing and enable when needed
(i'm not 100% sure what it means if a driver does not reference
sense_buffer, but all except ultrastor and u14-34f do not) 
- Add a explicit slave_alloc callback to enable block layer bouncing

Untested due to lack of hardware.

Signed-off-by: Andi Kleen <ak@xxxxxxx>

---
 drivers/scsi/NCR53c406a.c |    8 +++++-
 drivers/scsi/aha152x.c    |   29 +++++++++++++++++++++---
 drivers/scsi/sym53c416.c  |    9 ++++++-
 drivers/scsi/u14-34f.c    |   54 +++++++++++++++++++++++++++++++++++-----------
 drivers/scsi/ultrastor.c  |   13 ++++++++---
 drivers/scsi/wd7000.c     |   48 +++++++++++++++++++++++++++-------------
 6 files changed, 124 insertions(+), 37 deletions(-)

Index: linux/drivers/scsi/aha152x.c
===================================================================
--- linux.orig/drivers/scsi/aha152x.c
+++ linux/drivers/scsi/aha152x.c
@@ -551,6 +551,10 @@ struct aha152x_hostdata {
 	struct list_head host_list;
 };
 
+struct aha152x_hostdata_ptr {
+	struct aha152x_hostdata *host;
+	dma_addr_t dma;
+};
 
 /*
  * host specific command extension
@@ -564,7 +568,10 @@ struct aha152x_scdata {
 
 /* access macros for hostdata */
 
-#define HOSTDATA(shpnt)		((struct aha152x_hostdata *) &shpnt->hostdata)
+#define HOSTDATA(shpnt) \
+	(((struct aha152x_hostdata_ptr *) shost_priv(shpnt))->host)
+#define HOSTDMA(shpnt) \
+	(((struct aha152x_hostdata_ptr *) shost_priv(shpnt))->dma)
 
 #define HOSTNO			((shpnt)->host_no)
 
@@ -771,14 +778,24 @@ static irqreturn_t swintr(int irqno, voi
 struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
 {
 	struct Scsi_Host *shpnt;
+	struct aha152x_hostdata *host;
 
-	shpnt = scsi_host_alloc(&aha152x_driver_template, sizeof(struct aha152x_hostdata));
+	shpnt = scsi_host_alloc(&aha152x_driver_template,
+				sizeof(struct aha152x_hostdata_ptr));
 	if (!shpnt) {
 		printk(KERN_ERR "aha152x: scsi_host_alloc failed\n");
 		return NULL;
 	}
 
-	memset(HOSTDATA(shpnt), 0, sizeof *HOSTDATA(shpnt));
+	host = dma_alloc_coherent(NULL, sizeof(struct aha152x_hostdata),
+				  &HOSTDMA(shpnt), GFP_KERNEL);
+	HOSTDATA(shpnt) = host;
+	if (!host) {
+		scsi_host_put(shpnt);
+		printk(KERN_ERR "aha152x: dma alloc of hostdata failed\n");
+		return NULL;
+	}
+
 	INIT_LIST_HEAD(&HOSTDATA(shpnt)->host_list);
 
 	/* need to have host registered before triggering any interrupt */
@@ -899,6 +916,8 @@ struct Scsi_Host *aha152x_probe_one(stru
 
 out_host_put:
 	list_del(&HOSTDATA(shpnt)->host_list);
+	dma_free_coherent(NULL, sizeof(struct aha152x_hostdata),
+			  HOSTDATA(shpnt), HOSTDMA(shpnt));
 	scsi_host_put(shpnt);
 
 	return NULL;
@@ -924,6 +943,8 @@ void aha152x_release(struct Scsi_Host *s
 #endif
 
 	list_del(&HOSTDATA(shpnt)->host_list);
+	dma_free_coherent(NULL, sizeof(struct aha152x_hostdata),
+			  HOSTDATA(shpnt), HOSTDMA(shpnt));
 	scsi_host_put(shpnt);
 }
 
@@ -3456,7 +3477,7 @@ static int aha152x_proc_info(struct Scsi
 
 static int aha152x_adjust_queue(struct scsi_device *device)
 {
-	blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_HIGH);
+	blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_ISA);
 	return 0;
 }
 
Index: linux/drivers/scsi/wd7000.c
===================================================================
--- linux.orig/drivers/scsi/wd7000.c
+++ linux/drivers/scsi/wd7000.c
@@ -189,7 +189,6 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsicam.h>
 
-
 #undef  WD7000_DEBUG		/* general debug                */
 #ifdef WD7000_DEBUG
 #define dprintk printk
@@ -260,6 +259,14 @@ typedef struct adapter {
 	unchar rev1, rev2;	/* filled in by wd7000_revision      */
 } Adapter;
 
+struct adapter_ptr {
+	Adapter *host;
+	dma_addr_t dma;
+};
+
+#define wd_host(shost) (((struct adapter_ptr *)shost_priv(shost))->host)
+#define wd_host_dma(shost) (((struct adapter_ptr *)shost_priv(shost))->dma)
+
 /*
  * (linear) base address for ROM BIOS
  */
@@ -1092,7 +1099,7 @@ static int wd7000_queuecommand(struct sc
 	unchar idlun;
 	short cdblen;
 	int nseg;
-	Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
+	Adapter *host = wd_host(SCpnt->device->host);
 
 	cdblen = SCpnt->cmd_len;
 	idlun = ((SCpnt->device->id << 5) & 0xe0) | (SCpnt->device->lun & 7);
@@ -1312,7 +1319,7 @@ static int wd7000_set_info(char *buffer,
 
 static int wd7000_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length,  int inout)
 {
-	Adapter *adapter = (Adapter *)host->hostdata;
+	Adapter *adapter = wd_host(host);
 	unsigned long flags;
 	char *pos = buffer;
 #ifdef WD7000_DEBUG
@@ -1485,18 +1492,17 @@ static __init int wd7000_detect(struct s
 				dprintk("ok!\n");
 
 			if (inb(iobase + ASC_INTR_STAT) == 1) {
-				/*
-				 *  We register here, to get a pointer to the extra space,
-				 *  which we'll use as the Adapter structure (host) for
-				 *  this adapter.  It is located just after the registered
-				 *  Scsi_Host structure (sh), and is located by the empty
-				 *  array hostdata.
-				 */
-				sh = scsi_register(tpnt, sizeof(Adapter));
+				sh = scsi_register(tpnt, sizeof(struct adapter_ptr));
 				if (sh == NULL)
 					goto err_release;
 
-				host = (Adapter *) sh->hostdata;
+				host = dma_alloc_coherent(NULL, sizeof(Adapter),
+							  &wd_host_dma(sh),
+							  GFP_KERNEL);
+				if (!host)
+					goto err_unregister;
+
+				wd_host(sh) = host;
 
 				dprintk("wd7000_detect: adapter allocated at 0x%x\n", (int) host);
 				memset(host, 0, sizeof(Adapter));
@@ -1513,7 +1519,7 @@ static __init int wd7000_detect(struct s
 				dprintk("wd7000_detect: Trying init WD-7000 card at IO " "0x%x, IRQ %d, DMA %d...\n", host->iobase, host->irq, host->dma);
 
 				if (!wd7000_init(host))	/* Initialization failed */
-					goto err_unregister;
+					goto err_free_host;
 
 				/*
 				 *  OK from here - we'll use this adapter/configuration.
@@ -1540,6 +1546,8 @@ static __init int wd7000_detect(struct s
 
 		continue;
 
+	      err_free_host:
+		dma_free_coherent(NULL, sizeof(Adapter), host,wd_host_dma(sh));
 	      err_unregister:
 		scsi_unregister(sh);
 	      err_release:
@@ -1559,6 +1567,8 @@ static int wd7000_release(struct Scsi_Ho
 		free_irq(shost->irq, NULL);
 	if (shost->io_port && shost->n_io_port)
 		release_region(shost->io_port, shost->n_io_port);
+	dma_free_coherent(NULL, sizeof(Adapter), wd_host(shost),
+			  wd_host_dma(shost));
 	scsi_unregister(shost);
 	return 0;
 }
@@ -1569,7 +1579,7 @@ static int wd7000_release(struct Scsi_Ho
  */
 static int wd7000_abort(Scsi_Cmnd * SCpnt)
 {
-	Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
+	Adapter *host = wd_host(SCpnt->device->host);
 
 	if (inb(host->iobase + ASC_STAT) & INT_IM) {
 		printk("wd7000_abort: lost interrupt\n");
@@ -1586,7 +1596,7 @@ static int wd7000_abort(Scsi_Cmnd * SCpn
 
 static int wd7000_host_reset(struct scsi_cmnd *SCpnt)
 {
-	Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
+	Adapter *host = wd_host(SCpnt->device->host);
 
 	spin_unlock_irq(SCpnt->device->host->host_lock);
 
@@ -1652,6 +1662,12 @@ static int wd7000_biosparam(struct scsi_
 	return (0);
 }
 
+static int wd7000_adjust_queue(struct scsi_device *device)
+{
+	blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_ISA);
+	return 0;
+}
+
 MODULE_AUTHOR("Thomas Wuensche, John Boyd, Miroslav Zagorac");
 MODULE_DESCRIPTION("Driver for the WD7000 series ISA controllers");
 MODULE_LICENSE("GPL");
@@ -1669,7 +1685,7 @@ static struct scsi_host_template driver_
 	.this_id		= 7,
 	.sg_tablesize		= WD7000_SG,
 	.cmd_per_lun		= 1,
-	.unchecked_isa_dma	= 1,
+	.slave_alloc		= wd7000_adjust_queue,
 	.use_clustering		= ENABLE_CLUSTERING,
 };
 
Index: linux/drivers/scsi/NCR53c406a.c
===================================================================
--- linux.orig/drivers/scsi/NCR53c406a.c
+++ linux/drivers/scsi/NCR53c406a.c
@@ -1045,6 +1045,12 @@ static void __init calc_port_addr(void)
 
 MODULE_LICENSE("GPL");
 
+static int NCR53c406a_adjust_queue(struct scsi_device *device)
+{
+	blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_ISA);
+	return 0;
+}
+
 /* NOTE:  scatter-gather support only works in PIO mode.
  * Use SG_NONE if DMA mode is enabled!
  */
@@ -1063,8 +1069,8 @@ static struct scsi_host_template driver_
      .this_id           	= 7			/* SCSI ID of the chip */,
      .sg_tablesize      	= 32			/*SG_ALL*/ /*SG_NONE*/, 
      .cmd_per_lun       	= 1			/* commands per lun */, 
-     .unchecked_isa_dma 	= 1			/* unchecked_isa_dma */,
      .use_clustering    	= ENABLE_CLUSTERING,
+     .slave_alloc		= NCR53c406a_adjust_queue,
 };
 
 #include "scsi_module.c"
Index: linux/drivers/scsi/u14-34f.c
===================================================================
--- linux.orig/drivers/scsi/u14-34f.c
+++ linux/drivers/scsi/u14-34f.c
@@ -439,6 +439,12 @@ static int u14_34f_bios_param(struct scs
                               sector_t, int *);
 static int u14_34f_slave_configure(struct scsi_device *);
 
+static int u14_34f_adjust_queue(struct scsi_device *device)
+{
+	blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_ISA);
+	return 0;
+}
+
 static struct scsi_host_template driver_template = {
                 .name                    = "UltraStor 14F/34F rev. 8.10.00 ",
                 .detect                  = u14_34f_detect,
@@ -449,8 +455,9 @@ static struct scsi_host_template driver_
                 .bios_param              = u14_34f_bios_param,
                 .slave_configure         = u14_34f_slave_configure,
                 .this_id                 = 7,
-                .unchecked_isa_dma       = 1,
                 .use_clustering          = ENABLE_CLUSTERING,
+		.sense_buffer_mask	 = DMA_24BIT_MASK,
+		.slave_alloc		 = u14_34f_adjust_queue,
                 };
 
 #if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD)
@@ -606,6 +613,11 @@ struct hostdata {
    char board_id[256];                  /* data from INQUIRY on this board */
    };
 
+struct hostdata_ptr {
+	struct hostdata *host;
+	dma_addr_t dma;
+};
+
 static struct Scsi_Host *sh[MAX_BOARDS + 1];
 static const char *driver_name = "Ux4F";
 static char sha[MAX_BOARDS];
@@ -627,7 +639,9 @@ static unsigned long io_port[] = {
    0x0
    };
 
-#define HD(board) ((struct hostdata *) &sh[board]->hostdata)
+#define HOSTDATA(shost) (((struct hostdata_ptr *)shost_priv(shost))->host)
+#define HOSTDMA(shost) (((struct hostdata_ptr *)shost_priv(shost))->dma)
+#define HD(board) HOSTDATA(sh[board])
 #define BN(board) (HD(board)->board_name)
 
 /* Device is Little Endian */
@@ -688,7 +702,7 @@ static int u14_34f_slave_configure(struc
    char *tag_suffix, *link_suffix;
    struct Scsi_Host *host = dev->host;
 
-   j = ((struct hostdata *) host->hostdata)->board_number;
+   j = HOSTDATA(host)->board_number;
 
    utqd = MAX_CMD_PER_LUN;
    tqd = max_queue_depth;
@@ -798,6 +812,8 @@ static int port_detect \
    unsigned char irq, dma_channel, subversion, i;
    unsigned char in_byte;
    char *bus_type, dma_name[16];
+   struct hostdata *host;
+   dma_addr_t dma;
 
    /* Allowed BIOS base addresses (NULL indicates reserved) */
    unsigned long bios_segment_table[8] = {
@@ -887,13 +903,26 @@ static int port_detect \
    if (have_old_firmware) tpnt->use_clustering = DISABLE_CLUSTERING;
 
    spin_unlock_irq(&driver_lock);
-   sh[j] = scsi_register(tpnt, sizeof(struct hostdata));
+
+   host = dma_alloc_coherent(NULL, sizeof(struct hostdata), &dma, GFP_KERNEL);
+   if (!host) {
+	   printk("%s: unable to allocate dma data\n", name);
+	   spin_lock_irq(&driver_lock);
+	   goto freedma;
+   }
+
+   sh[j] = scsi_register(tpnt, sizeof(struct hostdata_ptr));
+   if (sh[j])
+     HOSTDMA(sh[j]) = dma;
+
    spin_lock_irq(&driver_lock);
 
    if (sh[j] == NULL) {
       printk("%s: unable to register host, detaching.\n", name);
-      goto freedma;
-      }
+      goto freebounce;
+   }
+   HOSTDATA(sh[j]) = host;
+   memset(host, 0, sizeof(struct hostdata));
 
    sh[j]->io_port = port_base;
    sh[j]->unique_id = port_base;
@@ -931,14 +960,12 @@ static int port_detect \
    if (have_old_firmware) sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
 
    if (HD(j)->subversion == ESA) {
-      sh[j]->unchecked_isa_dma = FALSE;
       sh[j]->dma_channel = NO_DMA;
       sprintf(BN(j), "U34F%d", j);
       bus_type = "VESA";
       }
    else {
       unsigned long flags;
-      sh[j]->unchecked_isa_dma = TRUE;
 
       flags=claim_dma_lock();
       disable_dma(dma_channel);
@@ -980,7 +1007,7 @@ static int port_detect \
    for (i = 0; i < sh[j]->can_queue; i++)
       if (! ((&HD(j)->cp[i])->sglist = kmalloc(
             sh[j]->sg_tablesize * sizeof(struct sg_list),
-            (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) {
+	    ((HD(j)->subversion != ESA) ? __GFP_DMA : 0) | GFP_ATOMIC))) {
          printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i);
          goto release;
          }
@@ -1014,6 +1041,8 @@ static int port_detect \
 
    return TRUE;
 
+freebounce:
+   dma_free_coherent(NULL, sizeof(struct hostdata), host, HOSTDMA(sh[j]));
 freedma:
    if (subversion == ISA) free_dma(dma_channel);
 freeirq:
@@ -1250,7 +1279,7 @@ static int u14_34f_queuecommand(struct s
    struct mscp *cpp;
 
    /* j is the board number */
-   j = ((struct hostdata *) SCpnt->device->host->hostdata)->board_number;
+   j = HOSTDATA(SCpnt->device->host)->board_number;
 
    if (SCpnt->host_scribble)
       panic("%s: qcomm, pid %ld, SCpnt %p already active.\n",
@@ -1329,7 +1358,7 @@ static int u14_34f_queuecommand(struct s
 static int u14_34f_eh_abort(struct scsi_cmnd *SCarg) {
    unsigned int i, j;
 
-   j = ((struct hostdata *) SCarg->device->host->hostdata)->board_number;
+   j = HOSTDATA(SCarg->device->host)->board_number;
 
    if (SCarg->host_scribble == NULL) {
       scmd_printk(KERN_INFO, SCarg, "abort, pid %ld inactive.\n",
@@ -1396,7 +1425,7 @@ static int u14_34f_eh_host_reset(struct 
    int arg_done = FALSE;
    struct scsi_cmnd *SCpnt;
 
-   j = ((struct hostdata *) SCarg->device->host->hostdata)->board_number;
+   j = HOSTDATA(SCarg->device->host)->board_number;
    scmd_printk(KERN_INFO, SCarg, "reset, enter, pid %ld.\n", SCarg->serial_number);
 
    spin_lock_irq(sh[j]->host_lock);
@@ -1961,6 +1990,7 @@ static int u14_34f_release(struct Scsi_H
       free_dma(sh[j]->dma_channel);
 
    release_region(sh[j]->io_port, sh[j]->n_io_port);
+   dma_free_coherent(NULL, sizeof(struct hostdata), sh[j], HOSTDMA(sh[j]));
    scsi_unregister(sh[j]);
    return FALSE;
 }
Index: linux/drivers/scsi/sym53c416.c
===================================================================
--- linux.orig/drivers/scsi/sym53c416.c
+++ linux/drivers/scsi/sym53c416.c
@@ -825,6 +825,12 @@ module_param_array(sym53c416_3, uint, NU
 
 #endif
 
+static int sym53c416_adjust_queue(struct scsi_device *device)
+{
+	blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_ISA);
+	return 0;
+}
+
 static struct scsi_host_template driver_template = {
 	.proc_name =		"sym53c416",
 	.name =			"Symbios Logic 53c416",
@@ -838,7 +844,8 @@ static struct scsi_host_template driver_
 	.this_id =		SYM53C416_SCSI_ID,
 	.sg_tablesize =		32,
 	.cmd_per_lun =		1,
-	.unchecked_isa_dma =	1,
 	.use_clustering =	ENABLE_CLUSTERING,
+	.slave_alloc =		sym53c416_adjust_queue,
+
 };
 #include "scsi_module.c"
Index: linux/drivers/scsi/ultrastor.c
===================================================================
--- linux.orig/drivers/scsi/ultrastor.c
+++ linux/drivers/scsi/ultrastor.c
@@ -350,6 +350,12 @@ static void log_ultrastor_abort(struct u
 }
 #endif
 
+static int ultrastor_adjust_queue(struct scsi_device *device)
+{
+	blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_ISA);
+	return 0;
+}
+
 static int ultrastor_14f_detect(struct scsi_host_template * tpnt)
 {
     size_t i;
@@ -501,7 +507,10 @@ static int ultrastor_14f_detect(struct s
 	   config.dma_channel, config.ha_scsi_id, config.subversion);
 #endif
     tpnt->this_id = config.ha_scsi_id;
-    tpnt->unchecked_isa_dma = (config.subversion != U34F);
+    if (config.subversion != U34F) {
+	tpnt->sense_buffer_mask = DMA_24BIT_MASK;
+	tpnt->slave_alloc = ultrastor_adjust_queue;
+    }
 
 #if ULTRASTOR_MAX_CMDS > 1
     config.mscp_free = ~0;
@@ -605,7 +614,6 @@ static int ultrastor_24f_detect(struct s
 	     config.interrupt, config.ha_scsi_id);
 #endif
       tpnt->this_id = config.ha_scsi_id;
-      tpnt->unchecked_isa_dma = 0;
       tpnt->sg_tablesize = ULTRASTOR_24F_MAX_SG;
 
       shpnt = scsi_register(tpnt, 0);
@@ -1202,7 +1210,6 @@ static struct scsi_host_template driver_
 	.can_queue         = ULTRASTOR_MAX_CMDS,
 	.sg_tablesize      = ULTRASTOR_14F_MAX_SG,
 	.cmd_per_lun       = ULTRASTOR_MAX_CMDS_PER_LUN,
-	.unchecked_isa_dma = 1,
 	.use_clustering    = ENABLE_CLUSTERING,
 };
 #include "scsi_module.c"
--
To unsubscribe from this list: 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