aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichał Mirosław <mirq-linux@rere.qmqm.pl>2013-01-29 10:14:16 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-29 22:58:40 -0500
commitd2ed273d30c5ffd14f6b5ec7ecc751d960f832fc (patch)
tree3a127f68981cd7536303fb111ee2668af44003e9
parent29e3b1608c8dca3ae4224a26862d18ea003ccee6 (diff)
net: disallow drivers with buggy VLAN accel to register_netdevice()
Instead of jumping aroung bugs that are easily fixed just don't let them in: affected drivers should be either fixed or have NETIF_F_HW_VLAN_FILTER removed from advertised features. Quick grep in drivers/net shows two drivers that have NETIF_F_HW_VLAN_FILTER but not ndo_vlan_rx_add/kill_vid(), but those are false-positives (features are commented out). OTOH two drivers have ndo_vlan_rx_add/kill_vid() implemented but don't advertise NETIF_F_HW_VLAN_FILTER. Those are: +ethernet/cisco/enic/enic_main.c +ethernet/qlogic/qlcnic/qlcnic_main.c Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/8021q/vlan.c7
-rw-r--r--net/8021q/vlan_core.c6
-rw-r--r--net/core/dev.c8
3 files changed, 10 insertions, 11 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index babfde9f734c..addc578d5443 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -117,19 +117,12 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
117int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id) 117int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id)
118{ 118{
119 const char *name = real_dev->name; 119 const char *name = real_dev->name;
120 const struct net_device_ops *ops = real_dev->netdev_ops;
121 120
122 if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { 121 if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
123 pr_info("VLANs not supported on %s\n", name); 122 pr_info("VLANs not supported on %s\n", name);
124 return -EOPNOTSUPP; 123 return -EOPNOTSUPP;
125 } 124 }
126 125
127 if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
128 (!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) {
129 pr_info("Device %s has buggy VLAN hw accel\n", name);
130 return -EOPNOTSUPP;
131 }
132
133 if (vlan_find_dev(real_dev, vlan_id) != NULL) 126 if (vlan_find_dev(real_dev, vlan_id) != NULL)
134 return -EEXIST; 127 return -EEXIST;
135 128
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 380440b8ea89..71b64fde8dc9 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -224,8 +224,7 @@ static int __vlan_vid_add(struct vlan_info *vlan_info, unsigned short vid,
224 if (!vid_info) 224 if (!vid_info)
225 return -ENOMEM; 225 return -ENOMEM;
226 226
227 if ((dev->features & NETIF_F_HW_VLAN_FILTER) && 227 if (dev->features & NETIF_F_HW_VLAN_FILTER) {
228 ops->ndo_vlan_rx_add_vid) {
229 err = ops->ndo_vlan_rx_add_vid(dev, vid); 228 err = ops->ndo_vlan_rx_add_vid(dev, vid);
230 if (err) { 229 if (err) {
231 kfree(vid_info); 230 kfree(vid_info);
@@ -282,8 +281,7 @@ static void __vlan_vid_del(struct vlan_info *vlan_info,
282 unsigned short vid = vid_info->vid; 281 unsigned short vid = vid_info->vid;
283 int err; 282 int err;
284 283
285 if ((dev->features & NETIF_F_HW_VLAN_FILTER) && 284 if (dev->features & NETIF_F_HW_VLAN_FILTER) {
286 ops->ndo_vlan_rx_kill_vid) {
287 err = ops->ndo_vlan_rx_kill_vid(dev, vid); 285 err = ops->ndo_vlan_rx_kill_vid(dev, vid);
288 if (err) { 286 if (err) {
289 pr_warn("failed to kill vid %d for device %s\n", 287 pr_warn("failed to kill vid %d for device %s\n",
diff --git a/net/core/dev.c b/net/core/dev.c
index a83375d3af72..a87bc74e9fd0 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6054,6 +6054,14 @@ int register_netdevice(struct net_device *dev)
6054 } 6054 }
6055 } 6055 }
6056 6056
6057 if (((dev->hw_features | dev->features) & NETIF_F_HW_VLAN_FILTER) &&
6058 (!dev->netdev_ops->ndo_vlan_rx_add_vid ||
6059 !dev->netdev_ops->ndo_vlan_rx_kill_vid)) {
6060 netdev_WARN(dev, "Buggy VLAN acceleration in driver!\n");
6061 ret = -EINVAL;
6062 goto err_uninit;
6063 }
6064
6057 ret = -EBUSY; 6065 ret = -EBUSY;
6058 if (!dev->ifindex) 6066 if (!dev->ifindex)
6059 dev->ifindex = dev_new_index(net); 6067 dev->ifindex = dev_new_index(net);