Skip to content

Commit 1794ef2

Browse files
Christoph Hellwigmartinkpetersen
authored andcommitted
scsi: aha1542: convert to DMA mapping API
aha1542 is one of the last users of the legacy isa_*_to_bus APIs, which also isn't portable enough. Convert it to the proper DMA mapping API. Thanks to Ondrej Zary for testing and finding and fixing a crucial bug. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 469f72d commit 1794ef2

File tree

1 file changed

+91
-35
lines changed

1 file changed

+91
-35
lines changed

drivers/scsi/aha1542.c

Lines changed: 91 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,15 @@ struct aha1542_hostdata {
5858
int aha1542_last_mbi_used;
5959
int aha1542_last_mbo_used;
6060
struct scsi_cmnd *int_cmds[AHA1542_MAILBOXES];
61-
struct mailbox mb[2 * AHA1542_MAILBOXES];
62-
struct ccb ccb[AHA1542_MAILBOXES];
61+
struct mailbox *mb;
62+
dma_addr_t mb_handle;
63+
struct ccb *ccb;
64+
dma_addr_t ccb_handle;
65+
};
66+
67+
struct aha1542_cmd {
68+
struct chain *chain;
69+
dma_addr_t chain_handle;
6370
};
6471

6572
static inline void aha1542_intr_reset(u16 base)
@@ -233,6 +240,21 @@ static int aha1542_test_port(struct Scsi_Host *sh)
233240
return 1;
234241
}
235242

243+
static void aha1542_free_cmd(struct scsi_cmnd *cmd)
244+
{
245+
struct aha1542_cmd *acmd = scsi_cmd_priv(cmd);
246+
struct device *dev = cmd->device->host->dma_dev;
247+
size_t len = scsi_sg_count(cmd) * sizeof(struct chain);
248+
249+
if (acmd->chain) {
250+
dma_unmap_single(dev, acmd->chain_handle, len, DMA_TO_DEVICE);
251+
kfree(acmd->chain);
252+
}
253+
254+
acmd->chain = NULL;
255+
scsi_dma_unmap(cmd);
256+
}
257+
236258
static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
237259
{
238260
struct Scsi_Host *sh = dev_id;
@@ -303,7 +325,7 @@ static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
303325
return IRQ_HANDLED;
304326
};
305327

306-
mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus(&ccb[0]))) / sizeof(struct ccb);
328+
mbo = (scsi2int(mb[mbi].ccbptr) - aha1542->ccb_handle) / sizeof(struct ccb);
307329
mbistatus = mb[mbi].status;
308330
mb[mbi].status = 0;
309331
aha1542->aha1542_last_mbi_used = mbi;
@@ -331,8 +353,7 @@ static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
331353
return IRQ_HANDLED;
332354
}
333355
my_done = tmp_cmd->scsi_done;
334-
kfree(tmp_cmd->host_scribble);
335-
tmp_cmd->host_scribble = NULL;
356+
aha1542_free_cmd(tmp_cmd);
336357
/* Fetch the sense data, and tuck it away, in the required slot. The
337358
Adaptec automatically fetches it, and there is no guarantee that
338359
we will still have it in the cdb when we come back */
@@ -369,6 +390,7 @@ static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
369390

370391
static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
371392
{
393+
struct aha1542_cmd *acmd = scsi_cmd_priv(cmd);
372394
struct aha1542_hostdata *aha1542 = shost_priv(sh);
373395
u8 direction;
374396
u8 target = cmd->device->id;
@@ -378,7 +400,6 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
378400
int mbo, sg_count;
379401
struct mailbox *mb = aha1542->mb;
380402
struct ccb *ccb = aha1542->ccb;
381-
struct chain *cptr;
382403

383404
if (*cmd->cmnd == REQUEST_SENSE) {
384405
/* Don't do the command - we have the sense data already */
@@ -398,15 +419,17 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
398419
print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, cmd->cmd_len);
399420
}
400421
#endif
401-
if (bufflen) { /* allocate memory before taking host_lock */
402-
sg_count = scsi_sg_count(cmd);
403-
cptr = kmalloc_array(sg_count, sizeof(*cptr),
404-
GFP_KERNEL | GFP_DMA);
405-
if (!cptr)
406-
return SCSI_MLQUEUE_HOST_BUSY;
407-
} else {
408-
sg_count = 0;
409-
cptr = NULL;
422+
sg_count = scsi_dma_map(cmd);
423+
if (sg_count) {
424+
size_t len = sg_count * sizeof(struct chain);
425+
426+
acmd->chain = kmalloc(len, GFP_DMA);
427+
if (!acmd->chain)
428+
goto out_unmap;
429+
acmd->chain_handle = dma_map_single(sh->dma_dev, acmd->chain,
430+
len, DMA_TO_DEVICE);
431+
if (dma_mapping_error(sh->dma_dev, acmd->chain_handle))
432+
goto out_free_chain;
410433
}
411434

412435
/* Use the outgoing mailboxes in a round-robin fashion, because this
@@ -437,7 +460,8 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
437460
shost_printk(KERN_DEBUG, sh, "Sending command (%d %p)...", mbo, cmd->scsi_done);
438461
#endif
439462

440-
any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
463+
/* This gets trashed for some reason */
464+
any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(*ccb));
441465

