On Thursday 02 August 2018 15:11:05 Christoph Hellwig wrote: > 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. > > Signed-off-by: Christoph Hellwig <hch@xxxxxx> > --- > drivers/scsi/aha1542.c | 112 ++++++++++++++++++++++++++++------------- > 1 file changed, 77 insertions(+), 35 deletions(-) > > diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c > index 41add33e3f1f..679b52a7cc69 100644 > --- a/drivers/scsi/aha1542.c > +++ b/drivers/scsi/aha1542.c > @@ -58,8 +58,15 @@ struct aha1542_hostdata { > int aha1542_last_mbi_used; > int aha1542_last_mbo_used; > struct scsi_cmnd *int_cmds[AHA1542_MAILBOXES]; > - struct mailbox mb[2 * AHA1542_MAILBOXES]; > - struct ccb ccb[AHA1542_MAILBOXES]; > + struct mailbox *mb; > + dma_addr_t mb_handle; > + struct ccb *ccb; > + dma_addr_t ccb_handle; > +}; > + > +struct aha1542_cmd { > + struct chain *chain; > + dma_addr_t chain_handle; > }; > > static inline void aha1542_intr_reset(u16 base) > @@ -233,6 +240,17 @@ static int aha1542_test_port(struct Scsi_Host *sh) > return 1; > } > > +static void aha1542_free_cmd(struct scsi_cmnd *cmd) > +{ > + struct aha1542_cmd *acmd = scsi_cmd_priv(cmd); > + struct device *dev = cmd->device->host->dma_dev; > + > + dma_free_coherent(dev, scsi_sg_count(cmd) * sizeof(struct chain), > + acmd->chain, acmd->chain_handle); > + acmd->chain = NULL; > + scsi_dma_unmap(cmd); > +} > + > static irqreturn_t aha1542_interrupt(int irq, void *dev_id) > { > struct Scsi_Host *sh = dev_id; > @@ -303,7 +321,7 @@ static irqreturn_t aha1542_interrupt(int irq, void > *dev_id) return IRQ_HANDLED; > }; > > - mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus(&ccb[0]))) / > sizeof(struct ccb); + mbo = (scsi2int(mb[mbi].ccbptr) - > aha1542->ccb_handle) / sizeof(struct ccb); mbistatus = mb[mbi].status; > mb[mbi].status = 0; > aha1542->aha1542_last_mbi_used = mbi; > @@ -331,8 +349,7 @@ static irqreturn_t aha1542_interrupt(int irq, void > *dev_id) return IRQ_HANDLED; > } > my_done = tmp_cmd->scsi_done; > - kfree(tmp_cmd->host_scribble); > - tmp_cmd->host_scribble = NULL; > + aha1542_free_cmd(tmp_cmd); > /* Fetch the sense data, and tuck it away, in the required slot. The > Adaptec automatically fetches it, and there is no guarantee that > we will still have it in the cdb when we come back */ > @@ -369,6 +386,7 @@ static irqreturn_t aha1542_interrupt(int irq, void > *dev_id) > > static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd > *cmd) { > + struct aha1542_cmd *acmd = scsi_cmd_priv(cmd); > struct aha1542_hostdata *aha1542 = shost_priv(sh); > u8 direction; > u8 target = cmd->device->id; > @@ -378,7 +396,6 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, > struct scsi_cmnd *cmd) int mbo, sg_count; > struct mailbox *mb = aha1542->mb; > struct ccb *ccb = aha1542->ccb; > - struct chain *cptr; > > if (*cmd->cmnd == REQUEST_SENSE) { > /* Don't do the command - we have the sense data already */ > @@ -398,15 +415,17 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, > struct scsi_cmnd *cmd) print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, > cmd->cmnd, cmd->cmd_len); } > #endif > - if (bufflen) { /* allocate memory before taking host_lock */ > - sg_count = scsi_sg_count(cmd); > - cptr = kmalloc_array(sg_count, sizeof(*cptr), > - GFP_KERNEL | GFP_DMA); > - if (!cptr) > + sg_count = scsi_dma_map(cmd); > + if (sg_count) { > + acmd->chain = dma_alloc_coherent(sh->dma_dev, > + sg_count * sizeof(struct chain), > + &acmd->chain_handle, GFP_DMA); > + if (!acmd->chain) { > + scsi_dma_unmap(cmd); > return SCSI_MLQUEUE_HOST_BUSY; > + } > } else { > - sg_count = 0; > - cptr = NULL; > + acmd->chain = NULL; > } > > /* Use the outgoing mailboxes in a round-robin fashion, because this > @@ -437,7 +456,8 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, > struct scsi_cmnd *cmd) shost_printk(KERN_DEBUG, sh, "Sending command (%d > %p)...", mbo, cmd->scsi_done); #endif > > - any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets > trashed for some reason */ + /* This gets trashed for some reason */ > + any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(ccb)); > > memset(&ccb[mbo], 0, sizeof(struct ccb)); > > @@ -456,21 +476,18 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, > struct scsi_cmnd *cmd) int i; > > ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */ > - cmd->host_scribble = (void *)cptr; > scsi_for_each_sg(cmd, sg, sg_count, i) { > - any2scsi(cptr[i].dataptr, isa_page_to_bus(sg_page(sg)) > - + sg->offset); > - any2scsi(cptr[i].datalen, sg->length); > + any2scsi(acmd->chain[i].dataptr, sg_dma_address(sg)); > + any2scsi(acmd->chain[i].datalen, sg_dma_len(sg)); > }; > any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain)); > - any2scsi(ccb[mbo].dataptr, isa_virt_to_bus(cptr)); > + any2scsi(ccb[mbo].dataptr, acmd->chain_handle); > #ifdef DEBUG > - shost_printk(KERN_DEBUG, sh, "cptr %p: ", cptr); > - print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, cptr, 18); > + shost_printk(KERN_DEBUG, sh, "cptr %p: ", acmd->chain); > + print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, acmd->chain, 18); > #endif > } else { > ccb[mbo].op = 0; /* SCSI Initiator Command */ > - cmd->host_scribble = NULL; > any2scsi(ccb[mbo].datalen, 0); > any2scsi(ccb[mbo].dataptr, 0); > }; > @@ -494,18 +511,17 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, > struct scsi_cmnd *cmd) static void setup_mailboxes(struct Scsi_Host *sh) > { > struct aha1542_hostdata *aha1542 = shost_priv(sh); > - int i; > - struct mailbox *mb = aha1542->mb; > - struct ccb *ccb = aha1542->ccb; > - > u8 mb_cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0}; > + int i; > > for (i = 0; i < AHA1542_MAILBOXES; i++) { > - mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0; > - any2scsi(mb[i].ccbptr, isa_virt_to_bus(&ccb[i])); > + aha1542->mb[i].status = 0; > + any2scsi(aha1542->mb[i].ccbptr, > + aha1542->ccb_handle + i * sizeof(struct ccb)); > + aha1542->mb[AHA1542_MAILBOXES + i].status = 0; > }; > aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block > */ - any2scsi((mb_cmd + 2), isa_virt_to_bus(mb)); > + any2scsi(mb_cmd + 2, aha1542->mb_handle); > if (aha1542_out(sh->io_port, mb_cmd, 5)) > shost_printk(KERN_ERR, sh, "failed setting up mailboxes\n"); > aha1542_intr_reset(sh->io_port); > @@ -756,12 +772,31 @@ static struct Scsi_Host *aha1542_hw_init(struct > scsi_host_template *tpnt, struct } > } > > - if (scsi_add_host(sh, pdev)) > + aha1542->mb = dma_alloc_coherent(pdev, > + AHA1542_MAILBOXES * 2 * sizeof(struct mailbox), > + &aha1542->mb_handle, GFP_KERNEL); > + if (!aha1542->mb) > goto free_dma; > > + aha1542->ccb = dma_alloc_coherent(pdev, > + AHA1542_MAILBOXES * sizeof(struct ccb), > + &aha1542->ccb_handle, GFP_KERNEL); > + if (!aha1542->ccb) > + goto free_mb; > + > + if (scsi_add_host(sh, pdev)) > + goto free_ccb; > + > scsi_scan_host(sh); > > return sh; > + > +free_ccb: > + dma_free_coherent(pdev, AHA1542_MAILBOXES * sizeof(struct ccb), > + aha1542->ccb, aha1542->ccb_handle); > +free_mb: > + dma_free_coherent(pdev, AHA1542_MAILBOXES * 2 * sizeof(struct mailbox), > + aha1542->mb, aha1542->mb_handle); > free_dma: > if (sh->dma_channel != 0xff) > free_dma(sh->dma_channel); > @@ -777,7 +812,14 @@ static struct Scsi_Host *aha1542_hw_init(struct > scsi_host_template *tpnt, struct > > static int aha1542_release(struct Scsi_Host *sh) > { > + struct aha1542_hostdata *aha1542 = shost_priv(sh); > + struct device *dev = sh->dma_dev; > + > scsi_remove_host(sh); > + dma_free_coherent(dev, AHA1542_MAILBOXES * sizeof(struct ccb), > + aha1542->ccb, aha1542->ccb_handle); > + dma_free_coherent(dev, AHA1542_MAILBOXES * 2 * sizeof(struct mailbox), > + aha1542->mb, aha1542->mb_handle); > if (sh->dma_channel != 0xff) > free_dma(sh->dma_channel); > if (sh->irq) > @@ -826,7 +868,8 @@ static int aha1542_dev_reset(struct scsi_cmnd *cmd) > > aha1542->aha1542_last_mbo_used = mbo; > > - any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets > trashed for some reason */ + /* This gets trashed for some reason */ > + any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(ccb)); > > memset(&ccb[mbo], 0, sizeof(struct ccb)); > > @@ -889,8 +932,7 @@ static int aha1542_reset(struct scsi_cmnd *cmd, u8 > reset_cmd) > > for (i = 0; i < AHA1542_MAILBOXES; i++) { > if (aha1542->int_cmds[i] != NULL) { > - struct scsi_cmnd *tmp_cmd; > - tmp_cmd = aha1542->int_cmds[i]; > + struct scsi_cmnd *tmp_cmd = aha1542->int_cmds[i]; > > if (tmp_cmd->device->soft_reset) { > /* > @@ -901,8 +943,7 @@ static int aha1542_reset(struct scsi_cmnd *cmd, u8 > reset_cmd) */ > continue; > } > - kfree(tmp_cmd->host_scribble); > - tmp_cmd->host_scribble = NULL; > + aha1542_free_cmd(tmp_cmd); > aha1542->int_cmds[i] = NULL; > aha1542->mb[i].status = 0; > } > @@ -946,6 +987,7 @@ static struct scsi_host_template driver_template = { > .module = THIS_MODULE, > .proc_name = "aha1542", > .name = "Adaptec 1542", > + .cmd_size = sizeof(struct aha1542_cmd), > .queuecommand = aha1542_queuecommand, > .eh_device_reset_handler= aha1542_dev_reset, > .eh_bus_reset_handler = aha1542_bus_reset, Doesn't seem to work: [ 159.185536] scsi host2: Adaptec AHA-1542 (SCSI-ID 7) at IO 0x330, IRQ 11, DMA 7 [ 159.262108] BUG: unable to handle kernel NULL pointer dereference at 00000000 [ 159.264103] *pde = 00000000 [ 159.264103] Oops: 0002 [#1] SMP [ 159.264103] Modules linked in: aha1542(+) sr_mod cdrom i2c_dev psmouse serio_raw 8139cp nouveau sg parport_pc parport wmi hwmon ttm intel_agp [last unloaded: aha1542] [ 159.264103] CPU: 0 PID: 1848 Comm: modprobe Not tainted 4.17.0+ #263 [ 159.264103] Hardware name: /i440ZX-W977TF, BIOS 4.51 PG 07/12/00 [ 159.264103] EIP: setup_mailboxes+0x1a/0xb5 [aha1542] [ 159.264103] EFLAGS: 00010246 CPU: 0 [ 159.264103] EAX: 00000000 EBX: c0090000 ECX: cfde2164 EDX: 00000000 [ 159.264103] ESI: c0090000 EDI: cbf07d25 EBP: cbf07d08 ESP: cbf07cf8 [ 159.264103] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 [ 159.264103] CR0: 80050033 CR2: b7e9f050 CR3: 0bc70000 CR4: 00000290 [ 159.264103] Call Trace: [ 159.264103] aha1542_hw_init.constprop.7+0x5a8/0x702 [aha1542] [ 159.264103] aha1542_isa_match+0xb/0x1e [aha1542] [ 159.264103] isa_bus_match+0x20/0x40 [ 159.264103] __device_attach_driver+0x25/0x71 [ 159.264103] bus_for_each_drv+0x5c/0x68 [ 159.264103] __device_attach+0x79/0xcd [ 159.264103] ? driver_allows_async_probing+0x28/0x28 [ 159.264103] device_initial_probe+0xd/0xf [ 159.264103] bus_probe_device+0x22/0x65 [ 159.264103] device_add+0x368/0x434 [ 159.264103] ? pm_runtime_init+0xa5/0xac [ 159.264103] device_register+0x12/0x15 [ 159.264103] isa_register_driver+0xad/0x10a [ 159.264103] ? 0xd0d24000 [ 159.264103] aha1542_init+0x33/0x1000 [aha1542] [ 159.264103] do_one_initcall+0x60/0x11f [ 159.264103] ? _cond_resched+0x1e/0x22 [ 159.264103] ? slab_pre_alloc_hook+0x25/0x35 [ 159.264103] ? do_init_module+0x17/0x1ad [ 159.264103] ? kmem_cache_alloc+0x79/0x9c [ 159.264103] ? do_init_module+0x17/0x1ad [ 159.264103] do_init_module+0x46/0x1ad [ 159.264103] load_module+0x1708/0x1b23 [ 159.264103] ? kernel_read_file+0x116/0x143 [ 159.264103] sys_finit_module+0x62/0x67 [ 159.264103] do_int80_syscall_32+0x50/0x62 [ 159.264103] entry_INT80_32+0x2a/0x2a [ 159.264103] EIP: 0xb7f66a02 [ 159.264103] EFLAGS: 00000292 CPU: 0 [ 159.264103] EAX: ffffffda EBX: 00000003 ECX: 004fa970 EDX: 00000000 [ 159.264103] ESI: 00563e30 EDI: 00563ef8 EBP: 00000000 ESP: bf9100d8 [ 159.264103] DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 007b [ 159.264103] Code: 40 54 e8 44 ff ff ff c7 43 54 00 00 00 00 5b 5d c3 55 89 e5 56 53 89 c3 83 ec 08 31 c0 c6 45 f3 01 c6 45 f4 08 8b 93 7c 04 00 00 <c6> 04 02 00 6b d0 0b 8b b3 7c 04 00 00 03 93 88 04 00 00 01 c6 [ 159.264103] EIP: setup_mailboxes+0x1a/0xb5 [aha1542] SS:ESP: 0068:cbf07cf8 [ 159.264103] CR2: 0000000000000000 [ 159.479491] ---[ end trace 139123655cd08eca ]--- -- Ondrej Zary