Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a3eed83a authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'qed-Add-support-for-phy-module-query'



Sudarsana Reddy Kalluru says:

====================
qed*: Add support for phy module query.

The patch series adds driver support for querying the PHY module's
eeprom data.

Please consider applying it to 'net-next'.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 57dc2bfc 97df0d65
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -12444,6 +12444,8 @@ struct public_drv_mb {
#define DRV_MSG_CODE_STATS_TYPE_ISCSI           3
#define DRV_MSG_CODE_STATS_TYPE_RDMA            4

#define DRV_MSG_CODE_TRANSCEIVER_READ           0x00160000

#define DRV_MSG_CODE_MASK_PARITIES              0x001a0000

#define DRV_MSG_CODE_BIST_TEST			0x001e0000
@@ -12543,6 +12545,15 @@ struct public_drv_mb {
#define DRV_MB_PARAM_SET_LED_MODE_ON		0x1
#define DRV_MB_PARAM_SET_LED_MODE_OFF		0x2

#define DRV_MB_PARAM_TRANSCEIVER_PORT_OFFSET		0
#define DRV_MB_PARAM_TRANSCEIVER_PORT_MASK		0x00000003
#define DRV_MB_PARAM_TRANSCEIVER_SIZE_OFFSET		2
#define DRV_MB_PARAM_TRANSCEIVER_SIZE_MASK		0x000000FC
#define DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_OFFSET	8
#define DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_MASK	0x0000FF00
#define DRV_MB_PARAM_TRANSCEIVER_OFFSET_OFFSET		16
#define DRV_MB_PARAM_TRANSCEIVER_OFFSET_MASK		0xFFFF0000

	/* Resource Allocation params - Driver version support */
#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_MASK	0xFFFF0000
#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT	16
@@ -12596,6 +12607,9 @@ struct public_drv_mb {
#define FW_MSG_CODE_PHY_OK			0x00110000
#define FW_MSG_CODE_OK				0x00160000
#define FW_MSG_CODE_ERROR			0x00170000
#define FW_MSG_CODE_TRANSCEIVER_DIAG_OK		0x00160000
#define FW_MSG_CODE_TRANSCEIVER_DIAG_ERROR	0x00170000
#define FW_MSG_CODE_TRANSCEIVER_NOT_PRESENT	0x00020000

#define FW_MSG_CODE_OS_WOL_SUPPORTED            0x00800000
#define FW_MSG_CODE_OS_WOL_NOT_SUPPORTED        0x00810000
@@ -12687,6 +12701,8 @@ struct mcp_public_data {
	struct public_func func[MCP_GLOB_FUNC_MAX];
};

#define MAX_I2C_TRANSACTION_SIZE	16

/* OCBB definitions */
enum tlvs {
	/* Category 1: Device Properties */
+23 −0
Original line number Diff line number Diff line
@@ -2102,6 +2102,28 @@ static int qed_update_mtu(struct qed_dev *cdev, u16 mtu)
	return status;
}

static int qed_read_module_eeprom(struct qed_dev *cdev, char *buf,
				  u8 dev_addr, u32 offset, u32 len)
{
	struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
	struct qed_ptt *ptt;
	int rc = 0;

	if (IS_VF(cdev))
		return 0;

	ptt = qed_ptt_acquire(hwfn);
	if (!ptt)
		return -EAGAIN;

	rc = qed_mcp_phy_sfp_read(hwfn, ptt, MFW_PORT(hwfn), dev_addr,
				  offset, len, buf);

	qed_ptt_release(hwfn, ptt);

	return rc;
}

static struct qed_selftest_ops qed_selftest_ops_pass = {
	.selftest_memory = &qed_selftest_memory,
	.selftest_interrupt = &qed_selftest_interrupt,
@@ -2144,6 +2166,7 @@ const struct qed_common_ops qed_common_ops_pass = {
	.update_mac = &qed_update_mac,
	.update_mtu = &qed_update_mtu,
	.update_wol = &qed_update_wol,
	.read_module_eeprom = &qed_read_module_eeprom,
};

void qed_get_protocol_stats(struct qed_dev *cdev,
+49 −0
Original line number Diff line number Diff line
@@ -2463,6 +2463,55 @@ int qed_mcp_nvm_write(struct qed_dev *cdev,
	return rc;
}

int qed_mcp_phy_sfp_read(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
			 u32 port, u32 addr, u32 offset, u32 len, u8 *p_buf)
{
	u32 bytes_left, bytes_to_copy, buf_size, nvm_offset = 0;
	u32 resp, param;
	int rc;

	nvm_offset |= (port << DRV_MB_PARAM_TRANSCEIVER_PORT_OFFSET) &
		       DRV_MB_PARAM_TRANSCEIVER_PORT_MASK;
	nvm_offset |= (addr << DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_OFFSET) &
		       DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_MASK;

	addr = offset;
	offset = 0;
	bytes_left = len;
	while (bytes_left > 0) {
		bytes_to_copy = min_t(u32, bytes_left,
				      MAX_I2C_TRANSACTION_SIZE);
		nvm_offset &= (DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_MASK |
			       DRV_MB_PARAM_TRANSCEIVER_PORT_MASK);
		nvm_offset |= ((addr + offset) <<
			       DRV_MB_PARAM_TRANSCEIVER_OFFSET_OFFSET) &
			       DRV_MB_PARAM_TRANSCEIVER_OFFSET_MASK;
		nvm_offset |= (bytes_to_copy <<
			       DRV_MB_PARAM_TRANSCEIVER_SIZE_OFFSET) &
			       DRV_MB_PARAM_TRANSCEIVER_SIZE_MASK;
		rc = qed_mcp_nvm_rd_cmd(p_hwfn, p_ptt,
					DRV_MSG_CODE_TRANSCEIVER_READ,
					nvm_offset, &resp, &param, &buf_size,
					(u32 *)(p_buf + offset));
		if (rc) {
			DP_NOTICE(p_hwfn,
				  "Failed to send a transceiver read command to the MFW. rc = %d.\n",
				  rc);
			return rc;
		}

		if (resp == FW_MSG_CODE_TRANSCEIVER_NOT_PRESENT)
			return -ENODEV;
		else if (resp != FW_MSG_CODE_TRANSCEIVER_DIAG_OK)
			return -EINVAL;

		offset += buf_size;
		bytes_left -= buf_size;
	}

	return 0;
}

int qed_mcp_bist_register_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
{
	u32 drv_mb_param = 0, rsp, param;
+16 −0
Original line number Diff line number Diff line
@@ -839,6 +839,22 @@ int qed_mcp_nvm_rd_cmd(struct qed_hwfn *p_hwfn,
		       u32 *o_mcp_resp,
		       u32 *o_mcp_param, u32 *o_txn_size, u32 *o_buf);

/**
 * @brief Read from sfp
 *
 *  @param p_hwfn - hw function
 *  @param p_ptt  - PTT required for register access
 *  @param port   - transceiver port
 *  @param addr   - I2C address
 *  @param offset - offset in sfp
 *  @param len    - buffer length
 *  @param p_buf  - buffer to read into
 *
 * @return int - 0 - operation was successful.
 */
int qed_mcp_phy_sfp_read(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
			 u32 port, u32 addr, u32 offset, u32 len, u8 *p_buf);

/**
 * @brief indicates whether the MFW objects [under mcp_info] are accessible
 *
+88 −0
Original line number Diff line number Diff line
@@ -1780,6 +1780,92 @@ static int qede_set_eee(struct net_device *dev, struct ethtool_eee *edata)
	return 0;
}

static int qede_get_module_info(struct net_device *dev,
				struct ethtool_modinfo *modinfo)
{
	struct qede_dev *edev = netdev_priv(dev);
	u8 buf[4];
	int rc;

	/* Read first 4 bytes to find the sfp type */
	rc = edev->ops->common->read_module_eeprom(edev->cdev, buf,
						   QED_I2C_DEV_ADDR_A0, 0, 4);
	if (rc) {
		DP_ERR(edev, "Failed reading EEPROM data %d\n", rc);
		return rc;
	}

	switch (buf[0]) {
	case 0x3: /* SFP, SFP+, SFP-28 */
		modinfo->type = ETH_MODULE_SFF_8472;
		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
		break;
	case 0xc: /* QSFP */
	case 0xd: /* QSFP+ */
		modinfo->type = ETH_MODULE_SFF_8436;
		modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
		break;
	case 0x11: /* QSFP-28 */
		modinfo->type = ETH_MODULE_SFF_8636;
		modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
		break;
	default:
		DP_ERR(edev, "Unknown transceiver type 0x%x\n", buf[0]);
		return -EINVAL;
	}

	return 0;
}

static int qede_get_module_eeprom(struct net_device *dev,
				  struct ethtool_eeprom *ee, u8 *data)
{
	struct qede_dev *edev = netdev_priv(dev);
	u32 start_addr = ee->offset, size = 0;
	u8 *buf = data;
	int rc = 0;

	/* Read A0 section */
	if (ee->offset < ETH_MODULE_SFF_8079_LEN) {
		/* Limit transfer size to the A0 section boundary */
		if (ee->offset + ee->len > ETH_MODULE_SFF_8079_LEN)
			size = ETH_MODULE_SFF_8079_LEN - ee->offset;
		else
			size = ee->len;

		rc = edev->ops->common->read_module_eeprom(edev->cdev, buf,
							   QED_I2C_DEV_ADDR_A0,
							   start_addr, size);
		if (rc) {
			DP_ERR(edev, "Failed reading A0 section  %d\n", rc);
			return rc;
		}

		buf += size;
		start_addr += size;
	}

	/* Read A2 section */
	if (start_addr >= ETH_MODULE_SFF_8079_LEN &&
	    start_addr < ETH_MODULE_SFF_8472_LEN) {
		size = ee->len - size;
		/* Limit transfer size to the A2 section boundary */
		if (start_addr + size > ETH_MODULE_SFF_8472_LEN)
			size = ETH_MODULE_SFF_8472_LEN - start_addr;
		start_addr -= ETH_MODULE_SFF_8079_LEN;
		rc = edev->ops->common->read_module_eeprom(edev->cdev, buf,
							   QED_I2C_DEV_ADDR_A2,
							   start_addr, size);
		if (rc) {
			DP_VERBOSE(edev, QED_MSG_DEBUG,
				   "Failed reading A2 section %d\n", rc);
			return 0;
		}
	}

	return rc;
}

static const struct ethtool_ops qede_ethtool_ops = {
	.get_link_ksettings = qede_get_link_ksettings,
	.set_link_ksettings = qede_set_link_ksettings,
@@ -1813,6 +1899,8 @@ static const struct ethtool_ops qede_ethtool_ops = {
	.get_channels = qede_get_channels,
	.set_channels = qede_set_channels,
	.self_test = qede_self_test,
	.get_module_info = qede_get_module_info,
	.get_module_eeprom = qede_get_module_eeprom,
	.get_eee = qede_get_eee,
	.set_eee = qede_set_eee,

Loading