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

Merge branch 'hns3-fixes'



Salil Mehta says:

====================
Misc. bug fixes & small enhancements for HNS3 Driver

This patch-set presents some fixes and minor enhancements to HNS3 Driver
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 05a6843c 12f46bc1
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -1662,11 +1662,24 @@ static int hns3_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
	return 0;
}

static void hns3_shutdown(struct pci_dev *pdev)
{
	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);

	hnae3_unregister_ae_dev(ae_dev);
	devm_kfree(&pdev->dev, ae_dev);
	pci_set_drvdata(pdev, NULL);

	if (system_state == SYSTEM_POWER_OFF)
		pci_set_power_state(pdev, PCI_D3hot);
}

static struct pci_driver hns3_driver = {
	.name     = hns3_driver_name,
	.id_table = hns3_pci_tbl,
	.probe    = hns3_probe,
	.remove   = hns3_remove,
	.shutdown = hns3_shutdown,
	.sriov_configure = hns3_pci_sriov_configure,
};

+44 −58
Original line number Diff line number Diff line
@@ -100,41 +100,26 @@ static int hns3_lp_up(struct net_device *ndev, enum hnae3_loop loop_mode)
	struct hnae3_handle *h = hns3_get_handle(ndev);
	int ret;

	if (!h->ae_algo->ops->start)
		return -EOPNOTSUPP;

	ret = hns3_nic_reset_all_ring(h);
	if (ret)
		return ret;

	ret = h->ae_algo->ops->start(h);
	if (ret) {
		netdev_err(ndev,
			   "hns3_lb_up ae start return error: %d\n", ret);
		return ret;
	}

	ret = hns3_lp_setup(ndev, loop_mode, true);
	usleep_range(10000, 20000);

	return ret;
	return 0;
}