442466
memset(&ccb[mbo], 0, sizeof(struct ccb));
443467

@@ -456,21 +480,18 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
456480
int i;
457481

458482
ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
459-
cmd->host_scribble = (void *)cptr;
460483
scsi_for_each_sg(cmd, sg, sg_count, i) {
461-
any2scsi(cptr[i].dataptr, isa_page_to_bus(sg_page(sg))
462-
+ sg->offset);
463-
any2scsi(cptr[i].datalen, sg->length);
484+
any2scsi(acmd->chain[i].dataptr, sg_dma_address(sg));
485+
any2scsi(acmd->chain[i].datalen, sg_dma_len(sg));
464486
};
465487
any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
466-
any2scsi(ccb[mbo].dataptr, isa_virt_to_bus(cptr));
488+
any2scsi(ccb[mbo].dataptr, acmd->chain_handle);
467489
#ifdef DEBUG
468-
shost_printk(KERN_DEBUG, sh, "cptr %p: ", cptr);
469-
print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, cptr, 18);
490+
shost_printk(KERN_DEBUG, sh, "cptr %p: ", acmd->chain);
491+
print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, acmd->chain, 18);
470492
#endif
471493
} else {
472494
ccb[mbo].op = 0; /* SCSI Initiator Command */
473-
cmd->host_scribble = NULL;
474495
any2scsi(ccb[mbo].datalen, 0);
475496
any2scsi(ccb[mbo].dataptr, 0);
476497
};
@@ -488,24 +509,29 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
488509
spin_unlock_irqrestore(sh->host_lock, flags);
489510

490511
return 0;
512+
out_free_chain:
513+
kfree(acmd->chain);
514+
acmd->chain = NULL;
515+
out_unmap:
516+
scsi_dma_unmap(cmd);
517+
return SCSI_MLQUEUE_HOST_BUSY;
491518
}
492519

493520
/* Initialize mailboxes */
494521
static void setup_mailboxes(struct Scsi_Host *sh)
495522
{
496523
struct aha1542_hostdata *aha1542 = shost_priv(sh);
497-
int i;
498-
struct mailbox *mb = aha1542->mb;
499-
struct ccb *ccb = aha1542->ccb;
500-
501524
u8 mb_cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0};
525+
int i;
502526

503527
for (i = 0; i < AHA1542_MAILBOXES; i++) {
504-
mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0;
505-
any2scsi(mb[i].ccbptr, isa_virt_to_bus(&ccb[i]));
528+
aha1542->mb[i].status = 0;
529+
any2scsi(aha1542->mb[i].ccbptr,
530+
aha1542->ccb_handle + i * sizeof(struct ccb));
531+
aha1542->mb[AHA1542_MAILBOXES + i].status = 0;
506532
};
507533
aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */
508-
any2scsi((mb_cmd + 2), isa_virt_to_bus(mb));
534+
any2scsi(mb_cmd + 2, aha1542->mb_handle);
509535
if (aha1542_out(sh->io_port, mb_cmd, 5))
510536
shost_printk(KERN_ERR, sh, "failed setting up mailboxes\n");
511537
aha1542_intr_reset(sh->io_port);
@@ -739,11 +765,26 @@ static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct
739765
if (aha1542->bios_translation == BIOS_TRANSLATION_25563)
740766
shost_printk(KERN_INFO, sh, "Using extended bios translation\n");
741767

