lkml.org 
[lkml]   [2006]   [Feb]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[git patches] libata fixes

    Please pull from 'upstream-fixes' branch of
    master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

    to receive the following updates:

    drivers/scsi/libata-core.c | 15 +++++++++------
    drivers/scsi/sata_qstor.c | 2 +-
    include/linux/libata.h | 16 ++++++++++++++--
    3 files changed, 24 insertions(+), 9 deletions(-)

    Tejun Heo:
    libata: fix WARN_ON() condition in *_fill_sg()
    libata: fix qc->n_elem == 0 case handling in ata_qc_next_sg
    libata: make ata_sg_setup_one() trim zero length sg

    diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
    index 7ddd5a6..5f1d758 100644
    --- a/drivers/scsi/libata-core.c
    +++ b/drivers/scsi/libata-core.c
    @@ -2514,7 +2514,7 @@ static void ata_sg_clean(struct ata_queu
    assert(sg != NULL);

    if (qc->flags & ATA_QCFLAG_SINGLE)
    - assert(qc->n_elem == 1);
    + assert(qc->n_elem <= 1);

    VPRINTK("unmapping %u sg elements\n", qc->n_elem);

    @@ -2537,7 +2537,7 @@ static void ata_sg_clean(struct ata_queu
    kunmap_atomic(addr, KM_IRQ0);
    }
    } else {
    - if (sg_dma_len(&sg[0]) > 0)
    + if (qc->n_elem)
    dma_unmap_single(ap->host_set->dev,
    sg_dma_address(&sg[0]), sg_dma_len(&sg[0]),
    dir);
    @@ -2570,7 +2570,7 @@ static void ata_fill_sg(struct ata_queue
    unsigned int idx;

    assert(qc->__sg != NULL);
    - assert(qc->n_elem > 0);
    + assert(qc->n_elem > 0 || qc->pad_len > 0);

    idx = 0;
    ata_for_each_sg(sg, qc) {
    @@ -2715,6 +2715,7 @@ static int ata_sg_setup_one(struct ata_q
    int dir = qc->dma_dir;
    struct scatterlist *sg = qc->__sg;
    dma_addr_t dma_address;
    + int trim_sg = 0;

    /* we must lengthen transfers to end on a 32-bit boundary */
    qc->pad_len = sg->length & 3;
    @@ -2734,13 +2735,15 @@ static int ata_sg_setup_one(struct ata_q
    sg_dma_len(psg) = ATA_DMA_PAD_SZ;
    /* trim sg */
    sg->length -= qc->pad_len;
    + if (sg->length == 0)
    + trim_sg = 1;

    DPRINTK("padding done, sg->length=%u pad_len=%u\n",
    sg->length, qc->pad_len);
    }

    - if (!sg->length) {
    - sg_dma_address(sg) = 0;
    + if (trim_sg) {
    + qc->n_elem--;
    goto skip_map;
    }

    @@ -2753,9 +2756,9 @@ static int ata_sg_setup_one(struct ata_q
    }

    sg_dma_address(sg) = dma_address;
    -skip_map:
    sg_dma_len(sg) = sg->length;

    +skip_map:
    DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
    qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");

    diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
    index de05e28..80480f0 100644
    --- a/drivers/scsi/sata_qstor.c
    +++ b/drivers/scsi/sata_qstor.c
    @@ -277,7 +277,7 @@ static unsigned int qs_fill_sg(struct at
    u8 *prd = pp->pkt + QS_CPB_BYTES;

    assert(qc->__sg != NULL);
    - assert(qc->n_elem > 0);
    + assert(qc->n_elem > 0 || qc->pad_len > 0);

    nelem = 0;
    ata_for_each_sg(sg, qc) {
    diff --git a/include/linux/libata.h b/include/linux/libata.h
    index 9e5db29..c91be5e 100644
    --- a/include/linux/libata.h
    +++ b/include/linux/libata.h
    @@ -557,17 +557,29 @@ ata_sg_is_last(struct scatterlist *sg, s
    }

    static inline struct scatterlist *
    +ata_qc_first_sg(struct ata_queued_cmd *qc)
    +{
    + if (qc->n_elem)
    + return qc->__sg;
    + if (qc->pad_len)
    + return &qc->pad_sgent;
    + return NULL;
    +}
    +
    +static inline struct scatterlist *
    ata_qc_next_sg(struct scatterlist *sg, struct ata_queued_cmd *qc)
    {
    if (sg == &qc->pad_sgent)
    return NULL;
    if (++sg - qc->__sg < qc->n_elem)
    return sg;
    - return qc->pad_len ? &qc->pad_sgent : NULL;
    + if (qc->pad_len)
    + return &qc->pad_sgent;
    + return NULL;
    }

    #define ata_for_each_sg(sg, qc) \
    - for (sg = qc->__sg; sg; sg = ata_qc_next_sg(sg, qc))
    + for (sg = ata_qc_first_sg(qc); sg; sg = ata_qc_next_sg(sg, qc))

    static inline unsigned int ata_tag_valid(unsigned int tag)
    {
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2006-02-21 06:19    [W:0.027 / U:128.140 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site