aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2012-08-03 04:40:43 -0400
committerRoland Dreier <roland@purestorage.com>2012-09-30 23:33:33 -0400
commit54679e148287f0ca1bdd09264c908bacb9f19b3f (patch)
tree8ef261b3d7a51f8c29c2f625273ae9b399cb0402 /drivers/infiniband/hw
parentfc06573dfaf8a33bc0533bb70c49de13fa5232a4 (diff)
mlx4: Implement QP paravirtualization and maintain phys_pkey_cache for smp_snoop
This requires: 1. Replacing the paravirtualized P_Key index (inserted by the guest) with the real P_Key index. 2. For UD QPs, placing the guest's true source GID index in the address path structure mgid field, and setting the ud_force_mgid bit so that the mgid is taken from the QP context and not from the WQE when posting sends. 3. For UC and RC QPs, placing the guest's true source GID index in the address path structure mgid field. 4. For tunnel and proxy QPs, setting the Q_Key value reserved for that proxy/tunnel pair. Since not all the above adjustments occur in all the QP transitions, the QP transitions require separate wrapper functions. Secondly, initialize the P_Key virtualization table to its default values: Master virtualized table is 1-1 with the real P_Key table, guest virtualized table has P_Key index 0 mapped to the real P_Key index 0, and all the other P_Key indices mapped to the reserved (invalid) P_Key at index 127. Finally, add logic in smp_snoop for maintaining the phys_P_Key_cache. and generating events on the master only if a P_Key actually changed. Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c33
-rw-r--r--drivers/infiniband/hw/mlx4/main.c35
2 files changed, 66 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index e98849338a94..318d5bcf821b 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -185,6 +185,10 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad,
185{ 185{
186 struct ib_port_info *pinfo; 186 struct ib_port_info *pinfo;
187 u16 lid; 187 u16 lid;
188 __be16 *base;
189 u32 bn, pkey_change_bitmap;
190 int i;
191
188 192
189 struct mlx4_ib_dev *dev = to_mdev(ibdev); 193 struct mlx4_ib_dev *dev = to_mdev(ibdev);
190 if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || 194 if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED ||
@@ -209,8 +213,33 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad,
209 break; 213 break;
210 214
211 case IB_SMP_ATTR_PKEY_TABLE: 215 case IB_SMP_ATTR_PKEY_TABLE:
212 mlx4_ib_dispatch_event(dev, port_num, 216 if (!mlx4_is_mfunc(dev->dev)) {
213 IB_EVENT_PKEY_CHANGE); 217 mlx4_ib_dispatch_event(dev, port_num,
218 IB_EVENT_PKEY_CHANGE);
219 break;
220 }
221
222 bn = be32_to_cpu(((struct ib_smp *)mad)->attr_mod) & 0xFFFF;
223 base = (__be16 *) &(((struct ib_smp *)mad)->data[0]);
224 pkey_change_bitmap = 0;
225 for (i = 0; i < 32; i++) {
226 pr_debug("PKEY[%d] = x%x\n",
227 i + bn*32, be16_to_cpu(base[i]));
228 if (be16_to_cpu(base[i]) !=
229 dev->pkeys.phys_pkey_cache[port_num - 1][i + bn*32]) {
230 pkey_change_bitmap |= (1 << i);
231 dev->pkeys.phys_pkey_cache[port_num - 1][i + bn*32] =
232 be16_to_cpu(base[i]);
233 }
234 }
235 pr_debug("PKEY Change event: port=%d, "
236 "block=0x%x, change_bitmap=0x%x\n",
237 port_num, bn, pkey_change_bitmap);
238
239 if (pkey_change_bitmap)
240 mlx4_ib_dispatch_event(dev, port_num,
241 IB_EVENT_PKEY_CHANGE);
242
214 break; 243 break;
215 244
216 case IB_SMP_ATTR_GUID_INFO: 245 case IB_SMP_ATTR_GUID_INFO:
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 3f7f77f93a1c..8e10ec2af7b6 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -1121,6 +1121,38 @@ static int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event
1121 return NOTIFY_DONE; 1121 return NOTIFY_DONE;
1122} 1122}
1123 1123
1124static void init_pkeys(struct mlx4_ib_dev *ibdev)
1125{
1126 int port;
1127 int slave;
1128 int i;
1129
1130 if (mlx4_is_master(ibdev->dev)) {
1131 for (slave = 0; slave <= ibdev->dev->num_vfs; ++slave) {
1132 for (port = 1; port <= ibdev->dev->caps.num_ports; ++port) {
1133 for (i = 0;
1134 i < ibdev->dev->phys_caps.pkey_phys_table_len[port];
1135 ++i) {
1136 ibdev->pkeys.virt2phys_pkey[slave][port - 1][i] =
1137 /* master has the identity virt2phys pkey mapping */
1138 (slave == mlx4_master_func_num(ibdev->dev) || !i) ? i :
1139 ibdev->dev->phys_caps.pkey_phys_table_len[port] - 1;
1140 mlx4_sync_pkey_table(ibdev->dev, slave, port, i,
1141 ibdev->pkeys.virt2phys_pkey[slave][port - 1][i]);
1142 }
1143 }
1144 }
1145 /* initialize pkey cache */
1146 for (port = 1; port <= ibdev->dev->caps.num_ports; ++port) {
1147 for (i = 0;
1148 i < ibdev->dev->phys_caps.pkey_phys_table_len[port];
1149 ++i)
1150 ibdev->pkeys.phys_pkey_cache[port-1][i] =
1151 (i) ? 0 : 0xFFFF;
1152 }
1153 }
1154}
1155
1124static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) 1156static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
1125{ 1157{
1126 char name[32]; 1158 char name[32];
@@ -1375,6 +1407,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
1375 1407
1376 ibdev->ib_active = true; 1408 ibdev->ib_active = true;
1377 1409
1410 if (mlx4_is_mfunc(ibdev->dev))
1411 init_pkeys(ibdev);
1412
1378 return ibdev; 1413 return ibdev;
1379 1414
1380err_notif: 1415err_notif: