- Allocate hostdata with DMA separately in the driver - Audited ->cmnd uses and it only ever copies them - Enable sense_buffer bouncing using new sense_buffer_isa flag - Enable block layer bouncing explicitely - Remove unchecked_isa_dma Untested due to lack of hardware Signed-off-by: Andi Kleen <ak@xxxxxxx> Signed-off-by: Andi Kleen <andi@xxxxxxxxxxxxxx> Signed-off-by: Andi Kleen <ak@xxxxxxxxxxxxxxx> --- drivers/scsi/eata.c | 54 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) Index: linux/drivers/scsi/eata.c =================================================================== --- linux.orig/drivers/scsi/eata.c 2008-11-15 22:37:10.000000000 +0100 +++ linux/drivers/scsi/eata.c 2008-11-15 22:37:12.000000000 +0100 @@ -512,6 +512,13 @@ sector_t, int *); static int eata2x_slave_configure(struct scsi_device *); +static int eata_adjust_queue(struct scsi_device *device) +{ + if (device->host->sense_buffer_isa) + blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_ISA); + return 0; +} + static struct scsi_host_template driver_template = { .name = "EATA/DMA 2.0x rev. 8.10.00 ", .detect = eata2x_detect, @@ -522,8 +529,8 @@ .bios_param = eata2x_bios_param, .slave_configure = eata2x_slave_configure, .this_id = 7, - .unchecked_isa_dma = 1, .use_clustering = ENABLE_CLUSTERING, + .slave_alloc = eata_adjust_queue, }; #if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD) @@ -834,6 +841,16 @@ struct mssp sp; /* Local copy of sp buffer */ }; +struct hostdata_ptr { + struct hostdata *host; + dma_addr_t dma; +}; + +#define eata_shost_priv(shost) \ + (((struct hostdata_ptr *)shost_priv(shost))->host) +#define eata_shost_dma(shost) \ + (((struct hostdata_ptr *)shost_priv(shost))->dma) + static struct Scsi_Host *sh[MAX_BOARDS]; static const char *driver_name = "EATA"; static char sha[MAX_BOARDS]; @@ -1266,14 +1283,23 @@ #endif spin_unlock_irq(&driver_lock); - sh[j] = shost = scsi_register(tpnt, sizeof(struct hostdata)); + sh[j] = shost = scsi_register(tpnt, sizeof(struct hostdata_ptr)); + ha = dma_alloc_coherent(pdev ? &pdev->dev : NULL, + sizeof(struct hostdata), + &eata_shost_dma(shost), GFP_KERNEL); spin_lock_irq(&driver_lock); - if (shost == NULL) { + if (shost == NULL || ha == NULL) { + if (ha) + dma_free_coherent(pdev ? &pdev->dev : NULL, + sizeof(struct hostdata), + ha, eata_shost_dma(shost)); printk("%s: unable to register host, detaching.\n", name); goto freedma; } + eata_shost_priv(shost) = ha; + shost->io_port = port_base; shost->unique_id = port_base; shost->n_io_port = REGION_SIZE; @@ -1283,8 +1309,6 @@ shost->this_id = (ushort) info.host_addr[3]; shost->can_queue = (ushort) info.queue_size; shost->cmd_per_lun = MAX_CMD_PER_LUN; - - ha = (struct hostdata *)shost->hostdata; memset(ha, 0, sizeof(struct hostdata)); ha->subversion = subversion; @@ -1293,11 +1317,9 @@ ha->pdev = pdev; ha->board_number = j; - if (ha->subversion == ESA) - shost->unchecked_isa_dma = 0; - else { + if (ha->subversion != ESA) { unsigned long flags; - shost->unchecked_isa_dma = 1; + shost->sense_buffer_isa = 1; flags = claim_dma_lock(); disable_dma(dma_channel); @@ -1355,7 +1377,7 @@ for (i = 0; i < shost->can_queue; i++) { size_t sz = shost->sg_tablesize *sizeof(struct sg_list); - gfp_t gfp_mask = (shost->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC; + gfp_t gfp_mask = (shost->sense_buffer_isa ? GFP_DMA : 0) | GFP_ATOMIC; ha->cp[i].sglist = kmalloc(sz, gfp_mask); if (!ha->cp[i].sglist) { printk @@ -1752,7 +1774,7 @@ void (*done) (struct scsi_cmnd *)) { struct Scsi_Host *shost = SCpnt->device->host; - struct hostdata *ha = (struct hostdata *)shost->hostdata; + struct hostdata *ha = eata_shost_priv(shost); unsigned int i, k; struct mscp *cpp; @@ -1836,7 +1858,7 @@ static int eata2x_eh_abort(struct scsi_cmnd *SCarg) { struct Scsi_Host *shost = SCarg->device->host; - struct hostdata *ha = (struct hostdata *)shost->hostdata; + struct hostdata *ha = eata_shost_priv(shost); unsigned int i; if (SCarg->host_scribble == NULL) { @@ -1906,7 +1928,7 @@ int arg_done = 0; struct scsi_cmnd *SCpnt; struct Scsi_Host *shost = SCarg->device->host; - struct hostdata *ha = (struct hostdata *)shost->hostdata; + struct hostdata *ha = eata_shost_priv(shost); scmd_printk(KERN_INFO, SCarg, "reset, enter, pid %ld.\n", SCarg->serial_number); @@ -2292,7 +2314,7 @@ unsigned int i, k, c, status, tstatus, reg; struct mssp *spp; struct mscp *cpp; - struct hostdata *ha = (struct hostdata *)shost->hostdata; + struct hostdata *ha = eata_shost_priv(shost); int irq = shost->irq; /* Check if this board need to be serviced */ @@ -2552,7 +2574,7 @@ static int eata2x_release(struct Scsi_Host *shost) { - struct hostdata *ha = (struct hostdata *)shost->hostdata; + struct hostdata *ha = eata_shost_priv(shost); unsigned int i; for (i = 0; i < shost->can_queue; i++) @@ -2572,6 +2594,8 @@ free_dma(shost->dma_channel); release_region(shost->io_port, shost->n_io_port); + dma_free_coherent(ha->pdev ? &ha->pdev->dev : NULL, + sizeof(*ha), ha, eata_shost_dma(shost)); scsi_unregister(shost); return 0; } -- 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