Commit 07afcc7a authored by Luo bin's avatar Luo bin Committed by David S. Miller
Browse files

hinic: add support to identify physical device



add support to identify physical device by flashing an LED
attached to it with ethtool -p cmd.

Signed-off-by: default avatarLuo bin <luobin9@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4aa218a4
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -1684,6 +1684,39 @@ static void hinic_diag_test(struct net_device *netdev,
		netif_carrier_on(netdev);
}

static int hinic_set_phys_id(struct net_device *netdev,
			     enum ethtool_phys_id_state state)
{
	struct hinic_dev *nic_dev = netdev_priv(netdev);
	int err = 0;
	u8 port;

	port = nic_dev->hwdev->port_id;

	switch (state) {
	case ETHTOOL_ID_ACTIVE:
		err = hinic_set_led_status(nic_dev->hwdev, port,
					   HINIC_LED_TYPE_LINK,
					   HINIC_LED_MODE_FORCE_2HZ);
		if (err)
			netif_err(nic_dev, drv, netdev,
				  "Set LED blinking in 2HZ failed\n");
		break;

	case ETHTOOL_ID_INACTIVE:
		err = hinic_reset_led_status(nic_dev->hwdev, port);
		if (err)
			netif_err(nic_dev, drv, netdev,
				  "Reset LED to original status failed\n");
		break;

	default:
		return -EOPNOTSUPP;
	}

	return err;
}

static const struct ethtool_ops hinic_ethtool_ops = {
	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
				     ETHTOOL_COALESCE_RX_MAX_FRAMES |
@@ -1714,6 +1747,7 @@ static const struct ethtool_ops hinic_ethtool_ops = {
	.get_ethtool_stats = hinic_get_ethtool_stats,
	.get_strings = hinic_get_strings,
	.self_test = hinic_diag_test,
	.set_phys_id = hinic_set_phys_id,
};

static const struct ethtool_ops hinicvf_ethtool_ops = {
+2 −0
Original line number Diff line number Diff line
@@ -83,6 +83,8 @@ static int parse_capability(struct hinic_hwdev *hwdev,
		nic_cap->max_vf_qps = dev_cap->max_vf_sqs + 1;
	}

	hwdev->port_id = dev_cap->port_id;

	return 0;
}

+1 −0
Original line number Diff line number Diff line
@@ -312,6 +312,7 @@ struct hinic_hwdev {
	struct hinic_mbox_func_to_func  *func_to_func;

	struct hinic_cap                nic_cap;
	u8				port_id;
};

struct hinic_nic_cb {
+3 −1
Original line number Diff line number Diff line
@@ -81,6 +81,8 @@ enum hinic_comm_cmd {
	HINIC_COMM_CMD_MSI_CTRL_REG_WR_BY_UP,
	HINIC_COMM_CMD_MSI_CTRL_REG_RD_BY_UP,

	HINIC_COMM_CMD_SET_LED_STATUS	= 0x4a,

	HINIC_COMM_CMD_L2NIC_RESET	= 0x4b,

	HINIC_COMM_CMD_PAGESIZE_SET	= 0x50,
+55 −0
Original line number Diff line number Diff line
@@ -1268,3 +1268,58 @@ int hinic_set_loopback_mode(struct hinic_hwdev *hwdev, u32 mode, u32 enable)

	return 0;
}

static int _set_led_status(struct hinic_hwdev *hwdev, u8 port,
			   enum hinic_led_type type,
			   enum hinic_led_mode mode, u8 reset)
{
	struct hinic_led_info led_info = {0};
	u16 out_size = sizeof(led_info);
	struct hinic_pfhwdev *pfhwdev;
	int err;

	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);

	led_info.port = port;
	led_info.reset = reset;

	led_info.type = type;
	led_info.mode = mode;

	err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
				HINIC_COMM_CMD_SET_LED_STATUS,
				&led_info, sizeof(led_info),
				&led_info, &out_size, HINIC_MGMT_MSG_SYNC);
	if (err || led_info.status || !out_size) {
		dev_err(&hwdev->hwif->pdev->dev, "Failed to set led status, err: %d, status: 0x%x, out size: 0x%x\n",
			err, led_info.status, out_size);
		return -EIO;
	}

	return 0;
}

int hinic_set_led_status(struct hinic_hwdev *hwdev, u8 port,
			 enum hinic_led_type type, enum hinic_led_mode mode)
{
	if (!hwdev)
		return -EINVAL;

	return _set_led_status(hwdev, port, type, mode, 0);
}

int hinic_reset_led_status(struct hinic_hwdev *hwdev, u8 port)
{
	int err;

	if (!hwdev)
		return -EINVAL;

	err = _set_led_status(hwdev, port, HINIC_LED_TYPE_INVALID,
			      HINIC_LED_MODE_INVALID, 1);
	if (err)
		dev_err(&hwdev->hwif->pdev->dev,
			"Failed to reset led status\n");

	return err;
}
Loading