aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2012-08-03 04:40:38 -0400
committerRoland Dreier <roland@purestorage.com>2012-09-30 23:33:29 -0400
commitff7166c447df23a61e4f51bf748319dc6728dc74 (patch)
treec37b966015832ad93661cbcbce6e2f8fb6d276c2 /drivers/infiniband
parentd2b57063e4aba51d3c49ec957607d2e4c9d5f29a (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.c15
-rw-r--r--drivers/infiniband/core/device.c16
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}
724EXPORT_SYMBOL(ib_find_pkey); 734EXPORT_SYMBOL(ib_find_pkey);