IB/core: Handle table with full and partial membership for the same P_Key
Extend the cached and non-cached P_Key table lookups to handle limited and full membership of the same P_Key to co-exist in the P_Key table. This is necessary for SR-IOV, to allow for some guests would to have the full membership P_Key in their virtual P_Key table, while other guests on the same physical HCA would have the limited one. To support this, we need both the limited and full membership P_Keys to be present in the master's (hypervisor physical port) P_Key table. The algorithm for handling P_Key tables which contain both the limited and the full membership versions of the same P_Key works as follows: When scanning the P_Key table for a 15-bit P_Key: A. If there is a full member version of that P_Key anywhere in the table, return its index (even if a limited-member version of the P_Key exists earlier in the table). B. If the full member version is not in the table, but the limited-member version is in the table, return the index of the limited P_Key. Signed-off-by: Liran Liss <liranl@mellanox.com> Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
This commit is contained in:
parent
d2b57063e4
commit
ff7166c447
2 changed files with 25 additions and 6 deletions
|
@ -167,6 +167,7 @@ int ib_find_cached_pkey(struct ib_device *device,
|
|||
unsigned long flags;
|
||||
int i;
|
||||
int ret = -ENOENT;
|
||||
int partial_ix = -1;
|
||||
|
||||
if (port_num < start_port(device) || port_num > end_port(device))
|
||||
return -EINVAL;
|
||||
|
@ -179,11 +180,19 @@ int ib_find_cached_pkey(struct ib_device *device,
|
|||
|
||||
for (i = 0; i < cache->table_len; ++i)
|
||||
if ((cache->table[i] & 0x7fff) == (pkey & 0x7fff)) {
|
||||
*index = i;
|
||||
ret = 0;
|
||||
break;
|
||||
if (cache->table[i] & 0x8000) {
|
||||
*index = i;
|
||||
ret = 0;
|
||||
break;
|
||||
} else
|
||||
partial_ix = i;
|
||||
}
|
||||
|
||||
if (ret && partial_ix >= 0) {
|
||||
*index = partial_ix;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
read_unlock_irqrestore(&device->cache.lock, flags);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -707,18 +707,28 @@ int ib_find_pkey(struct ib_device *device,
|
|||
{
|
||||
int ret, i;
|
||||
u16 tmp_pkey;
|
||||
int partial_ix = -1;
|
||||
|
||||
for (i = 0; i < device->pkey_tbl_len[port_num - start_port(device)]; ++i) {
|
||||
ret = ib_query_pkey(device, port_num, i, &tmp_pkey);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((pkey & 0x7fff) == (tmp_pkey & 0x7fff)) {
|
||||
*index = i;
|
||||
return 0;
|
||||
/* if there is full-member pkey take it.*/
|
||||
if (tmp_pkey & 0x8000) {
|
||||
*index = i;
|
||||
return 0;
|
||||
}
|
||||
if (partial_ix < 0)
|
||||
partial_ix = i;
|
||||
}
|
||||
}
|
||||
|
||||
/*no full-member, if exists take the limited*/
|
||||
if (partial_ix >= 0) {
|
||||
*index = partial_ix;
|
||||
return 0;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_find_pkey);
|
||||
|
|
Loading…
Reference in a new issue