static int hns3_lp_down(struct net_device *ndev, enum hnae3_loop loop_mode)
{
	struct hnae3_handle *h = hns3_get_handle(ndev);
	int ret;

	if (!h->ae_algo->ops->stop)
		return -EOPNOTSUPP;

	ret = hns3_lp_setup(ndev, loop_mode, false);
	if (ret) {
		netdev_err(ndev, "lb_setup return error: %d\n", ret);
		return ret;
	}

	h->ae_algo->ops->stop(h);
	usleep_range(10000, 20000);

	return 0;
@@ -152,6 +137,7 @@ static void hns3_lp_setup_skb(struct sk_buff *skb)
	packet = skb_put(skb, HNS3_NIC_LB_TEST_PACKET_SIZE);

	memcpy(ethh->h_dest, ndev->dev_addr, ETH_ALEN);
	ethh->h_dest[5] += 0x1f;
	eth_zero_addr(ethh->h_source);
	ethh->h_proto = htons(ETH_P_ARP);
	skb_reset_mac_header(skb);
@@ -309,7 +295,7 @@ static void hns3_self_test(struct net_device *ndev,
			h->flags & HNAE3_SUPPORT_SERDES_LOOPBACK;

	if (if_running)
		dev_close(ndev);
		ndev->netdev_ops->ndo_stop(ndev);

#if IS_ENABLED(CONFIG_VLAN_8021Q)
	/* Disable the vlan filter for selftest does not support it */
@@ -347,7 +333,7 @@ static void hns3_self_test(struct net_device *ndev,
#endif

	if (if_running)
		dev_open(ndev);
		ndev->netdev_ops->ndo_open(ndev);
}

static int hns3_get_sset_count(struct net_device *netdev, int stringset)
@@ -560,62 +546,62 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
				   struct ethtool_link_ksettings *cmd)
{
	struct hnae3_handle *h = hns3_get_handle(netdev);
	u32 flowctrl_adv = 0;
	const struct hnae3_ae_ops *ops;
	u8 link_stat;

	if (!h->ae_algo || !h->ae_algo->ops)
		return -EOPNOTSUPP;

	/* 1.auto_neg & speed & duplex from cmd */
	if (netdev->phydev) {
		phy_ethtool_ksettings_get(netdev->phydev, cmd);

		return 0;
	}
	ops = h->ae_algo->ops;
	if (ops->get_port_type)
		ops->get_port_type(h, &cmd->base.port);
	else
		return -EOPNOTSUPP;

	if (h->ae_algo->ops->get_ksettings_an_result)
		h->ae_algo->ops->get_ksettings_an_result(h,
	switch (cmd->base.port) {
	case PORT_FIBRE:
		/* 1.auto_neg & speed & duplex from cmd */
		if (ops->get_ksettings_an_result)
			ops->get_ksettings_an_result(h,
						     &cmd->base.autoneg,
						     &cmd->base.speed,
						     &cmd->base.duplex);
		else
			return -EOPNOTSUPP;

	link_stat = hns3_get_link(netdev);
	if (!link_stat) {
		cmd->base.speed = SPEED_UNKNOWN;
		cmd->base.duplex = DUPLEX_UNKNOWN;
	}

	/* 2.get link mode and port type*/
	if (h->ae_algo->ops->get_link_mode)
		h->ae_algo->ops->get_link_mode(h,
		/* 2.get link mode*/
		if (ops->get_link_mode)
			ops->get_link_mode(h,
					   cmd->link_modes.supported,
					   cmd->link_modes.advertising);

	cmd->base.port = PORT_NONE;
	if (h->ae_algo->ops->get_port_type)
		h->ae_algo->ops->get_port_type(h,
					       &cmd->base.port);

		/* 3.mdix_ctrl&mdix get from phy reg */
	if (h->ae_algo->ops->get_mdix_mode)
		h->ae_algo->ops->get_mdix_mode(h, &cmd->base.eth_tp_mdix_ctrl,
		if (ops->get_mdix_mode)
			ops->get_mdix_mode(h, &cmd->base.eth_tp_mdix_ctrl,
					   &cmd->base.eth_tp_mdix);
	/* 4.mdio_support */
	cmd->base.mdio_support = ETH_MDIO_SUPPORTS_C22;

	/* 5.get flow control setttings */
	if (h->ae_algo->ops->get_flowctrl_adv)
		h->ae_algo->ops->get_flowctrl_adv(h, &flowctrl_adv);
		break;
	case PORT_TP:
		if (!netdev->phydev)
			return -EOPNOTSUPP;

		phy_ethtool_ksettings_get(netdev->phydev, cmd);

		break;
	default:
		netdev_warn(netdev,
			    "Unknown port type, neither Fibre/Copper detected");
		return 0;
	}

	if (flowctrl_adv & ADVERTISED_Pause)
		ethtool_link_ksettings_add_link_mode(cmd, advertising,
						     Pause);
	/* mdio_support */
	cmd->base.mdio_support = ETH_MDIO_SUPPORTS_C22;

	if (flowctrl_adv & ADVERTISED_Asym_Pause)
		ethtool_link_ksettings_add_link_mode(cmd, advertising,
						     Asym_Pause);
	link_stat = hns3_get_link(netdev);
	if (!link_stat) {
		cmd->base.speed = SPEED_UNKNOWN;
		cmd->base.duplex = DUPLEX_UNKNOWN;
	}

	return 0;
}
+75 −56
Original line number Diff line number Diff line
@@ -2066,19 +2066,17 @@ static int hclge_init_msi(struct hclge_dev *hdev)
	return 0;
}

static void hclge_check_speed_dup(struct hclge_dev *hdev, int duplex, int speed)
static u8 hclge_check_speed_dup(u8 duplex, int speed)
{
	struct hclge_mac *mac = &hdev->hw.mac;

	if ((speed == HCLGE_MAC_SPEED_10M) || (speed == HCLGE_MAC_SPEED_100M))
		mac->duplex = (u8)duplex;
	else
		mac->duplex = HCLGE_MAC_FULL;
	if (!(speed == HCLGE_MAC_SPEED_10M || speed == HCLGE_MAC_SPEED_100M))
		duplex = HCLGE_MAC_FULL;

	mac->speed = speed;
	return duplex;
}

int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex)
static int hclge_cfg_mac_speed_dup_hw(struct hclge_dev *hdev, int speed,
				      u8 duplex)
{
	struct hclge_config_mac_speed_dup_cmd *req;
	struct hclge_desc desc;
@@ -2138,7 +2136,23 @@ int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex)
		return ret;
	}

	hclge_check_speed_dup(hdev, duplex, speed);
	return 0;
}