768+
if (dma_set_mask_and_coherent(pdev, DMA_BIT_MASK(24)) < 0)
769+
goto unregister;
770+
771+
aha1542->mb = dma_alloc_coherent(pdev,
772+
AHA1542_MAILBOXES * 2 * sizeof(struct mailbox),
773+
&aha1542->mb_handle, GFP_KERNEL);
774+
if (!aha1542->mb)
775+
goto unregister;
776+
777+
aha1542->ccb = dma_alloc_coherent(pdev,
778+
AHA1542_MAILBOXES * sizeof(struct ccb),
779+
&aha1542->ccb_handle, GFP_KERNEL);
780+
if (!aha1542->ccb)
781+
goto free_mb;
782+
742783
setup_mailboxes(sh);
743784

744785
if (request_irq(sh->irq, aha1542_interrupt, 0, "aha1542", sh)) {
745786
shost_printk(KERN_ERR, sh, "Unable to allocate IRQ.\n");
746-
goto unregister;
787+
goto free_ccb;
747788
}
748789
if (sh->dma_channel != 0xFF) {
749790
if (request_dma(sh->dma_channel, "aha1542")) {
@@ -762,11 +803,18 @@ static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct
762803
scsi_scan_host(sh);
763804

764805
return sh;
806+
765807
free_dma:
766808
if (sh->dma_channel != 0xff)
767809
free_dma(sh->dma_channel);
768810
free_irq:
769811
free_irq(sh->irq, sh);
812+
free_ccb:
813+
dma_free_coherent(pdev, AHA1542_MAILBOXES * sizeof(struct ccb),
814+
aha1542->ccb, aha1542->ccb_handle);
815+
free_mb:
816+
dma_free_coherent(pdev, AHA1542_MAILBOXES * 2 * sizeof(struct mailbox),
817+
aha1542->mb, aha1542->mb_handle);
770818
unregister:
771819
scsi_host_put(sh);
772820
release:
@@ -777,9 +825,16 @@ static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct
777825

778826
static int aha1542_release(struct Scsi_Host *sh)
779827
{
828+
struct aha1542_hostdata *aha1542 = shost_priv(sh);
829+
struct device *dev = sh->dma_dev;
830+
780831
scsi_remove_host(sh);
781832
if (sh->dma_channel != 0xff)
782833
free_dma(sh->dma_channel);
834+
dma_free_coherent(dev, AHA1542_MAILBOXES * sizeof(struct ccb),
835+
aha1542->ccb, aha1542->ccb_handle);
836+
dma_free_coherent(dev, AHA1542_MAILBOXES * 2 * sizeof(struct mailbox),
837+
aha1542->mb, aha1542->mb_handle);
783838
if (sh->irq)
784839
free_irq(sh->irq, sh);
785840
if (sh->io_port && sh->n_io_port)
@@ -826,7 +881,8 @@ static int aha1542_dev_reset(struct scsi_cmnd *cmd)
826881

827882
aha1542->aha1542_last_mbo_used = mbo;
828883

829-
any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
884+
/* This gets trashed for some reason */
885+
any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(*ccb));
830886

831887
memset(&ccb[mbo], 0, sizeof(struct ccb));
832888

@@ -901,8 +957,7 @@ static int aha1542_reset(struct scsi_cmnd *cmd, u8 reset_cmd)
901957
*/
902958
continue;
903959
}
904-
kfree(tmp_cmd->host_scribble);
905-
tmp_cmd->host_scribble = NULL;
960+
aha1542_free_cmd(tmp_cmd);
906961
aha1542->int_cmds[i] = NULL;
907962
aha1542->mb[i].status = 0;
908963
}
@@ -946,6 +1001,7 @@ static struct scsi_host_template driver_template = {
9461001
.module = THIS_MODULE,
9471002
.proc_name = "aha1542",
9481003
.name = "Adaptec 1542",
1004+
.cmd_size = sizeof(struct aha1542_cmd),
9491005
.queuecommand = aha1542_queuecommand,
9501006
.eh_device_reset_handler= aha1542_dev_reset,
9511007
.eh_bus_reset_handler = aha1542_bus_reset,

0 commit comments

Comments
 (0)