|
@@ -549,6 +549,34 @@ arbel_cmd_2rst_qpee ( struct arbel *arbel, unsigned long qpn ) {
|
549
|
549
|
0x03, NULL, qpn, NULL );
|
550
|
550
|
}
|
551
|
551
|
|
|
552
|
+static inline int
|
|
553
|
+arbel_cmd_read_mgm ( struct arbel *arbel, unsigned int index,
|
|
554
|
+ struct arbelprm_mgm_entry *mgm ) {
|
|
555
|
+ return arbel_cmd ( arbel,
|
|
556
|
+ ARBEL_HCR_OUT_CMD ( ARBEL_HCR_READ_MGM,
|
|
557
|
+ 1, sizeof ( *mgm ) ),
|
|
558
|
+ 0, NULL, index, mgm );
|
|
559
|
+}
|
|
560
|
+
|
|
561
|
+static inline int
|
|
562
|
+arbel_cmd_write_mgm ( struct arbel *arbel, unsigned int index,
|
|
563
|
+ const struct arbelprm_mgm_entry *mgm ) {
|
|
564
|
+ return arbel_cmd ( arbel,
|
|
565
|
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_WRITE_MGM,
|
|
566
|
+ 1, sizeof ( *mgm ) ),
|
|
567
|
+ 0, mgm, index, NULL );
|
|
568
|
+}
|
|
569
|
+
|
|
570
|
+static inline int
|
|
571
|
+arbel_cmd_mgid_hash ( struct arbel *arbel, const struct ib_gid *gid,
|
|
572
|
+ struct arbelprm_mgm_hash *hash ) {
|
|
573
|
+ return arbel_cmd ( arbel,
|
|
574
|
+ ARBEL_HCR_INOUT_CMD ( ARBEL_HCR_MGID_HASH,
|
|
575
|
+ 1, sizeof ( *gid ),
|
|
576
|
+ 0, sizeof ( *hash ) ),
|
|
577
|
+ 0, gid, 0, hash );
|
|
578
|
+}
|
|
579
|
+
|
552
|
580
|
/***************************************************************************
|
553
|
581
|
*
|
554
|
582
|
* Completion queue operations
|
|
@@ -1253,6 +1281,104 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
|
1253
|
1281
|
}
|
1254
|
1282
|
}
|
1255
|
1283
|
|
|
1284
|
+/***************************************************************************
|
|
1285
|
+ *
|
|
1286
|
+ * Multicast group operations
|
|
1287
|
+ *
|
|
1288
|
+ ***************************************************************************
|
|
1289
|
+ */
|
|
1290
|
+
|
|
1291
|
+/**
|
|
1292
|
+ * Attach to multicast group
|
|
1293
|
+ *
|
|
1294
|
+ * @v ibdev Infiniband device
|
|
1295
|
+ * @v qp Queue pair
|
|
1296
|
+ * @v gid Multicast GID
|
|
1297
|
+ * @ret rc Return status code
|
|
1298
|
+ */
|
|
1299
|
+static int arbel_mcast_attach ( struct ib_device *ibdev,
|
|
1300
|
+ struct ib_queue_pair *qp,
|
|
1301
|
+ struct ib_gid *gid ) {
|
|
1302
|
+ struct arbel *arbel = ibdev->dev_priv;
|
|
1303
|
+ struct arbelprm_mgm_hash hash;
|
|
1304
|
+ struct arbelprm_mgm_entry mgm;
|
|
1305
|
+ unsigned int index;
|
|
1306
|
+ int rc;
|
|
1307
|
+
|
|
1308
|
+ /* Generate hash table index */
|
|
1309
|
+ if ( ( rc = arbel_cmd_mgid_hash ( arbel, gid, &hash ) ) != 0 ) {
|
|
1310
|
+ DBGC ( arbel, "Arbel %p could not hash GID: %s\n",
|
|
1311
|
+ arbel, strerror ( rc ) );
|
|
1312
|
+ return rc;
|
|
1313
|
+ }
|
|
1314
|
+ index = MLX_GET ( &hash, hash );
|
|
1315
|
+
|
|
1316
|
+ /* Check for existing hash table entry */
|
|
1317
|
+ if ( ( rc = arbel_cmd_read_mgm ( arbel, index, &mgm ) ) != 0 ) {
|
|
1318
|
+ DBGC ( arbel, "Arbel %p could not read MGM %#x: %s\n",
|
|
1319
|
+ arbel, index, strerror ( rc ) );
|
|
1320
|
+ return rc;
|
|
1321
|
+ }
|
|
1322
|
+ if ( MLX_GET ( &mgm, mgmqp_0.qi ) != 0 ) {
|
|
1323
|
+ /* FIXME: this implementation allows only a single QP
|
|
1324
|
+ * per multicast group, and doesn't handle hash
|
|
1325
|
+ * collisions. Sufficient for IPoIB but may need to
|
|
1326
|
+ * be extended in future.
|
|
1327
|
+ */
|
|
1328
|
+ DBGC ( arbel, "Arbel %p MGID index %#x already in use\n",
|
|
1329
|
+ arbel, index );
|
|
1330
|
+ return -EBUSY;
|
|
1331
|
+ }
|
|
1332
|
+
|
|
1333
|
+ /* Update hash table entry */
|
|
1334
|
+ MLX_FILL_2 ( &mgm, 8,
|
|
1335
|
+ mgmqp_0.qpn_i, qp->qpn,
|
|
1336
|
+ mgmqp_0.qi, 1 );
|
|
1337
|
+ memcpy ( &mgm.u.dwords[4], gid, sizeof ( *gid ) );
|
|
1338
|
+ if ( ( rc = arbel_cmd_write_mgm ( arbel, index, &mgm ) ) != 0 ) {
|
|
1339
|
+ DBGC ( arbel, "Arbel %p could not write MGM %#x: %s\n",
|
|
1340
|
+ arbel, index, strerror ( rc ) );
|
|
1341
|
+ return rc;
|
|
1342
|
+ }
|
|
1343
|
+
|
|
1344
|
+ return 0;
|
|
1345
|
+}
|
|
1346
|
+
|
|
1347
|
+/**
|
|
1348
|
+ * Detach from multicast group
|
|
1349
|
+ *
|
|
1350
|
+ * @v ibdev Infiniband device
|
|
1351
|
+ * @v qp Queue pair
|
|
1352
|
+ * @v gid Multicast GID
|
|
1353
|
+ */
|
|
1354
|
+static void arbel_mcast_detach ( struct ib_device *ibdev,
|
|
1355
|
+ struct ib_queue_pair *qp __unused,
|
|
1356
|
+ struct ib_gid *gid ) {
|
|
1357
|
+ struct arbel *arbel = ibdev->dev_priv;
|
|
1358
|
+ struct arbelprm_mgm_hash hash;
|
|
1359
|
+ struct arbelprm_mgm_entry mgm;
|
|
1360
|
+ unsigned int index;
|
|
1361
|
+ int rc;
|
|
1362
|
+
|
|
1363
|
+ /* Generate hash table index */
|
|
1364
|
+ if ( ( rc = arbel_cmd_mgid_hash ( arbel, gid, &hash ) ) != 0 ) {
|
|
1365
|
+ DBGC ( arbel, "Arbel %p could not hash GID: %s\n",
|
|
1366
|
+ arbel, strerror ( rc ) );
|
|
1367
|
+ return;
|
|
1368
|
+ }
|
|
1369
|
+ index = MLX_GET ( &hash, hash );
|
|
1370
|
+
|
|
1371
|
+ /* Clear hash table entry */
|
|
1372
|
+ memset ( &mgm, 0, sizeof ( mgm ) );
|
|
1373
|
+ if ( ( rc = arbel_cmd_write_mgm ( arbel, index, &mgm ) ) != 0 ) {
|
|
1374
|
+ DBGC ( arbel, "Arbel %p could not write MGM %#x: %s\n",
|
|
1375
|
+ arbel, index, strerror ( rc ) );
|
|
1376
|
+ return;
|
|
1377
|
+ }
|
|
1378
|
+}
|
|
1379
|
+
|
|
1380
|
+
|
|
1381
|
+
|
1256
|
1382
|
/** Arbel Infiniband operations */
|
1257
|
1383
|
static struct ib_device_operations arbel_ib_operations = {
|
1258
|
1384
|
.create_cq = arbel_create_cq,
|
|
@@ -1262,6 +1388,8 @@ static struct ib_device_operations arbel_ib_operations = {
|
1262
|
1388
|
.post_send = arbel_post_send,
|
1263
|
1389
|
.post_recv = arbel_post_recv,
|
1264
|
1390
|
.poll_cq = arbel_poll_cq,
|
|
1391
|
+ .mcast_attach = arbel_mcast_attach,
|
|
1392
|
+ .mcast_detach = arbel_mcast_detach,
|
1265
|
1393
|
};
|
1266
|
1394
|
|
1267
|
1395
|
/**
|
|
@@ -1379,6 +1507,14 @@ static int arbel_probe ( struct pci_device *pci,
|
1379
|
1507
|
return -EIO;
|
1380
|
1508
|
}
|
1381
|
1509
|
mlx->own_qp->owner_priv = netdev;
|
|
1510
|
+ struct ib_gid *bcast_gid = ( struct ib_gid * ) &ib_data.bcast_gid;
|
|
1511
|
+ if ( ( rc = ib_mcast_attach ( ibdev, mlx->own_qp,
|
|
1512
|
+ bcast_gid ) ) != 0 ) {
|
|
1513
|
+ DBG ( "Could not attach to broadcast GID: %s\n",
|
|
1514
|
+ strerror ( rc ) );
|
|
1515
|
+ return rc;
|
|
1516
|
+ }
|
|
1517
|
+
|
1382
|
1518
|
|
1383
|
1519
|
mac = ( ( struct ib_mac * ) netdev->ll_addr );
|
1384
|
1520
|
mac->qpn = htonl ( mlx->own_qp->qpn );
|