diff options
| author | Jack Morgenstein <jackm@dev.mellanox.co.il> | 2012-08-03 08:40:38 +0000 | 
|---|---|---|
| committer | Roland Dreier <roland@purestorage.com> | 2012-09-30 20:33:29 -0700 | 
| commit | ff7166c447df23a61e4f51bf748319dc6728dc74 (patch) | |
| tree | c37b966015832ad93661cbcbce6e2f8fb6d276c2 /drivers/infiniband/core/cache.c | |
| parent | d2b57063e4aba51d3c49ec957607d2e4c9d5f29a (diff) | |
| download | olio-linux-3.10-ff7166c447df23a61e4f51bf748319dc6728dc74.tar.xz olio-linux-3.10-ff7166c447df23a61e4f51bf748319dc6728dc74.zip  | |
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>
Diffstat (limited to 'drivers/infiniband/core/cache.c')
| -rw-r--r-- | drivers/infiniband/core/cache.c | 15 | 
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 9353992f9ee..4da381b74f5 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -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;  |