Skip to content

Commit

Permalink
IB/hfi1: Do not read more than a SGE length
Browse files Browse the repository at this point in the history
In certain cases, if the tail of an SGE is not
8-byte aligned, bytes beyond the end to an 8-byte
alignment can be read. Change the copy routine
to avoid the over-read. Instead, stop on the final
whole quad-word, then read the remaining bytes.

Reviewed-by: Dean Luick <dean.luick@intel.com>
Signed-off-by: Sebastian Sanchez <sebastian.sanchez@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
  • Loading branch information
Sebastian Sanchez authored and Doug Ledford committed Oct 2, 2016
1 parent d5cf683 commit a4309d9
Showing 1 changed file with 40 additions and 48 deletions.
88 changes: 40 additions & 48 deletions drivers/infiniband/hw/hfi1/pio_copy.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,30 +253,6 @@ static inline void read_extra_bytes(struct pio_buf *pbuf,
}
}

/*
* Zero extra bytes from the end of pbuf->carry.
*
* NOTES:
* o zbytes <= old_bytes
*/
static inline void zero_extra_bytes(struct pio_buf *pbuf, unsigned int zbytes)
{
unsigned int remaining;

if (zbytes == 0) /* nothing to do */
return;

remaining = pbuf->carry_bytes - zbytes; /* remaining bytes */

/* NOTE: zshift only guaranteed to work if remaining != 0 */
if (remaining)
pbuf->carry.val64 = (pbuf->carry.val64 << zshift(remaining))
>> zshift(remaining);
else
pbuf->carry.val64 = 0;
pbuf->carry_bytes = remaining;
}

/*
* Write a quad word using parts of pbuf->carry and the next 8 bytes of src.
* Put the unused part of the next 8 bytes of src into the LSB bytes of
Expand Down Expand Up @@ -384,20 +360,6 @@ static inline void read_extra_bytes(struct pio_buf *pbuf,
pbuf->carry_bytes += nbytes;
}

/*
* Zero extra bytes from the end of pbuf->carry.
*
* We do not care about the value of unused bytes in carry, so just
* reduce the byte count.
*
* NOTES:
* o zbytes <= old_bytes
*/
static inline void zero_extra_bytes(struct pio_buf *pbuf, unsigned int zbytes)
{
pbuf->carry_bytes -= zbytes;
}

/*
* Write a quad word using parts of pbuf->carry and the next 8 bytes of src.
* Put the unused part of the next 8 bytes of src into the low bytes of
Expand Down Expand Up @@ -550,8 +512,8 @@ static void mid_copy_mix(struct pio_buf *pbuf, const void *from, size_t nbytes)
{
void __iomem *dest = pbuf->start + (pbuf->qw_written * sizeof(u64));
void __iomem *dend; /* 8-byte data end */
unsigned long qw_to_write = (pbuf->carry_bytes + nbytes) >> 3;
unsigned long bytes_left = (pbuf->carry_bytes + nbytes) & 0x7;
unsigned long qw_to_write = nbytes >> 3;
unsigned long bytes_left = nbytes & 0x7;

/* calculate 8-byte data end */
dend = dest + (qw_to_write * sizeof(u64));
Expand Down Expand Up @@ -621,16 +583,46 @@ static void mid_copy_mix(struct pio_buf *pbuf, const void *from, size_t nbytes)
dest += sizeof(u64);
}

/* adjust carry */
if (pbuf->carry_bytes < bytes_left) {
/* need to read more */
read_extra_bytes(pbuf, from, bytes_left - pbuf->carry_bytes);
pbuf->qw_written += qw_to_write;

/* handle carry and left-over bytes */
if (pbuf->carry_bytes + bytes_left >= 8) {
unsigned long nread;

/* there is enough to fill another qw - fill carry */
nread = 8 - pbuf->carry_bytes;
read_extra_bytes(pbuf, from, nread);

/*
* One more write - but need to make sure dest is correct.
* Check for wrap and the possibility the write
* should be in SOP space.
*
* The two checks immediately below cannot both be true, hence
* the else. If we have wrapped, we cannot still be within the
* first block. Conversely, if we are still in the first block,
* we cannot have wrapped. We do the wrap check first as that
* is more likely.
*/
/* adjust if we have wrapped */
if (dest >= pbuf->end)
dest -= pbuf->size;
/* jump to the SOP range if within the first block */
else if (pbuf->qw_written < PIO_BLOCK_QWS)
dest += SOP_DISTANCE;

/* flush out full carry */
carry8_write8(pbuf->carry, dest);
pbuf->qw_written++;

/* now adjust and read the rest of the bytes into carry */
bytes_left -= nread;
from += nread; /* from is now not aligned */
read_low_bytes(pbuf, from, bytes_left);
} else {
/* remove invalid bytes */
zero_extra_bytes(pbuf, pbuf->carry_bytes - bytes_left);
/* not enough to fill another qw, append the rest to carry */
read_extra_bytes(pbuf, from, bytes_left);
}

pbuf->qw_written += qw_to_write;
}

/*
Expand Down

0 comments on commit a4309d9

Please sign in to comment.