|
@@ -304,8 +304,6 @@ static const struct hclge_comm_stats_str g_mac_stats_string[] = {
|
|
|
HCLGE_MAC_STATS_FIELD_OFF(mac_tx_2048_4095_oct_pkt_num)},
|
|
|
{"mac_tx_4096_8191_oct_pkt_num",
|
|
|
HCLGE_MAC_STATS_FIELD_OFF(mac_tx_4096_8191_oct_pkt_num)},
|
|
|
- {"mac_tx_8192_12287_oct_pkt_num",
|
|
|
- HCLGE_MAC_STATS_FIELD_OFF(mac_tx_8192_12287_oct_pkt_num)},
|
|
|
{"mac_tx_8192_9216_oct_pkt_num",
|
|
|
HCLGE_MAC_STATS_FIELD_OFF(mac_tx_8192_9216_oct_pkt_num)},
|
|
|
{"mac_tx_9217_12287_oct_pkt_num",
|
|
@@ -356,8 +354,6 @@ static const struct hclge_comm_stats_str g_mac_stats_string[] = {
|
|
|
HCLGE_MAC_STATS_FIELD_OFF(mac_rx_2048_4095_oct_pkt_num)},
|
|
|
{"mac_rx_4096_8191_oct_pkt_num",
|
|
|
HCLGE_MAC_STATS_FIELD_OFF(mac_rx_4096_8191_oct_pkt_num)},
|
|
|
- {"mac_rx_8192_12287_oct_pkt_num",
|
|
|
- HCLGE_MAC_STATS_FIELD_OFF(mac_rx_8192_12287_oct_pkt_num)},
|
|
|
{"mac_rx_8192_9216_oct_pkt_num",
|
|
|
HCLGE_MAC_STATS_FIELD_OFF(mac_rx_8192_9216_oct_pkt_num)},
|
|
|
{"mac_rx_9217_12287_oct_pkt_num",
|
|
@@ -1459,8 +1455,11 @@ static int hclge_alloc_vport(struct hclge_dev *hdev)
|
|
|
/* We need to alloc a vport for main NIC of PF */
|
|
|
num_vport = hdev->num_vmdq_vport + hdev->num_req_vfs + 1;
|
|
|
|
|
|
- if (hdev->num_tqps < num_vport)
|
|
|
- num_vport = hdev->num_tqps;
|
|
|
+ if (hdev->num_tqps < num_vport) {
|
|
|
+ dev_err(&hdev->pdev->dev, "tqps(%d) is less than vports(%d)",
|
|
|
+ hdev->num_tqps, num_vport);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
|
|
|
/* Alloc the same number of TQPs for every vport */
|
|
|
tqp_per_vport = hdev->num_tqps / num_vport;
|
|
@@ -4540,8 +4539,9 @@ static void hclge_enable_vlan_filter(struct hnae3_handle *handle, bool enable)
|
|
|
hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF, enable);
|
|
|
}
|
|
|
|
|
|
-int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid,
|
|
|
- bool is_kill, u16 vlan, u8 qos, __be16 proto)
|
|
|
+static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid,
|
|
|
+ bool is_kill, u16 vlan, u8 qos,
|
|
|
+ __be16 proto)
|
|
|
{
|
|
|
#define HCLGE_MAX_VF_BYTES 16
|
|
|
struct hclge_vlan_filter_vf_cfg_cmd *req0;
|
|
@@ -4599,12 +4599,9 @@ int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid,
|
|
|
return -EIO;
|
|
|
}
|
|
|
|
|
|
-static int hclge_set_port_vlan_filter(struct hnae3_handle *handle,
|
|
|
- __be16 proto, u16 vlan_id,
|
|
|
- bool is_kill)
|
|
|
+static int hclge_set_port_vlan_filter(struct hclge_dev *hdev, __be16 proto,
|
|
|
+ u16 vlan_id, bool is_kill)
|
|
|
{
|
|
|
- struct hclge_vport *vport = hclge_get_vport(handle);
|
|
|
- struct hclge_dev *hdev = vport->back;
|
|
|
struct hclge_vlan_filter_pf_cfg_cmd *req;
|
|
|
struct hclge_desc desc;
|
|
|
u8 vlan_offset_byte_val;
|
|
@@ -4624,22 +4621,66 @@ static int hclge_set_port_vlan_filter(struct hnae3_handle *handle,
|
|
|
req->vlan_offset_bitmap[vlan_offset_byte] = vlan_offset_byte_val;
|
|
|
|
|
|
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
|
|
+ if (ret)
|
|
|
+ dev_err(&hdev->pdev->dev,
|
|
|
+ "port vlan command, send fail, ret =%d.\n", ret);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto,
|
|
|
+ u16 vport_id, u16 vlan_id, u8 qos,
|
|
|
+ bool is_kill)
|
|
|
+{
|
|
|
+ u16 vport_idx, vport_num = 0;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = hclge_set_vf_vlan_common(hdev, vport_id, is_kill, vlan_id,
|
|
|
+ 0, proto);
|
|
|
if (ret) {
|
|
|
dev_err(&hdev->pdev->dev,
|
|
|
- "port vlan command, send fail, ret =%d.\n",
|
|
|
- ret);
|
|
|
+ "Set %d vport vlan filter config fail, ret =%d.\n",
|
|
|
+ vport_id, ret);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- ret = hclge_set_vf_vlan_common(hdev, 0, is_kill, vlan_id, 0, proto);
|
|
|
- if (ret) {
|
|
|
+ /* vlan 0 may be added twice when 8021q module is enabled */
|
|
|
+ if (!is_kill && !vlan_id &&
|
|
|
+ test_bit(vport_id, hdev->vlan_table[vlan_id]))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (!is_kill && test_and_set_bit(vport_id, hdev->vlan_table[vlan_id])) {
|
|
|
dev_err(&hdev->pdev->dev,
|
|
|
- "Set pf vlan filter config fail, ret =%d.\n",
|
|
|
- ret);
|
|
|
- return -EIO;
|
|
|
+ "Add port vlan failed, vport %d is already in vlan %d\n",
|
|
|
+ vport_id, vlan_id);
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ if (is_kill &&
|
|
|
+ !test_and_clear_bit(vport_id, hdev->vlan_table[vlan_id])) {
|
|
|
+ dev_err(&hdev->pdev->dev,
|
|
|
+ "Delete port vlan failed, vport %d is not in vlan %d\n",
|
|
|
+ vport_id, vlan_id);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ for_each_set_bit(vport_idx, hdev->vlan_table[vlan_id], VLAN_N_VID)
|
|
|
+ vport_num++;
|
|
|
+
|
|
|
+ if ((is_kill && vport_num == 0) || (!is_kill && vport_num == 1))
|
|
|
+ ret = hclge_set_port_vlan_filter(hdev, proto, vlan_id,
|
|
|
+ is_kill);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
|
|
|
+ u16 vlan_id, bool is_kill)
|
|
|
+{
|
|
|
+ struct hclge_vport *vport = hclge_get_vport(handle);
|
|
|
+ struct hclge_dev *hdev = vport->back;
|
|
|
+
|
|
|
+ return hclge_set_vlan_filter_hw(hdev, proto, vport->vport_id, vlan_id,
|
|
|
+ 0, is_kill);
|
|
|
}
|
|
|
|
|
|
static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
|
|
@@ -4653,7 +4694,7 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
|
|
|
if (proto != htons(ETH_P_8021Q))
|
|
|
return -EPROTONOSUPPORT;
|
|
|
|
|
|
- return hclge_set_vf_vlan_common(hdev, vfid, false, vlan, qos, proto);
|
|
|
+ return hclge_set_vlan_filter_hw(hdev, proto, vfid, vlan, qos, false);
|
|
|
}
|
|
|
|
|
|
static int hclge_set_vlan_tx_offload_cfg(struct hclge_vport *vport)
|
|
@@ -4818,7 +4859,7 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
|
|
|
}
|
|
|
|
|
|
handle = &hdev->vport[0].nic;
|
|
|
- return hclge_set_port_vlan_filter(handle, htons(ETH_P_8021Q), 0, false);
|
|
|
+ return hclge_set_vlan_filter(handle, htons(ETH_P_8021Q), 0, false);
|
|
|
}
|
|
|
|
|
|
static int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
|
|
@@ -5166,12 +5207,6 @@ static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg,
|
|
|
struct phy_device *phydev = hdev->hw.mac.phydev;
|
|
|
u32 fc_autoneg;
|
|
|
|
|
|
- /* Only support flow control negotiation for netdev with
|
|
|
- * phy attached for now.
|
|
|
- */
|
|
|
- if (!phydev)
|
|
|
- return -EOPNOTSUPP;
|
|
|
-
|
|
|
fc_autoneg = hclge_get_autoneg(handle);
|
|
|
if (auto_neg != fc_autoneg) {
|
|
|
dev_info(&hdev->pdev->dev,
|
|
@@ -5190,6 +5225,12 @@ static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg,
|
|
|
if (!fc_autoneg)
|
|
|
return hclge_cfg_pauseparam(hdev, rx_en, tx_en);
|
|
|
|
|
|
+ /* Only support flow control negotiation for netdev with
|
|
|
+ * phy attached for now.
|
|
|
+ */
|
|
|
+ if (!phydev)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
return phy_start_aneg(phydev);
|
|
|
}
|
|
|
|
|
@@ -5427,7 +5468,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
|
|
|
hdev = devm_kzalloc(&pdev->dev, sizeof(*hdev), GFP_KERNEL);
|
|
|
if (!hdev) {
|
|
|
ret = -ENOMEM;
|
|
|
- goto err_hclge_dev;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
hdev->pdev = pdev;
|
|
@@ -5440,38 +5481,38 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
|
|
|
ret = hclge_pci_init(hdev);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "PCI init failed\n");
|
|
|
- goto err_pci_init;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
/* Firmware command queue initialize */
|
|
|
ret = hclge_cmd_queue_init(hdev);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "Cmd queue init failed, ret = %d.\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err_pci_uninit;
|
|
|
}
|
|
|
|
|
|
/* Firmware command initialize */
|
|
|
ret = hclge_cmd_init(hdev);
|
|
|
if (ret)
|
|
|
- goto err_cmd_init;
|
|
|
+ goto err_cmd_uninit;
|
|
|
|
|
|
ret = hclge_get_cap(hdev);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "get hw capability error, ret = %d.\n",
|
|
|
ret);
|
|
|
- return ret;
|
|
|
+ goto err_cmd_uninit;
|
|
|
}
|
|
|
|
|
|
ret = hclge_configure(hdev);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "Configure dev error, ret = %d.\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err_cmd_uninit;
|
|
|
}
|
|
|
|
|
|
ret = hclge_init_msi(hdev);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "Init MSI/MSI-X error, ret = %d.\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err_cmd_uninit;
|
|
|
}
|
|
|
|
|
|
ret = hclge_misc_irq_init(hdev);
|
|
@@ -5479,69 +5520,71 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
|
|
|
dev_err(&pdev->dev,
|
|
|
"Misc IRQ(vector0) init error, ret = %d.\n",
|
|
|
ret);
|
|
|
- return ret;
|
|
|
+ goto err_msi_uninit;
|
|
|
}
|
|
|
|
|
|
ret = hclge_alloc_tqps(hdev);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "Allocate TQPs error, ret = %d.\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err_msi_irq_uninit;
|
|
|
}
|
|
|
|
|
|
ret = hclge_alloc_vport(hdev);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "Allocate vport error, ret = %d.\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err_msi_irq_uninit;
|
|
|
}
|
|
|
|
|
|
ret = hclge_map_tqp(hdev);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "Map tqp error, ret = %d.\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err_sriov_disable;
|
|
|
}
|
|
|
|
|
|
- ret = hclge_mac_mdio_config(hdev);
|
|
|
- if (ret) {
|
|
|
- dev_warn(&hdev->pdev->dev,
|
|
|
- "mdio config fail ret=%d\n", ret);
|
|
|
- return ret;
|
|
|
+ if (hdev->hw.mac.media_type == HNAE3_MEDIA_TYPE_COPPER) {
|
|
|
+ ret = hclge_mac_mdio_config(hdev);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(&hdev->pdev->dev,
|
|
|
+ "mdio config fail ret=%d\n", ret);
|
|
|
+ goto err_sriov_disable;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
ret = hclge_mac_init(hdev);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "Mac init error, ret = %d\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err_mdiobus_unreg;
|
|
|
}
|
|
|
|
|
|
ret = hclge_config_tso(hdev, HCLGE_TSO_MSS_MIN, HCLGE_TSO_MSS_MAX);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "Enable tso fail, ret =%d\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err_mdiobus_unreg;
|
|
|
}
|
|
|
|
|
|
ret = hclge_init_vlan_config(hdev);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "VLAN init fail, ret =%d\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err_mdiobus_unreg;
|
|
|
}
|
|
|
|
|
|
ret = hclge_tm_schd_init(hdev);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "tm schd init fail, ret =%d\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err_mdiobus_unreg;
|
|
|
}
|
|
|
|
|
|
hclge_rss_init_cfg(hdev);
|
|
|
ret = hclge_rss_init_hw(hdev);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "Rss init fail, ret =%d\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err_mdiobus_unreg;
|
|
|
}
|
|
|
|
|
|
ret = init_mgr_tbl(hdev);
|
|
|
if (ret) {
|
|
|
dev_err(&pdev->dev, "manager table init fail, ret =%d\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err_mdiobus_unreg;
|
|
|
}
|
|
|
|
|
|
hclge_dcb_ops_set(hdev);
|
|
@@ -5564,11 +5607,24 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
|
|
|
pr_info("%s driver initialization finished.\n", HCLGE_DRIVER_NAME);
|
|
|
return 0;
|
|
|
|
|
|
-err_cmd_init:
|
|
|
+err_mdiobus_unreg:
|
|
|
+ if (hdev->hw.mac.phydev)
|
|
|
+ mdiobus_unregister(hdev->hw.mac.mdio_bus);
|
|
|
+err_sriov_disable:
|
|
|
+ if (IS_ENABLED(CONFIG_PCI_IOV))
|
|
|
+ hclge_disable_sriov(hdev);
|
|
|
+err_msi_irq_uninit:
|
|
|
+ hclge_misc_irq_uninit(hdev);
|
|
|
+err_msi_uninit:
|
|
|
+ pci_free_irq_vectors(pdev);
|
|
|
+err_cmd_uninit:
|
|
|
+ hclge_destroy_cmd_queue(&hdev->hw);
|
|
|
+err_pci_uninit:
|
|
|
+ pci_clear_master(pdev);
|
|
|
pci_release_regions(pdev);
|
|
|
-err_pci_init:
|
|
|
+ pci_disable_device(pdev);
|
|
|
pci_set_drvdata(pdev, NULL);
|
|
|
-err_hclge_dev:
|
|
|
+out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -5586,6 +5642,7 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev)
|
|
|
set_bit(HCLGE_STATE_DOWN, &hdev->state);
|
|
|
|
|
|
hclge_stats_clear(hdev);
|
|
|
+ memset(hdev->vlan_table, 0, sizeof(hdev->vlan_table));
|
|
|
|
|
|
ret = hclge_cmd_init(hdev);
|
|
|
if (ret) {
|
|
@@ -6203,7 +6260,7 @@ static const struct hnae3_ae_ops hclge_ops = {
|
|
|
.get_fw_version = hclge_get_fw_version,
|
|
|
.get_mdix_mode = hclge_get_mdix_mode,
|
|
|
.enable_vlan_filter = hclge_enable_vlan_filter,
|
|
|
- .set_vlan_filter = hclge_set_port_vlan_filter,
|
|
|
+ .set_vlan_filter = hclge_set_vlan_filter,
|
|
|
.set_vf_vlan_filter = hclge_set_vf_vlan_filter,
|
|
|
.enable_hw_strip_rxvtag = hclge_en_hw_strip_rxvtag,
|
|
|
.reset_event = hclge_reset_event,
|