提交 7038cdb7 编写于 作者: J Julia Cartwright 提交者: David S. Miller

net: macb: reduce scope of rx_fs_lock-protected regions

Commit ae8223de ("net: macb: Added support for RX filtering")
introduces a lock, rx_fs_lock which is intended to protect the list of
rx_flow items and synchronize access to the hardware rx filtering
registers.

However, the region protected by this lock is overscoped, unnecessarily
including things like slab allocation.  Reduce this lock scope to only
include operations which must be performed atomically: list traversal,
addition, and removal, and hitting the macb filtering registers.

This fixes the use of kmalloc w/ GFP_KERNEL in atomic context.

Fixes: ae8223de ("net: macb: Added support for RX filtering")
Cc: Rafal Ozieblo <rafalo@cadence.com>
Cc: Julia Lawall <julia.lawall@lip6.fr>
Acked-by: NNicolas Ferre <nicolas.ferre@microchip.com>
Signed-off-by: NJulia Cartwright <julia@ni.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 a3da8adc
...@@ -2796,6 +2796,7 @@ static int gem_add_flow_filter(struct net_device *netdev, ...@@ -2796,6 +2796,7 @@ static int gem_add_flow_filter(struct net_device *netdev,
struct macb *bp = netdev_priv(netdev); struct macb *bp = netdev_priv(netdev);
struct ethtool_rx_flow_spec *fs = &cmd->fs; struct ethtool_rx_flow_spec *fs = &cmd->fs;
struct ethtool_rx_fs_item *item, *newfs; struct ethtool_rx_fs_item *item, *newfs;
unsigned long flags;
int ret = -EINVAL; int ret = -EINVAL;
bool added = false; bool added = false;
...@@ -2811,6 +2812,8 @@ static int gem_add_flow_filter(struct net_device *netdev, ...@@ -2811,6 +2812,8 @@ static int gem_add_flow_filter(struct net_device *netdev,
htonl(fs->h_u.tcp_ip4_spec.ip4dst), htonl(fs->h_u.tcp_ip4_spec.ip4dst),
htons(fs->h_u.tcp_ip4_spec.psrc), htons(fs->h_u.tcp_ip4_spec.pdst)); htons(fs->h_u.tcp_ip4_spec.psrc), htons(fs->h_u.tcp_ip4_spec.pdst));
spin_lock_irqsave(&bp->rx_fs_lock, flags);
/* find correct place to add in list */ /* find correct place to add in list */
list_for_each_entry(item, &bp->rx_fs_list.list, list) { list_for_each_entry(item, &bp->rx_fs_list.list, list) {
if (item->fs.location > newfs->fs.location) { if (item->fs.location > newfs->fs.location) {
...@@ -2833,9 +2836,11 @@ static int gem_add_flow_filter(struct net_device *netdev, ...@@ -2833,9 +2836,11 @@ static int gem_add_flow_filter(struct net_device *netdev,
if (netdev->features & NETIF_F_NTUPLE) if (netdev->features & NETIF_F_NTUPLE)
gem_enable_flow_filters(bp, 1); gem_enable_flow_filters(bp, 1);
spin_unlock_irqrestore(&bp->rx_fs_lock, flags);
return 0; return 0;
err: err:
spin_unlock_irqrestore(&bp->rx_fs_lock, flags);
kfree(newfs); kfree(newfs);
return ret; return ret;
} }
...@@ -2846,6 +2851,9 @@ static int gem_del_flow_filter(struct net_device *netdev, ...@@ -2846,6 +2851,9 @@ static int gem_del_flow_filter(struct net_device *netdev,
struct macb *bp = netdev_priv(netdev); struct macb *bp = netdev_priv(netdev);
struct ethtool_rx_fs_item *item; struct ethtool_rx_fs_item *item;
struct ethtool_rx_flow_spec *fs; struct ethtool_rx_flow_spec *fs;
unsigned long flags;
spin_lock_irqsave(&bp->rx_fs_lock, flags);
list_for_each_entry(item, &bp->rx_fs_list.list, list) { list_for_each_entry(item, &bp->rx_fs_list.list, list) {
if (item->fs.location == cmd->fs.location) { if (item->fs.location == cmd->fs.location) {
...@@ -2862,12 +2870,14 @@ static int gem_del_flow_filter(struct net_device *netdev, ...@@ -2862,12 +2870,14 @@ static int gem_del_flow_filter(struct net_device *netdev,
gem_writel_n(bp, SCRT2, fs->location, 0); gem_writel_n(bp, SCRT2, fs->location, 0);
list_del(&item->list); list_del(&item->list);
kfree(item);
bp->rx_fs_list.count--; bp->rx_fs_list.count--;
spin_unlock_irqrestore(&bp->rx_fs_lock, flags);
kfree(item);
return 0; return 0;
} }
} }
spin_unlock_irqrestore(&bp->rx_fs_lock, flags);
return -EINVAL; return -EINVAL;
} }
...@@ -2936,11 +2946,8 @@ static int gem_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, ...@@ -2936,11 +2946,8 @@ static int gem_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
static int gem_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) static int gem_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
{ {
struct macb *bp = netdev_priv(netdev); struct macb *bp = netdev_priv(netdev);
unsigned long flags;
int ret; int ret;
spin_lock_irqsave(&bp->rx_fs_lock, flags);
switch (cmd->cmd) { switch (cmd->cmd) {
case ETHTOOL_SRXCLSRLINS: case ETHTOOL_SRXCLSRLINS:
if ((cmd->fs.location >= bp->max_tuples) if ((cmd->fs.location >= bp->max_tuples)
...@@ -2959,7 +2966,6 @@ static int gem_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) ...@@ -2959,7 +2966,6 @@ static int gem_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
} }
spin_unlock_irqrestore(&bp->rx_fs_lock, flags);
return ret; return ret;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册