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

2018-11-10 Thread Christoph Hellwig
> > @@ -826,7 +881,8 @@ static int aha1542_dev_reset(struct scsi_cmnd *cmd)
> >  
> > aha1542->aha1542_last_mbo_used = mbo;
> >  
> > -   any2scsi(mb[mbo].ccbptr, isa_virt_to_bus([mbo]));   /* This gets 
> > trashed for some reason */
> > +   /* This gets trashed for some reason */
> > +   any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(ccb));
> ^^^
> This looks wrong too. It's the same code as in aha1542_queuecommand.

Indeed, I'll resend.


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

2018-11-09 Thread Ondrej Zary
On Friday 09 November 2018 16:45:54 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.
> 
> Thanks to Ondrej Zary for testing and finding and fixing a crucial
> bug.
> 
> Signed-off-by: Christoph Hellwig 
> Tested-by: Ondrej Zary 
> ---
>  drivers/scsi/aha1542.c | 126 +
>  1 file changed, 91 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
> index 41add33e3f1f..398fcdc6f4c9 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,21 @@ 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;
> + size_t len = scsi_sg_count(cmd) * sizeof(struct chain);
> +
> + if (acmd->chain) {
> + dma_unmap_single(dev, acmd->chain_handle, len, DMA_TO_DEVICE);
> + kfree(acmd->chain);
> + }
> +
> + 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 +325,7 @@ static irqreturn_t aha1542_interrupt(int irq, void 
> *dev_id)
>   return IRQ_HANDLED;
>   };
>  
> - mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus([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 +353,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 +390,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 +400,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 +419,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)
> - return SCSI_MLQUEUE_HOST_BUSY;
> - } else {
> - sg_count = 0;
> - cptr = NULL;
> + sg_count = scsi_dma_map(cmd);
> + if (sg_count) {
> + size_t len = sg_count * sizeof(struct chain);
> +
> + acmd->chain = kmalloc(len, GFP_DMA);
> + if (!acmd->chain)
> + goto out_unmap;
> + acmd->chain_handle = dma_map_single(sh->dma_dev, acmd->chain,
> + len, DMA_TO_DEVICE);
> + if (dma_mapping_error(sh->dma_dev, acmd->chain_handle))
> + goto out_free_chain;
>   }
>  
>   /* 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)
>   shost_printk(KERN_DEBUG, sh, "Sending command 

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

2018-10-21 Thread Ondrej Zary
On Thursday 09 August 2018 07:35:33 Christoph Hellwig wrote:
> On Wed, Aug 08, 2018 at 10:30:19PM +0200, Ondrej Zary wrote:
> > Then it crashes with null-pointer dereference in aha1542_reset.
> 
> Must be the dma_unmap.  Updated patch below:
> 
> ---
> From 98a9c770430cde972923838b990b2b9cf7b95816 Mon Sep 17 00:00:00 2001
> From: Christoph Hellwig 
> Date: Thu, 2 Aug 2018 14:22:46 +0200
> Subject: 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.
> 
> Signed-off-by: Christoph Hellwig 
> ---
>  drivers/scsi/aha1542.c | 126 +
>  1 file changed, 91 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
> index 41add33e3f1f..d09e19dde177 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,21 @@ 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;
> + size_t len = scsi_sg_count(cmd) * sizeof(struct chain);
> +
> + if (acmd->chain) {
> + dma_unmap_single(dev, acmd->chain_handle, len, DMA_TO_DEVICE);
> + kfree(acmd->chain);
> + }
> +
> + 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 +325,7 @@ static irqreturn_t aha1542_interrupt(int irq, void 
> *dev_id)
>   return IRQ_HANDLED;
>   };
>  
> - mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus([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 +353,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 +390,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 +400,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 +419,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)
> - return SCSI_MLQUEUE_HOST_BUSY;
> - } else {
> - sg_count = 0;
> - cptr = NULL;
> + sg_count = scsi_dma_map(cmd);
> + if (sg_count) {
> + size_t len = sg_count * sizeof(struct chain);
> +
> + acmd->chain = kmalloc(len, GFP_DMA);
> + if (!acmd->chain)
> + goto out_unmap;
> + acmd->chain_handle = dma_map_single(sh->dma_dev, acmd->chain,
> + len, DMA_TO_DEVICE);
> + if (dma_mapping_error(sh->dma_dev, acmd->chain_handle))
> +

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

2018-08-09 Thread Ondrej Zary
On Thursday 09 August 2018 07:35:33 Christoph Hellwig wrote:
> On Wed, Aug 08, 2018 at 10:30:19PM +0200, Ondrej Zary wrote:
> > Then it crashes with null-pointer dereference in aha1542_reset.
>
> Must be the dma_unmap.  Updated patch below:

No change in behavior, unfortunately. The crash is probably just a result of 
the bad things that happen before, starting with:
scsi host2: Unexpected interrupt

-- 
Ondrej Zary


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

2018-08-08 Thread Christoph Hellwig
On Wed, Aug 08, 2018 at 10:30:19PM +0200, Ondrej Zary wrote:
> Then it crashes with null-pointer dereference in aha1542_reset.

Must be the dma_unmap.  Updated patch below:

---
>From 98a9c770430cde972923838b990b2b9cf7b95816 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig 
Date: Thu, 2 Aug 2018 14:22:46 +0200
Subject: 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.

Signed-off-by: Christoph Hellwig 
---
 drivers/scsi/aha1542.c | 126 +
 1 file changed, 91 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 41add33e3f1f..d09e19dde177 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,21 @@ 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;
+   size_t len = scsi_sg_count(cmd) * sizeof(struct chain);
+
+   if (acmd->chain) {
+   dma_unmap_single(dev, acmd->chain_handle, len, DMA_TO_DEVICE);
+   kfree(acmd->chain);
+   }
+
+   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 +325,7 @@ static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
};
 
-   mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus([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 +353,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 +390,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 +400,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 +419,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)
-   return SCSI_MLQUEUE_HOST_BUSY;
-   } else {
-   sg_count = 0;
-   cptr = NULL;
+   sg_count = scsi_dma_map(cmd);
+   if (sg_count) {
+   size_t len = sg_count * sizeof(struct chain);
+
+   acmd->chain = kmalloc(len, GFP_DMA);
+   if (!acmd->chain)
+   goto out_unmap;
+   acmd->chain_handle = dma_map_single(sh->dma_dev, acmd->chain,
+   len, DMA_TO_DEVICE);
+   if (dma_mapping_error(sh->dma_dev, acmd->chain_handle))
+   goto out_free_chain;
}
 
/* Use the outgoing mailboxes in a round-robin fashion, because this
@@ -437,7 +460,8 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, 

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

2018-08-08 Thread Christoph Hellwig
On Wed, Aug 08, 2018 at 06:26:25PM +0200, Ondrej Zary wrote:
> Looks like you attached wrong file (same as the previous one).

This should be better:

---
>From afa1c18bd98168fb690d905fc84a2db6f0d617b6 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig 
Date: Thu, 2 Aug 2018 14:22:46 +0200
Subject: 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.

Signed-off-by: Christoph Hellwig 
---
 drivers/scsi/aha1542.c | 126 +
 1 file changed, 89 insertions(+), 37 deletions(-)

diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 41add33e3f1f..d5385eb3a7a4 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,18 @@ 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;
+   size_t len = scsi_sg_count(cmd) * sizeof(struct chain);
+
+   dma_unmap_single(dev, acmd->chain_handle, len, DMA_TO_DEVICE);
+   kfree(acmd->chain);
+   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 +322,7 @@ static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
};
 
-   mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus([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 +350,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 +387,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 +397,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 +416,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)
-   return SCSI_MLQUEUE_HOST_BUSY;
-   } else {
-   sg_count = 0;
-   cptr = NULL;
+   sg_count = scsi_dma_map(cmd);
+   if (sg_count) {
+   size_t len = sg_count * sizeof(struct chain);
+
+   acmd->chain = kmalloc(len, GFP_DMA);
+   if (!acmd->chain)
+   goto out_unmap;
+   acmd->chain_handle = dma_map_single(sh->dma_dev, acmd->chain,
+   len, DMA_TO_DEVICE);
+   if (dma_mapping_error(sh->dma_dev, acmd->chain_handle))
+   goto out_free_chain;
}
 
/* Use the outgoing mailboxes in a round-robin fashion, because this
@@ -437,7 +457,8 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, 
struct scsi_cmnd *cmd)
shost_printk(KERN_DEBUG, sh, "Sending command 

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

2018-08-08 Thread Ondrej Zary
On Wednesday 08 August 2018 11:14:33 Christoph Hellwig wrote:
> On Tue, Aug 07, 2018 at 07:30:17PM +0200, Ondrej Zary wrote:
> > On Tuesday 07 August 2018 09:29:59 Christoph Hellwig wrote:
> > > Looks like the dma allocation is too late.  Updated version below:
> > >
> > > ...
> >
> > Crashes a bit later now:
>
> Next try:
>
> ---
> From 9dd7a3eb89d1cc72c001daeb80e44de7c5fb5b00 Mon Sep 17 00:00:00 2001
> From: Christoph Hellwig 
> Date: Thu, 2 Aug 2018 14:22:46 +0200
> Subject: aha1542: convert to DMA mapping API

Looks like you attached wrong file (same as the previous one).

-- 
Ondrej Zary


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

2018-08-08 Thread Christoph Hellwig
On Tue, Aug 07, 2018 at 07:30:17PM +0200, Ondrej Zary wrote:
> On Tuesday 07 August 2018 09:29:59 Christoph Hellwig wrote:
> > Looks like the dma allocation is too late.  Updated version below:
> >
> > ...
> 
> Crashes a bit later now:

Next try:

---
>From 9dd7a3eb89d1cc72c001daeb80e44de7c5fb5b00 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig 
Date: Thu, 2 Aug 2018 14:22:46 +0200
Subject: 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.

Signed-off-by: Christoph Hellwig 
---
 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..fb9c8fdb5a09 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([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),
+   >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
 
- 

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

2018-08-07 Thread Ondrej Zary
On Tuesday 07 August 2018 09:29:59 Christoph Hellwig wrote:
> Looks like the dma allocation is too late.  Updated version below:
>
> ...

Crashes a bit later now:

[   89.270529] scsi host2: Adaptec AHA-1542 (SCSI-ID 7) at IO 0x330, IRQ 11, 
DMA 7
[   89.346535] scsi host2: Adaptec 1542
[   89.358411] bounce: isa pool size: 16 pages
[   89.627133] WARNING: CPU: 0 PID: 0 at ./include/linux/dma-mapping.h:541 
dma_free_attrs.constprop.8+0x29/0x76 [aha1542]
[   89.630753] Modules linked in: aha1542 i2c_dev nouveau psmouse serio_raw sg 
8139cp wmi hwmon ttm parport_pc parport intel_agp
[   89.630753] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.17.0+ #263
[   89.630753] Hardware name:  /i440ZX-W977TF, BIOS 4.51 PG 07/12/00
[   89.630753] EIP: dma_free_attrs.constprop.8+0x29/0x76 [aha1542]
[   89.630753] EFLAGS: 00010086 CPU: 0
[   89.630753] EAX: cfbda200 EBX: 0086 ECX: c008d000 EDX: 0006
[   89.630753] ESI:  EDI: cf514aa0 EBP: cf80df64 ESP: cf80df54
[   89.630753]  DS: 007b ES: 007b FS: 00d8 GS:  SS: 0068
[   89.630753] CR0: 80050033 CR2: d0d3b000 CR3: 0fbad000 CR4: 0290
[   89.630753] Call Trace:
[   89.630753]  
[   89.630753]  aha1542_free_cmd+0x29/0x40 [aha1542]
[   89.630753]  aha1542_interrupt+0x1be/0x267 [aha1542]
[   89.630753]  ? scsi_dev_queue_ready+0x7f/0x7f
[   89.630753]  __handle_irq_event_percpu+0x2f/0xb4
[   89.630753]  ? irq_set_chained_handler_and_data+0x4a/0x4a
[   89.630753]  handle_irq_event_percpu+0x17/0x3d
[   89.630753]  handle_irq_event+0x22/0x3b
[   89.630753]  handle_level_irq+0x55/0x7a
[   89.630753]  handle_irq+0x6c/0x81
[   89.630753]  
[   89.630753]  do_IRQ+0x35/0x95
[   89.630753]  ? acpi_idle_enter_s2idle+0x41/0x41
[   89.630753]  common_interrupt+0x34/0x3c
[   89.630753] EIP: cpuidle_enter_state+0xca/0x125
[   89.630753] EFLAGS: 0246 CPU: 0
[   89.630753] EAX: de2b83d5 EBX:  ECX: 0014 EDX: cfde46e0
[   89.630753] ESI: 0002 EDI: cf213c80 EBP: cf661f48 ESP: cf661f28
[   89.630753]  DS: 007b ES: 007b FS: 00d8 GS:  SS: 0068
[   89.630753]  ? acpi_idle_enter_s2idle+0x41/0x41
[   89.630753]  cpuidle_enter+0xf/0x12
[   89.630753]  do_idle+0x162/0x1b1
[   89.630753]  cpu_startup_entry+0x19/0x1b
[   89.630753]  rest_init+0x8c/0x8e
[   89.630753]  start_kernel+0x306/0x30b
[   89.630753]  i386_start_kernel+0x95/0x99
[   89.630753]  startup_32_smp+0x15f/0x164
[   89.630753] Code: 5d c3 55 85 c0 89 e5 57 56 53 53 74 0a 8b b8 20 01 00 00 
85 ff 75 0c 8b 3d 08 aa 66 cf 85 ff 75 02 0f 0b 9c 5b 0f ba e3 09 72 02 <0f> 0b 
89 45 f0 8d 42 ff 89 cb c1 e8 0c 83 c9 ff 89 d6 0f bd d0 
[   89.630753] ---[ end trace 3524d2ff63a5e038 ]---
[   90.240799] scsi host2: Unexpected interrupt
[   90.244724] scsi host2: tarstat=0, hastat=11 idlun=0 ccb#=0
[  100.293508] systemd-logind[1782]: Failed to start user service, ignoring: 
Unknown unit: user@0.service
[  100.416746] systemd-logind[1782]: New session c2 of user root.
[  111.096323] scsi 2:0:1:0: tag#0 Trying device reset for target
[  111.105632] scsi 2:0:1:0: tag#0 Trying device reset for target
[  111.114020] scsi host2: Sent BUS RESET to scsi host 2
[  111.114020] WARNING: CPU: 0 PID: 1821 at ./include/linux/dma-mapping.h:541 
dma_free_attrs.constprop.8+0x29/0x76 [aha1542]
[  111.114020] Modules linked in: aha1542 i2c_dev nouveau psmouse serio_raw sg 
8139cp wmi hwmon ttm parport_pc parport intel_agp
[  111.114020] CPU: 0 PID: 1821 Comm: scsi_eh_2 Tainted: GW 
4.17.0+ #263
[  111.114020] Hardware name:  /i440ZX-W977TF, BIOS 4.51 PG 07/12/00
[  111.114020] EIP: dma_free_attrs.constprop.8+0x29/0x76 [aha1542]
[  111.114020] EFLAGS: 00010086 CPU: 0
[  111.114020] EAX: cfbda200 EBX: 0086 ECX:  EDX: 0006
[  111.114020] ESI: c009 EDI: cf514aa0 EBP: cbe89ebc ESP: cbe89eac
[  111.114020]  DS: 007b ES: 007b FS: 00d8 GS:  SS: 0068
[  111.114020] CR0: 80050033 CR2: 0817ae44 CR3: 0bc2c000 CR4: 0290
[  111.114020] Call Trace:
[  111.114020]  aha1542_free_cmd+0x29/0x40 [aha1542]
[  111.114020]  aha1542_reset+0xb0/0xe5 [aha1542]
[  111.114020]  aha1542_bus_reset+0xd/0xf [aha1542]
[  111.114020]  scsi_try_bus_reset+0x4b/0x94
[  111.114020]  scsi_eh_ready_devs+0x5a4/0x781
[  111.114020]  scsi_error_handler+0x268/0x4b0
[  111.114020]  ? __schedule+0x38f/0x3dd
[  111.114020]  kthread+0xcc/0xce
[  111.114020]  ? scsi_eh_get_sense+0x16e/0x16e
[  111.114020]  ? kthread_cancel_delayed_work_sync+0xf/0xf
[  111.114020]  ret_from_fork+0x2e/0x38
[  111.114020] Code: 5d c3 55 85 c0 89 e5 57 56 53 53 74 0a 8b b8 20 01 00 00 
85 ff 75 0c 8b 3d 08 aa 66 cf 85 ff 75 02 0f 0b 9c 5b 0f ba e3 09 72 02 <0f> 0b 
89 45 f0 8d 42 ff 89 cb c1 e8 0c 83 c9 ff 89 d6 0f bd d0 
[  111.114020] ---[ end trace 3524d2ff63a5e039 ]---
[  111.114020] WARNING: CPU: 0 PID: 1821 at ./include/linux/dma-mapping.h:541 
dma_free_attrs.constprop.8+0x29/0x76 [aha1542]
[  111.114020] Modules linked in: aha1542 i2c_dev nouveau psmouse serio_raw sg 
8139cp wmi hwmon ttm parport_pc parport intel_agp
[  111.114020] CPU: 0 

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

2018-08-07 Thread Christoph Hellwig
Looks like the dma allocation is too late.  Updated version below:

---
>From 9dd7a3eb89d1cc72c001daeb80e44de7c5fb5b00 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig 
Date: Thu, 2 Aug 2018 14:22:46 +0200
Subject: 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.

Signed-off-by: Christoph Hellwig 
---
 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..fb9c8fdb5a09 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([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),
+   >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([mbo]));   /* This gets 
trashed for some reason */
+   /* This gets trashed for some reason */
+   any2scsi(mb[mbo].ccbptr, 

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

2018-08-06 Thread Ondrej Zary
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 
> ---
>  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([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),
> + >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([mbo]));   /* This gets
> trashed for some reason */ +  /* This gets trashed for some reason */
> + any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(ccb));
>
>   memset([mbo], 0, sizeof(struct ccb));
>
> @@ -456,21 +476,18 @@ static int aha1542_queuecommand(struct Scsi_Host *sh,
> struct scsi_cmnd *cmd) int i;
>
>