int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex)
{
	int ret;

	duplex = hclge_check_speed_dup(duplex, speed);
	if (hdev->hw.mac.speed == speed && hdev->hw.mac.duplex == duplex)
		return 0;

	ret = hclge_cfg_mac_speed_dup_hw(hdev, speed, duplex);
	if (ret)
		return ret;

	hdev->hw.mac.speed = speed;
	hdev->hw.mac.duplex = duplex;

	return 0;
}
@@ -2259,7 +2273,9 @@ static int hclge_mac_init(struct hclge_dev *hdev)
	int ret;
	int i;

	ret = hclge_cfg_mac_speed_dup(hdev, hdev->hw.mac.speed, HCLGE_MAC_FULL);
	hdev->hw.mac.duplex = HCLGE_MAC_FULL;
	ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed,
					 hdev->hw.mac.duplex);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"Config mac speed dup fail ret=%d\n", ret);
@@ -2415,14 +2431,12 @@ static int hclge_update_speed_duplex(struct hclge_dev *hdev)
		return ret;
	}

	if ((mac.speed != speed) || (mac.duplex != duplex)) {
	ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"mac speed/duplex config failed %d\n", ret);
		return ret;
	}
	}

	return 0;
}
@@ -3659,6 +3673,8 @@ static int hclge_set_mac_loopback(struct hclge_dev *hdev, bool en)
	/* 2 Then setup the loopback flag */
	loop_en = le32_to_cpu(req->txrx_pad_fcs_loop_en);
	hnae3_set_bit(loop_en, HCLGE_MAC_APP_LP_B, en ? 1 : 0);
	hnae3_set_bit(loop_en, HCLGE_MAC_TX_EN_B, en ? 1 : 0);
	hnae3_set_bit(loop_en, HCLGE_MAC_RX_EN_B, en ? 1 : 0);

	req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en);

@@ -3719,15 +3735,36 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en)
		return -EIO;
	}

	hclge_cfg_mac_mode(hdev, en);
	return 0;
}

static int hclge_tqp_enable(struct hclge_dev *hdev, int tqp_id,
			    int stream_id, bool enable)
{
	struct hclge_desc desc;
	struct hclge_cfg_com_tqp_queue_cmd *req =
		(struct hclge_cfg_com_tqp_queue_cmd *)desc.data;
	int ret;

	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_COM_TQP_QUEUE, false);
	req->tqp_id = cpu_to_le16(tqp_id & HCLGE_RING_ID_MASK);
	req->stream_id = cpu_to_le16(stream_id);
	req->enable |= enable << HCLGE_TQP_ENABLE_B;

	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
	if (ret)
		dev_err(&hdev->pdev->dev,
			"Tqp enable fail, status =%d.\n", ret);
	return ret;
}

static int hclge_set_loopback(struct hnae3_handle *handle,
			      enum hnae3_loop loop_mode, bool en)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct hclge_dev *hdev = vport->back;
	int ret;
	int i, ret;

	switch (loop_mode) {
	case HNAE3_MAC_INTER_LOOP_MAC:
@@ -3743,27 +3780,13 @@ static int hclge_set_loopback(struct hnae3_handle *handle,
		break;
	}

	for (i = 0; i < vport->alloc_tqps; i++) {
		ret = hclge_tqp_enable(hdev, i, 0, en);
		if (ret)
			return ret;
	}

static int hclge_tqp_enable(struct hclge_dev *hdev, int tqp_id,
			    int stream_id, bool enable)
{
	struct hclge_desc desc;
	struct hclge_cfg_com_tqp_queue_cmd *req =
		(struct hclge_cfg_com_tqp_queue_cmd *)desc.data;
	int ret;

	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_COM_TQP_QUEUE, false);
	req->tqp_id = cpu_to_le16(tqp_id & HCLGE_RING_ID_MASK);
	req->stream_id = cpu_to_le16(stream_id);
	req->enable |= enable << HCLGE_TQP_ENABLE_B;

	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
	if (ret)
		dev_err(&hdev->pdev->dev,
			"Tqp enable fail, status =%d.\n", ret);
	return ret;
	return 0;
}

