mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Grant Grundler" <grundler@google.com>
To: "Stefan Richter" <stefanr@s5r6.in-berlin.de>
Cc: linux1394-devel@lists.sourceforge.net,
	"FUJITA Tomonori" <fujita.tomonori@lab.ntt.co.jp>,
	linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] firewire: fw-sbp2: enforce s/g segment size limit
Date: Mon, 11 Aug 2008 12:52:19 -0700	[thread overview]
Message-ID: <da824cf30808111252m1decf08fk7ce3405105e1ceef@mail.gmail.com> (raw)
In-Reply-To: <tkrat.fa7d9c31f0c263fb@s5r6.in-berlin.de>

On Sat, Aug 9, 2008 at 11:21 AM, Stefan Richter
<stefanr@s5r6.in-berlin.de> wrote:
> 1. We don't need to round the SBP-2 segment size limit down to a
>   multiple of 4 kB (0xffff -> 0xf000).  It is only necessary to
>   ensure quadlet alignment (0xffff -> 0xfffc).
>
> 2. Use dma_set_max_seg_size() to tell the DMA mapping infrastructure
>   and the block IO layer about the restriction.  This way we can
>   remove the size checks and segment splitting in the queuecommand
>   path.
>
>   This assumes that no other code in the firewire stack uses
>   dma_map_sg() with conflicting requirements.  It furthermore assumes
>   that the controller device's platform actually allows us to set the
>   segment size to our liking.  Assert the latter with a BUG_ON().
>
> 3. Also use blk_queue_max_segment_size() to tell the block IO layer
>   about it.  It cannot know it because our scsi_add_host() does not
>   point to the FireWire controller's device.
>
> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
> ---
>  drivers/firewire/fw-sbp2.c |   68 +++++++++++++++++--------------------
>  1 file changed, 33 insertions(+), 35 deletions(-)
>
> Index: linux-2.6.27-rc2/drivers/firewire/fw-sbp2.c
> ===================================================================
> --- linux-2.6.27-rc2.orig/drivers/firewire/fw-sbp2.c
> +++ linux-2.6.27-rc2/drivers/firewire/fw-sbp2.c
> @@ -29,6 +29,7 @@
>  */
>
>  #include <linux/blkdev.h>
> +#include <linux/bug.h>
>  #include <linux/delay.h>
>  #include <linux/device.h>
>  #include <linux/dma-mapping.h>
> @@ -181,10 +182,16 @@ struct sbp2_target {
>  #define SBP2_MAX_LOGIN_ORB_TIMEOUT     40000U  /* Timeout in ms */
>  #define SBP2_ORB_TIMEOUT               2000U   /* Timeout in ms */
>  #define SBP2_ORB_NULL                  0x80000000
> -#define SBP2_MAX_SG_ELEMENT_LENGTH     0xf000
>  #define SBP2_RETRY_LIMIT               0xf             /* 15 retries */
>  #define SBP2_CYCLE_LIMIT               (0xc8 << 12)    /* 200 125us cycles */
>
> +/*
> + * The default maximum s/g segment size of a FireWire controller is
> + * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
> + * be quadlet-aligned, we set the length limit to 0xffff & ~3.
> + */
> +#define SBP2_MAX_SEG_SIZE              0xfffc
> +
>  /* Unit directory keys */
>  #define SBP2_CSR_UNIT_CHARACTERISTICS  0x3a
>  #define SBP2_CSR_FIRMWARE_REVISION     0x3c
> @@ -1099,6 +1106,10 @@ static int sbp2_probe(struct device *dev
>        struct Scsi_Host *shost;
>        u32 model, firmware_revision;
>
> +       if (dma_get_max_seg_size(device->card->device) > SBP2_MAX_SEG_SIZE)
> +               BUG_ON(dma_set_max_seg_size(device->card->device,
> +                                           SBP2_MAX_SEG_SIZE));
> +
>        shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt));
>        if (shost == NULL)
>                return -ENOMEM;
> @@ -1347,14 +1358,12 @@ static int
>  sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
>                     struct sbp2_logical_unit *lu)
>  {
> -       struct scatterlist *sg;
> -       int sg_len, l, i, j, count;
> -       dma_addr_t sg_addr;
> -
> -       sg = scsi_sglist(orb->cmd);
> -       count = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
> -                          orb->cmd->sc_data_direction);
> -       if (count == 0)
> +       struct scatterlist *sg = scsi_sglist(orb->cmd);
> +       int i, j, len;
> +
> +       i = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
> +                      orb->cmd->sc_data_direction);
> +       if (i == 0)
>                goto fail;
>
>        /*
> @@ -1364,7 +1373,7 @@ sbp2_map_scatterlist(struct sbp2_command
>         * as the second generation iPod which doesn't support page
>         * tables.
>         */
> -       if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) {
> +       if (i == 1) {
>                orb->request.data_descriptor.high =
>                        cpu_to_be32(lu->tgt->address_high);
>                orb->request.data_descriptor.low  =
> @@ -1374,29 +1383,15 @@ sbp2_map_scatterlist(struct sbp2_command
>                return 0;
>        }
>
> -       /*
> -        * Convert the scatterlist to an sbp2 page table.  If any
> -        * scatterlist entries are too big for sbp2, we split them as we
> -        * go.  Even if we ask the block I/O layer to not give us sg
> -        * elements larger than 65535 bytes, some IOMMUs may merge sg elements
> -        * during DMA mapping, and Linux currently doesn't prevent this.
> -        */
> -       for (i = 0, j = 0; i < count; i++, sg = sg_next(sg)) {
> -               sg_len = sg_dma_len(sg);
> -               sg_addr = sg_dma_address(sg);
> -               while (sg_len) {
> -                       /* FIXME: This won't get us out of the pinch. */
> -                       if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
> -                               fw_error("page table overflow\n");
> -                               goto fail_page_table;
> -                       }
> -                       l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
> -                       orb->page_table[j].low = cpu_to_be32(sg_addr);
> -                       orb->page_table[j].high = cpu_to_be32(l << 16);

I didn't check the rest of the driver - but it would be good if it
explicitly called dma_set_mask() or  pci_dma_set_mask() with a 32-bit
mask value. Most drivers assume 32-bit and that's why I point this
out.

The rest looks ok at first glance.

thanks,
grant

> -                       sg_addr += l;
> -                       sg_len -= l;
> -                       j++;
> -               }
> +       j = 0;
> +       for_each_sg(sg, sg, scsi_sg_count(orb->cmd), i) {
> +               len = sg_dma_len(sg);
> +               if (len == 0)
> +                       continue;
> +
> +               orb->page_table[j].high = cpu_to_be32(len << 16);
> +               orb->page_table[j].low = cpu_to_be32(sg_dma_address(sg));
> +               j++;
>        }
>
>        orb->page_table_bus =
> @@ -1420,8 +1415,9 @@ sbp2_map_scatterlist(struct sbp2_command
>        return 0;
>
>  fail_page_table:
> -       dma_unmap_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
> -                    orb->cmd->sc_data_direction);
> +       orb->page_table_bus = 0;
> +       dma_unmap_sg(device->card->device, scsi_sglist(orb->cmd),
> +                    scsi_sg_count(orb->cmd), orb->cmd->sc_data_direction);
>  fail:
>        return -ENOMEM;
>  }
> @@ -1542,6 +1538,8 @@ static int sbp2_scsi_slave_configure(str
>        if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
>                blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
>
> +       blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
> +
>        return 0;
>  }
>
>
> --
> Stefan Richter
> -=====-==--- =--- -=--=
> http://arcgraph.de/sr/
>
>

  reply	other threads:[~2008-08-11 19:52 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-08 19:44 Scatter-gather segment merges by IOMMU? Stefan Richter
2008-08-08 20:25 ` Grant Grundler
2008-08-08 21:21   ` Stefan Richter
2008-08-08 21:31     ` FUJITA Tomonori
2008-08-08 21:58       ` Stefan Richter
2008-08-08 22:17         ` FUJITA Tomonori
2008-08-09 18:20           ` [PATCH] ieee1394: sbp2: enforce s/g segment size limit Stefan Richter
2008-08-09 18:21             ` [PATCH] firewire: fw-sbp2: " Stefan Richter
2008-08-11 19:52               ` Grant Grundler [this message]
2008-08-13  9:38                 ` Stefan Richter
2008-08-12 17:04             ` [PATCH] ieee1394: sbp2: " Grant Grundler
2008-08-12 23:44               ` FUJITA Tomonori
2008-08-13 10:19                 ` [PATCH update] " Stefan Richter
2008-08-13 10:20                   ` [PATCH update] firewire: fw-sbp2: " Stefan Richter
2008-08-13 10:27                   ` [PATCH update] ieee1394: sbp2: " Stefan Richter
2008-08-14  0:55                   ` FUJITA Tomonori
2008-08-14  7:12                     ` Stefan Richter
2008-08-14  7:21                       ` FUJITA Tomonori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=da824cf30808111252m1decf08fk7ce3405105e1ceef@mail.gmail.com \
    --to=grundler@google.com \
    --cc=fujita.tomonori@lab.ntt.co.jp \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=linux1394-devel@lists.sourceforge.net \
    --cc=stefanr@s5r6.in-berlin.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®