mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-07 03:18:31 +00:00
IB/mlx5: Simplify mlx5_ib_cont_pages
The patch simplifies mlx5_ib_cont_pages and fixes the following
issues in the original implementation:
First issues is related to alignment of the PFNs. After the check
base + p != PFN, the alignment of the PFN wasn't checked. So the PFN
sequence 0, 1, 1, 2 would result in a page_shift of 13 even though
the 3rd PFN is not 8KB aligned.
This wasn't actually a bug because it was supported by all the
existing mlx5 compatible device, but we don't want to require
this support in all future devices.
Another issue is because the inner loop didn't advance PFN so
the test "if (base + p != pfn)" always failed for SGE with
len > (1<<page_shift).
Fixes: e126ba97db
("mlx5: Add driver for Mellanox Connect-IB adapters")
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
Reviewed-by: Eli Cohen <eli@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
parent
7c9d966210
commit
d67bc5d4e3
1 changed files with 17 additions and 30 deletions
|
@ -50,13 +50,9 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr,
|
||||||
{
|
{
|
||||||
unsigned long tmp;
|
unsigned long tmp;
|
||||||
unsigned long m;
|
unsigned long m;
|
||||||
int i, k;
|
u64 base = ~0, p = 0;
|
||||||
u64 base = 0;
|
u64 len, pfn;
|
||||||
int p = 0;
|
int i = 0;
|
||||||
int skip;
|
|
||||||
int mask;
|
|
||||||
u64 len;
|
|
||||||
u64 pfn;
|
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
int entry;
|
int entry;
|
||||||
unsigned long page_shift = umem->page_shift;
|
unsigned long page_shift = umem->page_shift;
|
||||||
|
@ -76,33 +72,24 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr,
|
||||||
m = find_first_bit(&tmp, BITS_PER_LONG);
|
m = find_first_bit(&tmp, BITS_PER_LONG);
|
||||||
if (max_page_shift)
|
if (max_page_shift)
|
||||||
m = min_t(unsigned long, max_page_shift - page_shift, m);
|
m = min_t(unsigned long, max_page_shift - page_shift, m);
|
||||||
skip = 1 << m;
|
|
||||||
mask = skip - 1;
|
|
||||||
i = 0;
|
|
||||||
for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
|
for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
|
||||||
len = sg_dma_len(sg) >> page_shift;
|
len = sg_dma_len(sg) >> page_shift;
|
||||||
pfn = sg_dma_address(sg) >> page_shift;
|
pfn = sg_dma_address(sg) >> page_shift;
|
||||||
for (k = 0; k < len; k++) {
|
|
||||||
if (!(i & mask)) {
|
|
||||||
tmp = (unsigned long)pfn;
|
|
||||||
m = min_t(unsigned long, m, find_first_bit(&tmp, BITS_PER_LONG));
|
|
||||||
skip = 1 << m;
|
|
||||||
mask = skip - 1;
|
|
||||||
base = pfn;
|
|
||||||
p = 0;
|
|
||||||
} else {
|
|
||||||
if (base + p != pfn) {
|
if (base + p != pfn) {
|
||||||
tmp = (unsigned long)p;
|
/* If either the offset or the new
|
||||||
|
* base are unaligned update m
|
||||||
|
*/
|
||||||
|
tmp = (unsigned long)(pfn | p);
|
||||||
|
if (!IS_ALIGNED(tmp, 1 << m))
|
||||||
m = find_first_bit(&tmp, BITS_PER_LONG);
|
m = find_first_bit(&tmp, BITS_PER_LONG);
|
||||||
skip = 1 << m;
|
|
||||||
mask = skip - 1;
|
|
||||||
base = pfn;
|
base = pfn;
|
||||||
p = 0;
|
p = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
p++;
|
p += len;
|
||||||
i++;
|
i += len;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i) {
|
if (i) {
|
||||||
|
|
Loading…
Reference in a new issue