Re: [PATCH] aha1542: convert to DMA mapping API

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

 



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



[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