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

Commit 97df0d65 authored by Sudarsana Reddy Kalluru's avatar Sudarsana Reddy Kalluru Committed by David S. Miller
Browse files

qede: Add driver callbacks for eeprom module query.



This patch implements the ethtool callbacks for querying sfp/eeprom module.

Signed-off-by: default avatarSudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: default avatarAriel Elior <ariel.elior@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b51dab46
Loading
Loading
Loading
Loading
+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,