diff options
author | Jack Morgenstein <jackm@dev.mellanox.co.il> | 2012-08-03 04:40:38 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2012-09-30 23:33:29 -0400 |
commit | ff7166c447df23a61e4f51bf748319dc6728dc74 (patch) | |
tree | c37b966015832ad93661cbcbce6e2f8fb6d276c2 /drivers/infiniband | |
parent | d2b57063e4aba51d3c49ec957607d2e4c9d5f29a (diff) |
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')
-rw-r--r-- | drivers/infiniband/core/cache.c | 15 | ||||
-rw-r--r-- | drivers/infiniband/core/device.c | 16 |
2 files changed, 25 insertions, 6 deletions
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 9353992f9eea..4da381b74f54 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, | |||
167 | unsigned long flags; | 167 | unsigned long flags; |
168 | int i; | 168 | int i; |
169 | int ret = -ENOENT; | 169 | int ret = -ENOENT; |
170 | int partial_ix = -1; | ||
170 | 171 | ||
171 | if (port_num < start_port(device) || port_num > end_port(device)) | 172 | if (port_num < start_port(device) || port_num > end_port(device)) |
172 | return -EINVAL; | 173 | return -EINVAL; |
@@ -179,11 +180,19 @@ int ib_find_cached_pkey(struct ib_device *device, | |||
179 | 180 | ||
180 | for (i = 0; i < cache->table_len; ++i) | 181 | for (i = 0; i < cache->table_len; ++i) |
181 | if ((cache->table[i] & 0x7fff) == (pkey & 0x7fff)) { | 182 | if ((cache->table[i] & 0x7fff) == (pkey & 0x7fff)) { |
182 | *index = i; | 183 | if (cache->table[i] & 0x8000) { |
183 | ret = 0; | 184 | *index = i; |
184 | break; | 185 | ret = 0; |
186 | break; | ||
187 | } else | ||
188 | partial_ix = i; | ||
185 | } | 189 | } |
186 | 190 | ||
191 | if (ret && partial_ix >= 0) { | ||
192 | *index = partial_ix; | ||
193 | ret = 0; | ||
194 | } | ||
195 | |||
187 | read_unlock_irqrestore(&device->cache.lock, flags); | 196 | read_unlock_irqrestore(&device->cache.lock, flags); |
188 | 197 | ||
189 | return ret; | 198 | return ret; |
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index e711de400a01..18c1ece765f2 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c | |||
@@ -707,18 +707,28 @@ int ib_find_pkey(struct ib_device *device, | |||
707 | { | 707 | { |
708 | int ret, i; | 708 | int ret, i; |
709 | u16 tmp_pkey; | 709 | u16 tmp_pkey; |
710 | int partial_ix = -1; | ||
710 | 711 | ||
711 | for (i = 0; i < device->pkey_tbl_len[port_num - start_port(device)]; ++i) { | 712 | for (i = 0; i < device->pkey_tbl_len[port_num - start_port(device)]; ++i) { |
712 | ret = ib_query_pkey(device, port_num, i, &tmp_pkey); | 713 | ret = ib_query_pkey(device, port_num, i, &tmp_pkey); |
713 | if (ret) | 714 | if (ret) |
714 | return ret; | 715 | return ret; |
715 | |||
716 | if ((pkey & 0x7fff) == (tmp_pkey & 0x7fff)) { | 716 | if ((pkey & 0x7fff) == (tmp_pkey & 0x7fff)) { |
717 | *index = i; | 717 | /* if there is full-member pkey take it.*/ |
718 | return 0; | 718 | if (tmp_pkey & 0x8000) { |
719 | *index = i; | ||
720 | return 0; | ||
721 | } | ||
722 | if (partial_ix < 0) | ||
723 | partial_ix = i; | ||
719 | } | 724 | } |
720 | } | 725 | } |
721 | 726 | ||
727 | /*no full-member, if exists take the limited*/ | ||
728 | if (partial_ix >= 0) { | ||
729 | *index = partial_ix; | ||
730 | return 0; | ||
731 | } | ||
722 | return -ENOENT; | 732 | return -ENOENT; |
723 | } | 733 | } |
724 | EXPORT_SYMBOL(ib_find_pkey); | 734 | EXPORT_SYMBOL(ib_find_pkey); |