static void hclge_reset_tqp_stats(struct hnae3_handle *handle)
@@ -4362,7 +4385,7 @@ int hclge_add_mc_addr_common(struct hclge_vport *vport,
	hnae3_set_bit(req.flags, HCLGE_MAC_VLAN_BIT0_EN_B, 1);
	hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT0_EN_B, 0);
	hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT1_EN_B, 1);
	hnae3_set_bit(req.mc_mac_en, HCLGE_MAC_VLAN_BIT0_EN_B, 0);
	hnae3_set_bit(req.mc_mac_en, HCLGE_MAC_VLAN_BIT0_EN_B, 1);
	hclge_prepare_mac_addr(&req, addr);
	status = hclge_lookup_mac_vlan_tbl(vport, &req, desc, true);
	if (!status) {
@@ -4429,7 +4452,7 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport,
	hnae3_set_bit(req.flags, HCLGE_MAC_VLAN_BIT0_EN_B, 1);
	hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT0_EN_B, 0);
	hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT1_EN_B, 1);
	hnae3_set_bit(req.mc_mac_en, HCLGE_MAC_VLAN_BIT0_EN_B, 0);
	hnae3_set_bit(req.mc_mac_en, HCLGE_MAC_VLAN_BIT0_EN_B, 1);
	hclge_prepare_mac_addr(&req, addr);
	status = hclge_lookup_mac_vlan_tbl(vport, &req, desc, true);
	if (!status) {
@@ -4686,9 +4709,17 @@ static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid,
			"Add vf vlan filter fail, ret =%d.\n",
			req0->resp_code);
	} else {
#define HCLGE_VF_VLAN_DEL_NO_FOUND	1
		if (!req0->resp_code)
			return 0;

		if (req0->resp_code == HCLGE_VF_VLAN_DEL_NO_FOUND) {
			dev_warn(&hdev->pdev->dev,
				 "vlan %d filter is not in vf vlan table\n",
				 vlan);
			return 0;
		}

		dev_err(&hdev->pdev->dev,
			"Kill vf vlan filter fail, ret =%d.\n",
			req0->resp_code);
@@ -4732,6 +4763,9 @@ static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto,
	u16 vport_idx, vport_num = 0;
	int ret;

	if (is_kill && !vlan_id)
		return 0;

	ret = hclge_set_vf_vlan_common(hdev, vport_id, is_kill, vlan_id,
				       0, proto);
	if (ret) {
@@ -4761,7 +4795,7 @@ static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto,
		return -EINVAL;
	}

	for_each_set_bit(vport_idx, hdev->vlan_table[vlan_id], VLAN_N_VID)
	for_each_set_bit(vport_idx, hdev->vlan_table[vlan_id], HCLGE_VPORT_NUM)
		vport_num++;

	if ((is_kill && vport_num == 0) || (!is_kill && vport_num == 1))
@@ -5187,20 +5221,6 @@ static u32 hclge_get_fw_version(struct hnae3_handle *handle)
	return hdev->fw_version;
}

static void hclge_get_flowctrl_adv(struct hnae3_handle *handle,
				   u32 *flowctrl_adv)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct hclge_dev *hdev = vport->back;
	struct phy_device *phydev = hdev->hw.mac.phydev;

	if (!phydev)
		return;

	*flowctrl_adv |= (phydev->advertising & ADVERTISED_Pause) |
			 (phydev->advertising & ADVERTISED_Asym_Pause);
}

static void hclge_set_flowctrl_adv(struct hclge_dev *hdev, u32 rx_en, u32 tx_en)
{
	struct phy_device *phydev = hdev->hw.mac.phydev;
@@ -6301,7 +6321,6 @@ static const struct hnae3_ae_ops hclge_ops = {
	.get_tqps_and_rss_info = hclge_get_tqps_and_rss_info,
	.set_channels = hclge_set_channels,
	.get_channels = hclge_get_channels,
	.get_flowctrl_adv = hclge_get_flowctrl_adv,
	.get_regs_len = hclge_get_regs_len,
	.get_regs = hclge_get_regs,
	.set_led_id = hclge_set_led_id,