Commit ffab9691 authored by Jian Shen's avatar Jian Shen Committed by David S. Miller

net: hns3: initialize CPU reverse mapping

Allocate CPU rmap and add entry for each irq. CPU rmap is
used in aRFS to get the queue number of the rx completion
interrupts.

In additional, remove the calling of
irq_set_affinity_notifier() in hns3_nic_init_irq(), because
we have registered notifier in irq_cpu_rmap_add() for each
vector, otherwise it may cause use-after-free issue.
Signed-off-by: default avatarJian Shen <shenjian15@huawei.com>
Signed-off-by: default avatarHuazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 18e88171
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#ifdef CONFIG_RFS_ACCEL
#include <linux/cpu_rmap.h>
#endif
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
...@@ -79,23 +82,6 @@ static irqreturn_t hns3_irq_handle(int irq, void *vector) ...@@ -79,23 +82,6 @@ static irqreturn_t hns3_irq_handle(int irq, void *vector)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/* This callback function is used to set affinity changes to the irq affinity
* masks when the irq_set_affinity_notifier function is used.
*/
static void hns3_nic_irq_affinity_notify(struct irq_affinity_notify *notify,
const cpumask_t *mask)
{
struct hns3_enet_tqp_vector *tqp_vectors =
container_of(notify, struct hns3_enet_tqp_vector,
affinity_notify);
tqp_vectors->affinity_mask = *mask;
}
static void hns3_nic_irq_affinity_release(struct kref *ref)
{
}
static void hns3_nic_uninit_irq(struct hns3_nic_priv *priv) static void hns3_nic_uninit_irq(struct hns3_nic_priv *priv)
{ {
struct hns3_enet_tqp_vector *tqp_vectors; struct hns3_enet_tqp_vector *tqp_vectors;
...@@ -107,8 +93,7 @@ static void hns3_nic_uninit_irq(struct hns3_nic_priv *priv) ...@@ -107,8 +93,7 @@ static void hns3_nic_uninit_irq(struct hns3_nic_priv *priv)
if (tqp_vectors->irq_init_flag != HNS3_VECTOR_INITED) if (tqp_vectors->irq_init_flag != HNS3_VECTOR_INITED)
continue; continue;
/* clear the affinity notifier and affinity mask */ /* clear the affinity mask */
irq_set_affinity_notifier(tqp_vectors->vector_irq, NULL);
irq_set_affinity_hint(tqp_vectors->vector_irq, NULL); irq_set_affinity_hint(tqp_vectors->vector_irq, NULL);
/* release the irq resource */ /* release the irq resource */
...@@ -161,12 +146,6 @@ static int hns3_nic_init_irq(struct hns3_nic_priv *priv) ...@@ -161,12 +146,6 @@ static int hns3_nic_init_irq(struct hns3_nic_priv *priv)
return ret; return ret;
} }
tqp_vectors->affinity_notify.notify =
hns3_nic_irq_affinity_notify;
tqp_vectors->affinity_notify.release =
hns3_nic_irq_affinity_release;
irq_set_affinity_notifier(tqp_vectors->vector_irq,
&tqp_vectors->affinity_notify);
irq_set_affinity_hint(tqp_vectors->vector_irq, irq_set_affinity_hint(tqp_vectors->vector_irq,
&tqp_vectors->affinity_mask); &tqp_vectors->affinity_mask);
...@@ -340,6 +319,40 @@ static void hns3_tqp_disable(struct hnae3_queue *tqp) ...@@ -340,6 +319,40 @@ static void hns3_tqp_disable(struct hnae3_queue *tqp)
hns3_write_dev(tqp, HNS3_RING_EN_REG, rcb_reg); hns3_write_dev(tqp, HNS3_RING_EN_REG, rcb_reg);
} }
static void hns3_free_rx_cpu_rmap(struct net_device *netdev)
{
#ifdef CONFIG_RFS_ACCEL
free_irq_cpu_rmap(netdev->rx_cpu_rmap);
netdev->rx_cpu_rmap = NULL;
#endif
}
static int hns3_set_rx_cpu_rmap(struct net_device *netdev)
{
#ifdef CONFIG_RFS_ACCEL
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hns3_enet_tqp_vector *tqp_vector;
int i, ret;
if (!netdev->rx_cpu_rmap) {
netdev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->vector_num);
if (!netdev->rx_cpu_rmap)
return -ENOMEM;
}
for (i = 0; i < priv->vector_num; i++) {
tqp_vector = &priv->tqp_vector[i];
ret = irq_cpu_rmap_add(netdev->rx_cpu_rmap,
tqp_vector->vector_irq);
if (ret) {
hns3_free_rx_cpu_rmap(netdev);
return ret;
}
}
#endif
return 0;
}
static int hns3_nic_net_up(struct net_device *netdev) static int hns3_nic_net_up(struct net_device *netdev)
{ {
struct hns3_nic_priv *priv = netdev_priv(netdev); struct hns3_nic_priv *priv = netdev_priv(netdev);
...@@ -351,11 +364,16 @@ static int hns3_nic_net_up(struct net_device *netdev) ...@@ -351,11 +364,16 @@ static int hns3_nic_net_up(struct net_device *netdev)
if (ret) if (ret)
return ret; return ret;
/* the device can work without cpu rmap, only aRFS needs it */
ret = hns3_set_rx_cpu_rmap(netdev);
if (ret)
netdev_warn(netdev, "set rx cpu rmap fail, ret=%d!\n", ret);
/* get irq resource for all vectors */ /* get irq resource for all vectors */
ret = hns3_nic_init_irq(priv); ret = hns3_nic_init_irq(priv);
if (ret) { if (ret) {
netdev_err(netdev, "hns init irq failed! ret=%d\n", ret); netdev_err(netdev, "hns init irq failed! ret=%d\n", ret);
return ret; goto free_rmap;
} }
clear_bit(HNS3_NIC_STATE_DOWN, &priv->state); clear_bit(HNS3_NIC_STATE_DOWN, &priv->state);
...@@ -384,7 +402,8 @@ static int hns3_nic_net_up(struct net_device *netdev) ...@@ -384,7 +402,8 @@ static int hns3_nic_net_up(struct net_device *netdev)
hns3_vector_disable(&priv->tqp_vector[j]); hns3_vector_disable(&priv->tqp_vector[j]);
hns3_nic_uninit_irq(priv); hns3_nic_uninit_irq(priv);
free_rmap:
hns3_free_rx_cpu_rmap(netdev);
return ret; return ret;
} }
...@@ -467,6 +486,8 @@ static void hns3_nic_net_down(struct net_device *netdev) ...@@ -467,6 +486,8 @@ static void hns3_nic_net_down(struct net_device *netdev)
if (ops->stop) if (ops->stop)
ops->stop(priv->ae_handle); ops->stop(priv->ae_handle);
hns3_free_rx_cpu_rmap(netdev);
/* free irq resources */ /* free irq resources */
hns3_nic_uninit_irq(priv); hns3_nic_uninit_irq(priv);
...@@ -3331,8 +3352,6 @@ static void hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv) ...@@ -3331,8 +3352,6 @@ static void hns3_nic_uninit_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 (tqp_vector->irq_init_flag == HNS3_VECTOR_INITED) { if (tqp_vector->irq_init_flag == HNS3_VECTOR_INITED) {
irq_set_affinity_notifier(tqp_vector->vector_irq,
NULL);
irq_set_affinity_hint(tqp_vector->vector_irq, NULL); irq_set_affinity_hint(tqp_vector->vector_irq, NULL);
free_irq(tqp_vector->vector_irq, tqp_vector); free_irq(tqp_vector->vector_irq, tqp_vector);
tqp_vector->irq_init_flag = HNS3_VECTOR_NOT_INITED; tqp_vector->irq_init_flag = HNS3_VECTOR_NOT_INITED;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment