Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a4309d94 authored by Sebastian Sanchez's avatar Sebastian Sanchez Committed by Doug Ledford
Browse files

IB/hfi1: Do not read more than a SGE length



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: default avatarDean Luick <dean.luick@intel.com>
Signed-off-by: default avatarSebastian Sanchez <sebastian.sanchez@intel.com>
Signed-off-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent d5cf683e
Loading
Loading
Loading
Loading
+40 −48
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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));
@@ -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;
}

/*