|
@@ -509,16 +509,18 @@ static void hns3_nic_set_rx_mode(struct net_device *netdev)
|
|
h->netdev_flags = new_flags;
|
|
h->netdev_flags = new_flags;
|
|
}
|
|
}
|
|
|
|
|
|
-void hns3_update_promisc_mode(struct net_device *netdev, u8 promisc_flags)
|
|
|
|
|
|
+int hns3_update_promisc_mode(struct net_device *netdev, u8 promisc_flags)
|
|
{
|
|
{
|
|
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
|
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
|
struct hnae3_handle *h = priv->ae_handle;
|
|
struct hnae3_handle *h = priv->ae_handle;
|
|
|
|
|
|
if (h->ae_algo->ops->set_promisc_mode) {
|
|
if (h->ae_algo->ops->set_promisc_mode) {
|
|
- h->ae_algo->ops->set_promisc_mode(h,
|
|
|
|
- promisc_flags & HNAE3_UPE,
|
|
|
|
- promisc_flags & HNAE3_MPE);
|
|
|
|
|
|
+ return h->ae_algo->ops->set_promisc_mode(h,
|
|
|
|
+ promisc_flags & HNAE3_UPE,
|
|
|
|
+ promisc_flags & HNAE3_MPE);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
void hns3_enable_vlan_filter(struct net_device *netdev, bool enable)
|
|
void hns3_enable_vlan_filter(struct net_device *netdev, bool enable)
|
|
@@ -1494,18 +1496,22 @@ static int hns3_vlan_rx_kill_vid(struct net_device *netdev,
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-static void hns3_restore_vlan(struct net_device *netdev)
|
|
|
|
|
|
+static int hns3_restore_vlan(struct net_device *netdev)
|
|
{
|
|
{
|
|
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
|
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
|
|
|
+ int ret = 0;
|
|
u16 vid;
|
|
u16 vid;
|
|
- int ret;
|
|
|
|
|
|
|
|
for_each_set_bit(vid, priv->active_vlans, VLAN_N_VID) {
|
|
for_each_set_bit(vid, priv->active_vlans, VLAN_N_VID) {
|
|
ret = hns3_vlan_rx_add_vid(netdev, htons(ETH_P_8021Q), vid);
|
|
ret = hns3_vlan_rx_add_vid(netdev, htons(ETH_P_8021Q), vid);
|
|
- if (ret)
|
|
|
|
- netdev_warn(netdev, "Restore vlan: %d filter, ret:%d\n",
|
|
|
|
- vid, ret);
|
|
|
|
|
|
+ if (ret) {
|
|
|
|
+ netdev_err(netdev, "Restore vlan: %d filter, ret:%d\n",
|
|
|
|
+ vid, ret);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
static int hns3_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
|
|
static int hns3_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
|
|
@@ -2727,7 +2733,7 @@ static int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
|
|
chain = devm_kzalloc(&pdev->dev, sizeof(*chain),
|
|
chain = devm_kzalloc(&pdev->dev, sizeof(*chain),
|
|
GFP_KERNEL);
|
|
GFP_KERNEL);
|
|
if (!chain)
|
|
if (!chain)
|
|
- return -ENOMEM;
|
|
|
|
|
|
+ goto err_free_chain;
|
|
|
|
|
|
cur_chain->next = chain;
|
|
cur_chain->next = chain;
|
|
chain->tqp_index = tx_ring->tqp->tqp_index;
|
|
chain->tqp_index = tx_ring->tqp->tqp_index;
|
|
@@ -2757,7 +2763,7 @@ static int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
|
|
while (rx_ring) {
|
|
while (rx_ring) {
|
|
chain = devm_kzalloc(&pdev->dev, sizeof(*chain), GFP_KERNEL);
|
|
chain = devm_kzalloc(&pdev->dev, sizeof(*chain), GFP_KERNEL);
|
|
if (!chain)
|
|
if (!chain)
|
|
- return -ENOMEM;
|
|
|
|
|
|
+ goto err_free_chain;
|
|
|
|
|
|
cur_chain->next = chain;
|
|
cur_chain->next = chain;
|
|
chain->tqp_index = rx_ring->tqp->tqp_index;
|
|
chain->tqp_index = rx_ring->tqp->tqp_index;
|
|
@@ -2772,6 +2778,16 @@ static int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
+
|
|
|
|
+err_free_chain:
|
|
|
|
+ cur_chain = head->next;
|
|
|
|
+ while (cur_chain) {
|
|
|
|
+ chain = cur_chain->next;
|
|
|
|
+ devm_kfree(&pdev->dev, chain);
|
|
|
|
+ cur_chain = chain;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return -ENOMEM;
|
|
}
|
|
}
|
|
|
|
|
|
static void hns3_free_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
|
|
static void hns3_free_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
|
|
@@ -2821,7 +2837,7 @@ static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv)
|
|
struct hnae3_handle *h = priv->ae_handle;
|
|
struct hnae3_handle *h = priv->ae_handle;
|
|
struct hns3_enet_tqp_vector *tqp_vector;
|
|
struct hns3_enet_tqp_vector *tqp_vector;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
- u16 i;
|
|
|
|
|
|
+ int i;
|
|
|
|
|
|
hns3_nic_set_cpumask(priv);
|
|
hns3_nic_set_cpumask(priv);
|
|
|
|
|
|
@@ -2868,13 +2884,19 @@ static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv)
|
|
hns3_free_vector_ring_chain(tqp_vector, &vector_ring_chain);
|
|
hns3_free_vector_ring_chain(tqp_vector, &vector_ring_chain);
|
|
|
|
|
|
if (ret)
|
|
if (ret)
|
|
- return ret;
|
|
|
|
|
|
+ goto map_ring_fail;
|
|
|
|
|
|
netif_napi_add(priv->netdev, &tqp_vector->napi,
|
|
netif_napi_add(priv->netdev, &tqp_vector->napi,
|
|
hns3_nic_common_poll, NAPI_POLL_WEIGHT);
|
|
hns3_nic_common_poll, NAPI_POLL_WEIGHT);
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
+
|
|
|
|
+map_ring_fail:
|
|
|
|
+ while (i--)
|
|
|
|
+ netif_napi_del(&priv->tqp_vector[i].napi);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
static int hns3_nic_alloc_vector_data(struct hns3_nic_priv *priv)
|
|
static int hns3_nic_alloc_vector_data(struct hns3_nic_priv *priv)
|
|
@@ -3031,8 +3053,10 @@ static int hns3_queue_to_ring(struct hnae3_queue *tqp,
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
ret = hns3_ring_get_cfg(tqp, priv, HNAE3_RING_TYPE_RX);
|
|
ret = hns3_ring_get_cfg(tqp, priv, HNAE3_RING_TYPE_RX);
|
|
- if (ret)
|
|
|
|
|
|
+ if (ret) {
|
|
|
|
+ devm_kfree(priv->dev, priv->ring_data[tqp->tqp_index].ring);
|
|
return ret;
|
|
return ret;
|
|
|
|
+ }
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -3059,6 +3083,12 @@ static int hns3_get_ring_config(struct hns3_nic_priv *priv)
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
err:
|
|
err:
|
|
|
|
+ while (i--) {
|
|
|
|
+ devm_kfree(priv->dev, priv->ring_data[i].ring);
|
|
|
|
+ devm_kfree(priv->dev,
|
|
|
|
+ priv->ring_data[i + h->kinfo.num_tqps].ring);
|
|
|
|
+ }
|
|
|
|
+
|
|
devm_kfree(&pdev->dev, priv->ring_data);
|
|
devm_kfree(&pdev->dev, priv->ring_data);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -3226,9 +3256,6 @@ int hns3_uninit_all_ring(struct hns3_nic_priv *priv)
|
|
int i;
|
|
int i;
|
|
|
|
|
|
for (i = 0; i < h->kinfo.num_tqps; i++) {
|
|
for (i = 0; i < h->kinfo.num_tqps; i++) {
|
|
- if (h->ae_algo->ops->reset_queue)
|
|
|
|
- h->ae_algo->ops->reset_queue(h, i);
|
|
|
|
-
|
|
|
|
hns3_fini_ring(priv->ring_data[i].ring);
|
|
hns3_fini_ring(priv->ring_data[i].ring);
|
|
hns3_fini_ring(priv->ring_data[i + h->kinfo.num_tqps].ring);
|
|
hns3_fini_ring(priv->ring_data[i + h->kinfo.num_tqps].ring);
|
|
}
|
|
}
|
|
@@ -3236,11 +3263,12 @@ int hns3_uninit_all_ring(struct hns3_nic_priv *priv)
|
|
}
|
|
}
|
|
|
|
|
|
/* Set mac addr if it is configured. or leave it to the AE driver */
|
|
/* Set mac addr if it is configured. or leave it to the AE driver */
|
|
-static void hns3_init_mac_addr(struct net_device *netdev, bool init)
|
|
|
|
|
|
+static int hns3_init_mac_addr(struct net_device *netdev, bool init)
|
|
{
|
|
{
|
|
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
|
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
|
struct hnae3_handle *h = priv->ae_handle;
|
|
struct hnae3_handle *h = priv->ae_handle;
|
|
u8 mac_addr_temp[ETH_ALEN];
|
|
u8 mac_addr_temp[ETH_ALEN];
|
|
|
|
+ int ret = 0;
|
|
|
|
|
|
if (h->ae_algo->ops->get_mac_addr && init) {
|
|
if (h->ae_algo->ops->get_mac_addr && init) {
|
|
h->ae_algo->ops->get_mac_addr(h, mac_addr_temp);
|
|
h->ae_algo->ops->get_mac_addr(h, mac_addr_temp);
|
|
@@ -3255,8 +3283,9 @@ static void hns3_init_mac_addr(struct net_device *netdev, bool init)
|
|
}
|
|
}
|
|
|
|
|
|
if (h->ae_algo->ops->set_mac_addr)
|
|
if (h->ae_algo->ops->set_mac_addr)
|
|
- h->ae_algo->ops->set_mac_addr(h, netdev->dev_addr, true);
|
|
|
|
|
|
+ ret = h->ae_algo->ops->set_mac_addr(h, netdev->dev_addr, true);
|
|
|
|
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
static int hns3_restore_fd_rules(struct net_device *netdev)
|
|
static int hns3_restore_fd_rules(struct net_device *netdev)
|
|
@@ -3469,20 +3498,29 @@ err_out:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-static void hns3_recover_hw_addr(struct net_device *ndev)
|
|
|
|
|
|
+static int hns3_recover_hw_addr(struct net_device *ndev)
|
|
{
|
|
{
|
|
struct netdev_hw_addr_list *list;
|
|
struct netdev_hw_addr_list *list;
|
|
struct netdev_hw_addr *ha, *tmp;
|
|
struct netdev_hw_addr *ha, *tmp;
|
|
|
|
+ int ret = 0;
|
|
|
|
|
|
/* go through and sync uc_addr entries to the device */
|
|
/* go through and sync uc_addr entries to the device */
|
|
list = &ndev->uc;
|
|
list = &ndev->uc;
|
|
- list_for_each_entry_safe(ha, tmp, &list->list, list)
|
|
|
|
- hns3_nic_uc_sync(ndev, ha->addr);
|
|
|
|
|
|
+ list_for_each_entry_safe(ha, tmp, &list->list, list) {
|
|
|
|
+ ret = hns3_nic_uc_sync(ndev, ha->addr);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
|
|
/* go through and sync mc_addr entries to the device */
|
|
/* go through and sync mc_addr entries to the device */
|
|
list = &ndev->mc;
|
|
list = &ndev->mc;
|
|
- list_for_each_entry_safe(ha, tmp, &list->list, list)
|
|
|
|
- hns3_nic_mc_sync(ndev, ha->addr);
|
|
|
|
|
|
+ list_for_each_entry_safe(ha, tmp, &list->list, list) {
|
|
|
|
+ ret = hns3_nic_mc_sync(ndev, ha->addr);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
static void hns3_remove_hw_addr(struct net_device *netdev)
|
|
static void hns3_remove_hw_addr(struct net_device *netdev)
|
|
@@ -3609,7 +3647,10 @@ int hns3_nic_reset_all_ring(struct hnae3_handle *h)
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
for (i = 0; i < h->kinfo.num_tqps; i++) {
|
|
for (i = 0; i < h->kinfo.num_tqps; i++) {
|
|
- h->ae_algo->ops->reset_queue(h, i);
|
|
|
|
|
|
+ ret = h->ae_algo->ops->reset_queue(h, i);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
hns3_init_ring_hw(priv->ring_data[i].ring);
|
|
hns3_init_ring_hw(priv->ring_data[i].ring);
|
|
|
|
|
|
/* We need to clear tx ring here because self test will
|
|
/* We need to clear tx ring here because self test will
|
|
@@ -3701,18 +3742,30 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle)
|
|
bool vlan_filter_enable;
|
|
bool vlan_filter_enable;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- hns3_init_mac_addr(netdev, false);
|
|
|
|
- hns3_recover_hw_addr(netdev);
|
|
|
|
- hns3_update_promisc_mode(netdev, handle->netdev_flags);
|
|
|
|
|
|
+ ret = hns3_init_mac_addr(netdev, false);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
|
|
+ ret = hns3_recover_hw_addr(netdev);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
|
|
+ ret = hns3_update_promisc_mode(netdev, handle->netdev_flags);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
vlan_filter_enable = netdev->flags & IFF_PROMISC ? false : true;
|
|
vlan_filter_enable = netdev->flags & IFF_PROMISC ? false : true;
|
|
hns3_enable_vlan_filter(netdev, vlan_filter_enable);
|
|
hns3_enable_vlan_filter(netdev, vlan_filter_enable);
|
|
|
|
|
|
-
|
|
|
|
/* Hardware table is only clear when pf resets */
|
|
/* Hardware table is only clear when pf resets */
|
|
- if (!(handle->flags & HNAE3_SUPPORT_VF))
|
|
|
|
- hns3_restore_vlan(netdev);
|
|
|
|
|
|
+ if (!(handle->flags & HNAE3_SUPPORT_VF)) {
|
|
|
|
+ ret = hns3_restore_vlan(netdev);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
|
|
- hns3_restore_fd_rules(netdev);
|
|
|
|
|
|
+ ret = hns3_restore_fd_rules(netdev);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
|
|
/* Carrier off reporting is important to ethtool even BEFORE open */
|
|
/* Carrier off reporting is important to ethtool even BEFORE open */
|
|
netif_carrier_off(netdev);
|
|
netif_carrier_off(netdev);
|