aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaeed Mahameed <saeedm@mellanox.com>2014-10-27 05:37:35 -0400
committerDavid S. Miller <davem@davemloft.net>2014-10-28 17:17:59 -0400
commit32a173c7f9e9ec2b87142f67e1478cd20084a45b (patch)
tree3464627af9e7001470aff187ecc9155ccf2e18a9
parent941d8ebcf773fd5da5c79e1c86e1afaae7032a0b (diff)
net/mlx4_core: Introduce mlx4_get_module_info for cable module info reading
Added new MAD_IFC command to read cable module info with attribute id (0xFF60). Update include/linux/mlx4/device.h with function declaration (mlx4_get_module_info) and the needed defines/enums for future use. Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: Amir Vadai <amirv@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/port.c156
-rw-r--r--include/linux/mlx4/device.h30
2 files changed, 186 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
index 94eeb2c7d7e4..30eb1ead0fe6 100644
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -1311,3 +1311,159 @@ int mlx4_get_roce_gid_from_slave(struct mlx4_dev *dev, int port, int slave_id,
1311 return 0; 1311 return 0;
1312} 1312}
1313EXPORT_SYMBOL(mlx4_get_roce_gid_from_slave); 1313EXPORT_SYMBOL(mlx4_get_roce_gid_from_slave);
1314
1315/* Cable Module Info */
1316#define MODULE_INFO_MAX_READ 48
1317
1318#define I2C_ADDR_LOW 0x50
1319#define I2C_ADDR_HIGH 0x51
1320#define I2C_PAGE_SIZE 256
1321
1322/* Module Info Data */
1323struct mlx4_cable_info {
1324 u8 i2c_addr;
1325 u8 page_num;
1326 __be16 dev_mem_address;
1327 __be16 reserved1;
1328 __be16 size;
1329 __be32 reserved2[2];
1330 u8 data[MODULE_INFO_MAX_READ];
1331};
1332
1333enum cable_info_err {
1334 CABLE_INF_INV_PORT = 0x1,
1335 CABLE_INF_OP_NOSUP = 0x2,
1336 CABLE_INF_NOT_CONN = 0x3,
1337 CABLE_INF_NO_EEPRM = 0x4,
1338 CABLE_INF_PAGE_ERR = 0x5,
1339 CABLE_INF_INV_ADDR = 0x6,
1340 CABLE_INF_I2C_ADDR = 0x7,
1341 CABLE_INF_QSFP_VIO = 0x8,
1342 CABLE_INF_I2C_BUSY = 0x9,
1343};
1344
1345#define MAD_STATUS_2_CABLE_ERR(mad_status) ((mad_status >> 8) & 0xFF)
1346
1347static inline const char *cable_info_mad_err_str(u16 mad_status)
1348{
1349 u8 err = MAD_STATUS_2_CABLE_ERR(mad_status);
1350
1351 switch (err) {
1352 case CABLE_INF_INV_PORT:
1353 return "invalid port selected";
1354 case CABLE_INF_OP_NOSUP:
1355 return "operation not supported for this port (the port is of type CX4 or internal)";
1356 case CABLE_INF_NOT_CONN:
1357 return "cable is not connected";
1358 case CABLE_INF_NO_EEPRM:
1359 return "the connected cable has no EPROM (passive copper cable)";
1360 case CABLE_INF_PAGE_ERR:
1361 return "page number is greater than 15";
1362 case CABLE_INF_INV_ADDR:
1363 return "invalid device_address or size (that is, size equals 0 or address+size is greater than 256)";
1364 case CABLE_INF_I2C_ADDR:
1365 return "invalid I2C slave address";
1366 case CABLE_INF_QSFP_VIO:
1367 return "at least one cable violates the QSFP specification and ignores the modsel signal";
1368 case CABLE_INF_I2C_BUSY:
1369 return "I2C bus is constantly busy";
1370 }
1371 return "Unknown Error";
1372}
1373
1374/**
1375 * mlx4_get_module_info - Read cable module eeprom data
1376 * @dev: mlx4_dev.
1377 * @port: port number.
1378 * @offset: byte offset in eeprom to start reading data from.
1379 * @size: num of bytes to read.
1380 * @data: output buffer to put the requested data into.
1381 *
1382 * Reads cable module eeprom data, puts the outcome data into
1383 * data pointer paramer.
1384 * Returns num of read bytes on success or a negative error
1385 * code.
1386 */
1387int mlx4_get_module_info(struct mlx4_dev *dev, u8 port,
1388 u16 offset, u16 size, u8 *data)
1389{
1390 struct mlx4_cmd_mailbox *inbox, *outbox;
1391 struct mlx4_mad_ifc *inmad, *outmad;
1392 struct mlx4_cable_info *cable_info;
1393 u16 i2c_addr;
1394 int ret;
1395
1396 if (size > MODULE_INFO_MAX_READ)
1397 size = MODULE_INFO_MAX_READ;
1398
1399 inbox = mlx4_alloc_cmd_mailbox(dev);
1400 if (IS_ERR(inbox))
1401 return PTR_ERR(inbox);
1402
1403 outbox = mlx4_alloc_cmd_mailbox(dev);
1404 if (IS_ERR(outbox)) {
1405 mlx4_free_cmd_mailbox(dev, inbox);
1406 return PTR_ERR(outbox);
1407 }
1408
1409 inmad = (struct mlx4_mad_ifc *)(inbox->buf);
1410 outmad = (struct mlx4_mad_ifc *)(outbox->buf);
1411
1412 inmad->method = 0x1; /* Get */
1413 inmad->class_version = 0x1;
1414 inmad->mgmt_class = 0x1;
1415 inmad->base_version = 0x1;
1416 inmad->attr_id = cpu_to_be16(0xFF60); /* Module Info */
1417
1418 if (offset < I2C_PAGE_SIZE && offset + size > I2C_PAGE_SIZE)
1419 /* Cross pages reads are not allowed
1420 * read until offset 256 in low page
1421 */
1422 size -= offset + size - I2C_PAGE_SIZE;
1423
1424 i2c_addr = I2C_ADDR_LOW;
1425 if (offset >= I2C_PAGE_SIZE) {
1426 /* Reset offset to high page */
1427 i2c_addr = I2C_ADDR_HIGH;
1428 offset -= I2C_PAGE_SIZE;
1429 }
1430
1431 cable_info = (struct mlx4_cable_info *)inmad->data;
1432 cable_info->dev_mem_address = cpu_to_be16(offset);
1433 cable_info->page_num = 0;
1434 cable_info->i2c_addr = i2c_addr;
1435 cable_info->size = cpu_to_be16(size);
1436
1437 ret = mlx4_cmd_box(dev, inbox->dma, outbox->dma, port, 3,
1438 MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C,
1439 MLX4_CMD_NATIVE);
1440 if (ret)
1441 goto out;
1442
1443 if (be16_to_cpu(outmad->status)) {
1444 /* Mad returned with bad status */
1445 ret = be16_to_cpu(outmad->status);
1446 mlx4_warn(dev,
1447 "MLX4_CMD_MAD_IFC Get Module info attr(%x) port(%d) i2c_addr(%x) offset(%d) size(%d): Response Mad Status(%x) - %s\n",
1448 0xFF60, port, i2c_addr, offset, size,
1449 ret, cable_info_mad_err_str(ret));
1450
1451 if (i2c_addr == I2C_ADDR_HIGH &&
1452 MAD_STATUS_2_CABLE_ERR(ret) == CABLE_INF_I2C_ADDR)
1453 /* Some SFP cables do not support i2c slave
1454 * address 0x51 (high page), abort silently.
1455 */
1456 ret = 0;
1457 else
1458 ret = -ret;
1459 goto out;
1460 }
1461 cable_info = (struct mlx4_cable_info *)outmad->data;
1462 memcpy(data, cable_info->data, size);
1463 ret = size;
1464out:
1465 mlx4_free_cmd_mailbox(dev, inbox);
1466 mlx4_free_cmd_mailbox(dev, outbox);
1467 return ret;
1468}
1469EXPORT_SYMBOL(mlx4_get_module_info);
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 37e4404d0227..73910daec317 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -379,6 +379,13 @@ enum {
379#define MSTR_SM_CHANGE_MASK (MLX4_EQ_PORT_INFO_MSTR_SM_SL_CHANGE_MASK | \ 379#define MSTR_SM_CHANGE_MASK (MLX4_EQ_PORT_INFO_MSTR_SM_SL_CHANGE_MASK | \
380 MLX4_EQ_PORT_INFO_MSTR_SM_LID_CHANGE_MASK) 380 MLX4_EQ_PORT_INFO_MSTR_SM_LID_CHANGE_MASK)
381 381
382enum mlx4_module_id {
383 MLX4_MODULE_ID_SFP = 0x3,
384 MLX4_MODULE_ID_QSFP = 0xC,
385 MLX4_MODULE_ID_QSFP_PLUS = 0xD,
386 MLX4_MODULE_ID_QSFP28 = 0x11,
387};
388
382static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor) 389static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor)
383{ 390{
384 return (major << 32) | (minor << 16) | subminor; 391 return (major << 32) | (minor << 16) | subminor;
@@ -799,6 +806,26 @@ struct mlx4_init_port_param {
799 u64 si_guid; 806 u64 si_guid;
800}; 807};
801 808
809#define MAD_IFC_DATA_SZ 192
810/* MAD IFC Mailbox */
811struct mlx4_mad_ifc {
812 u8 base_version;
813 u8 mgmt_class;
814 u8 class_version;
815 u8 method;
816 __be16 status;
817 __be16 class_specific;
818 __be64 tid;
819 __be16 attr_id;
820 __be16 resv;
821 __be32 attr_mod;
822 __be64 mkey;
823 __be16 dr_slid;
824 __be16 dr_dlid;
825 u8 reserved[28];
826 u8 data[MAD_IFC_DATA_SZ];
827} __packed;
828
802#define mlx4_foreach_port(port, dev, type) \ 829#define mlx4_foreach_port(port, dev, type) \
803 for ((port) = 1; (port) <= (dev)->caps.num_ports; (port)++) \ 830 for ((port) = 1; (port) <= (dev)->caps.num_ports; (port)++) \
804 if ((type) == (dev)->caps.port_mask[(port)]) 831 if ((type) == (dev)->caps.port_mask[(port)])
@@ -1283,6 +1310,9 @@ int mlx4_mr_rereg_mem_write(struct mlx4_dev *dev, struct mlx4_mr *mr,
1283 u64 iova, u64 size, int npages, 1310 u64 iova, u64 size, int npages,
1284 int page_shift, struct mlx4_mpt_entry *mpt_entry); 1311 int page_shift, struct mlx4_mpt_entry *mpt_entry);
1285 1312
1313int mlx4_get_module_info(struct mlx4_dev *dev, u8 port,
1314 u16 offset, u16 size, u8 *data);
1315
1286/* Returns true if running in low memory profile (kdump kernel) */ 1316/* Returns true if running in low memory profile (kdump kernel) */
1287static inline bool mlx4_low_memory_profile(void) 1317static inline bool mlx4_low_memory_profile(void)
1288{ 1318{