Skip to content

Commit

Permalink
hinic: add support to identify physical device
Browse files Browse the repository at this point in the history
add support to identify physical device by flashing an LED
attached to it with ethtool -p cmd.

Signed-off-by: Luo bin <luobin9@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Luo bin authored and David S. Miller committed Jun 29, 2020
1 parent 4aa218a commit 07afcc7
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 3 deletions.
34 changes: 34 additions & 0 deletions drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down Expand Up @@ -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 = {
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 3 additions & 1 deletion drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ 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_L2NIC_RESET = 0x4b,
HINIC_COMM_CMD_SET_LED_STATUS = 0x4a,

HINIC_COMM_CMD_L2NIC_RESET = 0x4b,

HINIC_COMM_CMD_PAGESIZE_SET = 0x50,

Expand Down
55 changes: 55 additions & 0 deletions drivers/net/ethernet/huawei/hinic/hinic_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
35 changes: 35 additions & 0 deletions drivers/net/ethernet/huawei/hinic/hinic_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,17 @@ struct hinic_port_loopback {
u32 en;
};

struct hinic_led_info {
u8 status;
u8 version;
u8 rsvd0[6];

u8 port;
u8 type;
u8 mode;
u8 reset;
};

int hinic_port_add_mac(struct hinic_dev *nic_dev, const u8 *addr,
u16 vlan_id);

Expand Down Expand Up @@ -765,6 +776,30 @@ int hinic_dcb_set_pfc(struct hinic_hwdev *hwdev, u8 pfc_en, u8 pfc_bitmap);

int hinic_set_loopback_mode(struct hinic_hwdev *hwdev, u32 mode, u32 enable);

enum hinic_led_mode {
HINIC_LED_MODE_ON,
HINIC_LED_MODE_OFF,
HINIC_LED_MODE_FORCE_1HZ,
HINIC_LED_MODE_FORCE_2HZ,
HINIC_LED_MODE_FORCE_4HZ,
HINIC_LED_MODE_1HZ,
HINIC_LED_MODE_2HZ,
HINIC_LED_MODE_4HZ,
HINIC_LED_MODE_INVALID,
};

enum hinic_led_type {
HINIC_LED_TYPE_LINK,
HINIC_LED_TYPE_LOW_SPEED,
HINIC_LED_TYPE_HIGH_SPEED,
HINIC_LED_TYPE_INVALID,
};

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

int hinic_set_led_status(struct hinic_hwdev *hwdev, u8 port,
enum hinic_led_type type, enum hinic_led_mode mode);

int hinic_open(struct net_device *netdev);

int hinic_close(struct net_device *netdev);
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/huawei/hinic/hinic_sriov.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ static int hinic_del_vf_mac_msg_handler(void *hwdev, u16 vf_id,

nic_io = &hw_dev->func_to_io;
vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
if (vf_info->pf_set_mac && is_valid_ether_addr(mac_in->mac) &&
if (vf_info->pf_set_mac && is_valid_ether_addr(mac_in->mac) &&
!memcmp(vf_info->vf_mac_addr, mac_in->mac, ETH_ALEN)) {
dev_warn(&hw_dev->hwif->pdev->dev, "PF has already set VF mac.\n");
mac_out->status = HINIC_PF_SET_VF_ALREADY;
Expand Down Expand Up @@ -905,7 +905,6 @@ int hinic_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)

err = hinic_set_vf_spoofchk(sriov_info->hwdev,
OS_VF_ID_TO_HW(vf), setting);

if (!err) {
netif_info(nic_dev, drv, netdev, "Set VF %d spoofchk %s successfully\n",
vf, setting ? "on" : "off");
Expand Down Expand Up @@ -1020,6 +1019,7 @@ static int cfg_mbx_pf_proc_vf_msg(void *hwdev, u16 vf_id, u8 cmd, void *buf_in,
dev_cap->max_vf = cap->max_vf;
dev_cap->max_sqs = cap->max_vf_qps;
dev_cap->max_rqs = cap->max_vf_qps;
dev_cap->port_id = dev->port_id;

*out_size = sizeof(*dev_cap);

Expand Down

0 comments on commit 07afcc7

Please sign in to comment.