* [RFC PATCH 2/7] vlan: Centralize handling of hardware acceleration.
From: Jesse Gross @ 2010-10-13 20:02 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1287000177-7126-1-git-send-email-jesse@nicira.com>
Currently each driver that is capable of vlan hardware acceleration
must be aware of the vlan groups that are configured and then pass
the stripped tag to a specialized receive function. This is
different from other types of hardware offload in that it places a
significant amount of knowledge in the driver itself rather keeping
it in the networking core.
This makes vlan offloading function more similarly to other forms
of offloading (such as checksum offloading or TSO) by doing the
following:
* On receive, stripped vlans are passed directly to the network
core, without attempting to check for vlan groups or reconstructing
the header if no group
* vlans are made less special by folding the logic into the main
receive routines
* On transmit, the device layer will add the vlan header in software
if the hardware doesn't support it, instead of spreading that logic
out in upper layers, such as bonding.
There are a number of advantages to this:
* Fixes all bugs with drivers incorrectly dropping vlan headers at once.
* Avoids having to disable VLAN acceleration when in promiscuous mode
(good for bridging since it always puts devices in promiscuous mode).
* Keeps VLAN tag separate until given to ultimate consumer, which
avoids needing to do header reconstruction as in tg3 unless absolutely
necessary.
* Consolidates common code in core networking.
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
include/linux/if_vlan.h | 27 ++++++++-
include/linux/netdevice.h | 12 +++-
net/8021q/vlan.c | 102 ++++++++-----------------------
net/8021q/vlan.h | 17 -----
net/8021q/vlan_core.c | 125 +++++++++------------------------------
net/8021q/vlan_dev.c | 2 +-
net/bridge/netfilter/ebt_vlan.c | 4 +-
net/core/dev.c | 42 ++++++++++++--
8 files changed, 129 insertions(+), 202 deletions(-)
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index a523207..e21028b 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -68,6 +68,7 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
#define VLAN_CFI_MASK 0x1000 /* Canonical Format Indicator */
#define VLAN_TAG_PRESENT VLAN_CFI_MASK
#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */
+#define VLAN_N_VID 4096
/* found in socket.c */
extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
@@ -76,7 +77,7 @@ extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
* depends on completely exhausting the VLAN identifier space. Thus
* it gives constant time look-up, but in many cases it wastes memory.
*/
-#define VLAN_GROUP_ARRAY_LEN 4096
+#define VLAN_GROUP_ARRAY_LEN VLAN_N_VID
#define VLAN_GROUP_ARRAY_SPLIT_PARTS 8
#define VLAN_GROUP_ARRAY_PART_LEN (VLAN_GROUP_ARRAY_LEN/VLAN_GROUP_ARRAY_SPLIT_PARTS)
@@ -114,12 +115,24 @@ static inline void vlan_group_set_device(struct vlan_group *vg,
#define vlan_tx_tag_get(__skb) ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT)
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+/* Must be invoked with rcu_read_lock or with RTNL. */
+static inline struct net_device *vlan_find_dev(struct net_device *real_dev,
+ u16 vlan_id)
+{
+ struct vlan_group *grp = rcu_dereference(real_dev->vlgrp);
+
+ if (grp)
+ return vlan_group_get_device(grp, vlan_id);
+
+ return NULL;
+}
+
extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
extern u16 vlan_dev_vlan_id(const struct net_device *dev);
extern int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
u16 vlan_tci, int polling);
-extern void vlan_hwaccel_do_receive(struct sk_buff *skb);
+extern int vlan_hwaccel_do_receive(struct sk_buff *skb);
extern gro_result_t
vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
unsigned int vlan_tci, struct sk_buff *skb);
@@ -128,6 +141,12 @@ vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
unsigned int vlan_tci);
#else
+static inline struct net_device *vlan_find_dev(struct net_device *real_dev,
+ u16 vlan_id)
+{
+ return NULL;
+}
+
static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev)
{
BUG();
@@ -147,8 +166,10 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
return NET_XMIT_SUCCESS;
}
-static inline void vlan_hwaccel_do_receive(struct sk_buff *skb)
+static inline int vlan_hwaccel_do_receive(struct sk_buff *skb)
{
+ BUG();
+ return 0;
}
static inline gro_result_t
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 14fbb04..ef4bbcb 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -942,7 +942,10 @@ struct net_device {
/* Protocol specific pointers */
-
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+ struct vlan_group *vlgrp; /* VLAN group */
+#endif
#ifdef CONFIG_NET_DSA
void *dsa_ptr; /* dsa specific data */
#endif
@@ -2248,8 +2251,13 @@ static inline int skb_gso_ok(struct sk_buff *skb, int features)
static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
{
+ int features = dev->features;
+
+ if (skb->protocol == htons(ETH_P_8021Q) || skb->vlan_tci)
+ features &= dev->vlan_features;
+
return skb_is_gso(skb) &&
- (!skb_gso_ok(skb, dev->features) ||
+ (!skb_gso_ok(skb, features) ||
unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
}
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 25c2133..77634b9 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -44,9 +44,6 @@
int vlan_net_id __read_mostly;
-/* Our listing of VLAN group(s) */
-static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
-
const char vlan_fullname[] = "802.1Q VLAN Support";
const char vlan_version[] = DRV_VERSION;
static const char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
@@ -59,40 +56,6 @@ static struct packet_type vlan_packet_type __read_mostly = {
/* End of global variables definitions. */
-static inline unsigned int vlan_grp_hashfn(unsigned int idx)
-{
- return ((idx >> VLAN_GRP_HASH_SHIFT) ^ idx) & VLAN_GRP_HASH_MASK;
-}
-
-/* Must be invoked with RCU read lock (no preempt) */
-static struct vlan_group *__vlan_find_group(struct net_device *real_dev)
-{
- struct vlan_group *grp;
- struct hlist_node *n;
- int hash = vlan_grp_hashfn(real_dev->ifindex);
-
- hlist_for_each_entry_rcu(grp, n, &vlan_group_hash[hash], hlist) {
- if (grp->real_dev == real_dev)
- return grp;
- }
-
- return NULL;
-}
-
-/* Find the protocol handler. Assumes VID < VLAN_VID_MASK.
- *
- * Must be invoked with RCU read lock (no preempt)
- */
-struct net_device *__find_vlan_dev(struct net_device *real_dev, u16 vlan_id)
-{
- struct vlan_group *grp = __vlan_find_group(real_dev);
-
- if (grp)
- return vlan_group_get_device(grp, vlan_id);
-
- return NULL;
-}
-
static void vlan_group_free(struct vlan_group *grp)
{
int i;
@@ -111,8 +74,6 @@ static struct vlan_group *vlan_group_alloc(struct net_device *real_dev)
return NULL;
grp->real_dev = real_dev;
- hlist_add_head_rcu(&grp->hlist,
- &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
return grp;
}
@@ -146,13 +107,10 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
struct vlan_dev_info *vlan = vlan_dev_info(dev);
struct net_device *real_dev = vlan->real_dev;
const struct net_device_ops *ops = real_dev->netdev_ops;
- struct vlan_group *grp;
u16 vlan_id = vlan->vlan_id;
ASSERT_RTNL();
-
- grp = __vlan_find_group(real_dev);
- BUG_ON(!grp);
+ BUG_ON(!real_dev->vlgrp);
/* Take it out of our own structures, but be sure to interlock with
* HW accelerating devices or SW vlan input packet processing if
@@ -161,25 +119,26 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
if (vlan_id && (real_dev->features & NETIF_F_HW_VLAN_FILTER))
ops->ndo_vlan_rx_kill_vid(real_dev, vlan_id);
- grp->nr_vlans--;
+ real_dev->vlgrp->nr_vlans--;
- vlan_group_set_device(grp, vlan_id, NULL);
- if (!grp->killall)
+ vlan_group_set_device(real_dev->vlgrp, vlan_id, NULL);
+ if (!real_dev->vlgrp->killall)
synchronize_net();
unregister_netdevice_queue(dev, head);
/* If the group is now empty, kill off the group. */
- if (grp->nr_vlans == 0) {
- vlan_gvrp_uninit_applicant(real_dev);
+ if (real_dev->vlgrp->nr_vlans == 0) {
+ struct vlan_group *vlgrp = real_dev->vlgrp;
- if (real_dev->features & NETIF_F_HW_VLAN_RX)
+ rcu_assign_pointer(real_dev->vlgrp, NULL);
+ if (ops->ndo_vlan_rx_register)
ops->ndo_vlan_rx_register(real_dev, NULL);
- hlist_del_rcu(&grp->hlist);
+ vlan_gvrp_uninit_applicant(real_dev);
/* Free the group, after all cpu's are done. */
- call_rcu(&grp->rcu, vlan_rcu_free);
+ call_rcu(&vlgrp->rcu, vlan_rcu_free);
}
/* Get rid of the vlan's reference to real_dev */
@@ -196,18 +155,13 @@ int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id)
return -EOPNOTSUPP;
}
- if ((real_dev->features & NETIF_F_HW_VLAN_RX) && !ops->ndo_vlan_rx_register) {
- pr_info("8021q: device %s has buggy VLAN hw accel\n", name);
- return -EOPNOTSUPP;
- }
-
if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
(!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) {
pr_info("8021q: Device %s has buggy VLAN hw accel\n", name);
return -EOPNOTSUPP;
}
- if (__find_vlan_dev(real_dev, vlan_id) != NULL)
+ if (vlan_find_dev(real_dev, vlan_id) != NULL)
return -EEXIST;
return 0;
@@ -222,7 +176,7 @@ int register_vlan_dev(struct net_device *dev)
struct vlan_group *grp, *ngrp = NULL;
int err;
- grp = __vlan_find_group(real_dev);
+ grp = real_dev->vlgrp;
if (!grp) {
ngrp = grp = vlan_group_alloc(real_dev);
if (!grp)
@@ -252,8 +206,11 @@ int register_vlan_dev(struct net_device *dev)
vlan_group_set_device(grp, vlan_id, dev);
grp->nr_vlans++;
- if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
- ops->ndo_vlan_rx_register(real_dev, ngrp);
+ if (ngrp) {
+ if (ops->ndo_vlan_rx_register)
+ ops->ndo_vlan_rx_register(real_dev, ngrp);
+ rcu_assign_pointer(real_dev->vlgrp, ngrp);
+ }
if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
ops->ndo_vlan_rx_add_vid(real_dev, vlan_id);
@@ -264,7 +221,6 @@ out_uninit_applicant:
vlan_gvrp_uninit_applicant(real_dev);
out_free_group:
if (ngrp) {
- hlist_del_rcu(&ngrp->hlist);
/* Free the group, after all cpu's are done. */
call_rcu(&ngrp->rcu, vlan_rcu_free);
}
@@ -428,7 +384,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0);
}
- grp = __vlan_find_group(dev);
+ grp = dev->vlgrp;
if (!grp)
goto out;
@@ -439,7 +395,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
switch (event) {
case NETDEV_CHANGE:
/* Propagate real device state to vlan devices */
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ for (i = 0; i < VLAN_N_VID; i++) {
vlandev = vlan_group_get_device(grp, i);
if (!vlandev)
continue;
@@ -450,7 +406,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
case NETDEV_CHANGEADDR:
/* Adjust unicast filters on underlying device */
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ for (i = 0; i < VLAN_N_VID; i++) {
vlandev = vlan_group_get_device(grp, i);
if (!vlandev)
continue;
@@ -464,7 +420,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
break;
case NETDEV_CHANGEMTU:
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ for (i = 0; i < VLAN_N_VID; i++) {
vlandev = vlan_group_get_device(grp, i);
if (!vlandev)
continue;
@@ -478,7 +434,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
case NETDEV_FEAT_CHANGE:
/* Propagate device features to underlying device */
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ for (i = 0; i < VLAN_N_VID; i++) {
vlandev = vlan_group_get_device(grp, i);
if (!vlandev)
continue;
@@ -490,7 +446,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
case NETDEV_DOWN:
/* Put all VLANs for this dev in the down state too. */
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ for (i = 0; i < VLAN_N_VID; i++) {
vlandev = vlan_group_get_device(grp, i);
if (!vlandev)
continue;
@@ -508,7 +464,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
case NETDEV_UP:
/* Put all VLANs for this dev in the up state too. */
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ for (i = 0; i < VLAN_N_VID; i++) {
vlandev = vlan_group_get_device(grp, i);
if (!vlandev)
continue;
@@ -532,7 +488,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
/* Delete all VLANs for this dev. */
grp->killall = 1;
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ for (i = 0; i < VLAN_N_VID; i++) {
vlandev = vlan_group_get_device(grp, i);
if (!vlandev)
continue;
@@ -540,7 +496,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
/* unregistration of last vlan destroys group, abort
* afterwards */
if (grp->nr_vlans == 1)
- i = VLAN_GROUP_ARRAY_LEN;
+ i = VLAN_N_VID;
unregister_vlan_dev(vlandev, &list);
}
@@ -746,8 +702,6 @@ err0:
static void __exit vlan_cleanup_module(void)
{
- unsigned int i;
-
vlan_ioctl_set(NULL);
vlan_netlink_fini();
@@ -755,10 +709,6 @@ static void __exit vlan_cleanup_module(void)
dev_remove_pack(&vlan_packet_type);
- /* This table must be empty if there are no module references left. */
- for (i = 0; i < VLAN_GRP_HASH_SIZE; i++)
- BUG_ON(!hlist_empty(&vlan_group_hash[i]));
-
unregister_pernet_subsys(&vlan_net_ops);
rcu_barrier(); /* Wait for completion of call_rcu()'s */
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 8d9503a..db01b31 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -72,23 +72,6 @@ static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev)
return netdev_priv(dev);
}
-#define VLAN_GRP_HASH_SHIFT 5
-#define VLAN_GRP_HASH_SIZE (1 << VLAN_GRP_HASH_SHIFT)
-#define VLAN_GRP_HASH_MASK (VLAN_GRP_HASH_SIZE - 1)
-
-/* Find a VLAN device by the MAC address of its Ethernet device, and
- * it's VLAN ID. The default configuration is to have VLAN's scope
- * to be box-wide, so the MAC will be ignored. The mac will only be
- * looked at if we are configured to have a separate set of VLANs per
- * each MAC addressable interface. Note that this latter option does
- * NOT follow the spec for VLANs, but may be useful for doing very
- * large quantities of VLAN MUX/DEMUX onto FrameRelay or ATM PVCs.
- *
- * Must be invoked with rcu_read_lock (ie preempt disabled)
- * or with RTNL.
- */
-struct net_device *__find_vlan_dev(struct net_device *real_dev, u16 vlan_id);
-
/* found in vlan_dev.c */
int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *ptype, struct net_device *orig_dev);
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index dee727c..df90412 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -4,54 +4,33 @@
#include <linux/netpoll.h>
#include "vlan.h"
-/* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */
-int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
- u16 vlan_tci, int polling)
+int vlan_hwaccel_do_receive(struct sk_buff *skb)
{
+ u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK;
struct net_device *vlan_dev;
- u16 vlan_id;
-
- if (netpoll_rx(skb))
- return NET_RX_DROP;
-
- if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
- skb->deliver_no_wcard = 1;
-
- skb->skb_iif = skb->dev->ifindex;
- __vlan_hwaccel_put_tag(skb, vlan_tci);
- vlan_id = vlan_tci & VLAN_VID_MASK;
- vlan_dev = vlan_group_get_device(grp, vlan_id);
+ struct vlan_rx_stats *rx_stats;
- if (vlan_dev)
- skb->dev = vlan_dev;
- else if (vlan_id) {
- if (!(skb->dev->flags & IFF_PROMISC))
- goto drop;
- skb->pkt_type = PACKET_OTHERHOST;
+ vlan_dev = vlan_find_dev(skb->dev, vlan_id);
+ if (!vlan_dev) {
+ if (vlan_id)
+ skb->pkt_type = PACKET_OTHERHOST;
+ return NET_RX_SUCCESS;
}
- return polling ? netif_receive_skb(skb) : netif_rx(skb);
-
-drop:
- atomic_long_inc(&skb->dev->rx_dropped);
- dev_kfree_skb_any(skb);
- return NET_RX_DROP;
-}
-EXPORT_SYMBOL(__vlan_hwaccel_rx);
-
-void vlan_hwaccel_do_receive(struct sk_buff *skb)
-{
- struct net_device *dev = skb->dev;
- struct vlan_rx_stats *rx_stats;
+ if (netpoll_receive_skb(skb))
+ return NET_RX_DROP;
- skb->dev = vlan_dev_real_dev(dev);
netif_nit_deliver(skb);
- skb->dev = dev;
- skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
+ skb->skb_iif = skb->dev->ifindex;
+ if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
+ skb->deliver_no_wcard = 1;
+
+ skb->dev = vlan_dev;
+ skb->priority = vlan_get_ingress_priority(skb->dev, skb->vlan_tci);
skb->vlan_tci = 0;
- rx_stats = this_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats);
+ rx_stats = this_cpu_ptr(vlan_dev_info(skb->dev)->vlan_rx_stats);
u64_stats_update_begin(&rx_stats->syncp);
rx_stats->rx_packets++;
@@ -68,11 +47,13 @@ void vlan_hwaccel_do_receive(struct sk_buff *skb)
* This allows the VLAN to have a different MAC than the
* underlying device, and still route correctly. */
if (!compare_ether_addr(eth_hdr(skb)->h_dest,
- dev->dev_addr))
+ skb->dev->dev_addr))
skb->pkt_type = PACKET_HOST;
break;
}
u64_stats_update_end(&rx_stats->syncp);
+
+ return NET_RX_SUCCESS;
}
struct net_device *vlan_dev_real_dev(const struct net_device *dev)
@@ -87,75 +68,27 @@ u16 vlan_dev_vlan_id(const struct net_device *dev)
}
EXPORT_SYMBOL(vlan_dev_vlan_id);
-static gro_result_t
-vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,
- unsigned int vlan_tci, struct sk_buff *skb)
+/* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */
+int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
+ u16 vlan_tci, int polling)
{
- struct sk_buff *p;
- struct net_device *vlan_dev;
- u16 vlan_id;
-
- if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
- skb->deliver_no_wcard = 1;
-
- skb->skb_iif = skb->dev->ifindex;
__vlan_hwaccel_put_tag(skb, vlan_tci);
- vlan_id = vlan_tci & VLAN_VID_MASK;
- vlan_dev = vlan_group_get_device(grp, vlan_id);
-
- if (vlan_dev)
- skb->dev = vlan_dev;
- else if (vlan_id) {
- if (!(skb->dev->flags & IFF_PROMISC))
- goto drop;
- skb->pkt_type = PACKET_OTHERHOST;
- }
-
- for (p = napi->gro_list; p; p = p->next) {
- unsigned long diffs;
-
- diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
- diffs |= compare_ether_header(skb_mac_header(p),
- skb_gro_mac_header(skb));
- NAPI_GRO_CB(p)->same_flow = !diffs;
- NAPI_GRO_CB(p)->flush = 0;
- }
-
- return dev_gro_receive(napi, skb);
-
-drop:
- atomic_long_inc(&skb->dev->rx_dropped);
- return GRO_DROP;
+ return polling ? netif_receive_skb(skb) : netif_rx(skb);
}
+EXPORT_SYMBOL(__vlan_hwaccel_rx);
gro_result_t vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
unsigned int vlan_tci, struct sk_buff *skb)
{
- if (netpoll_rx_on(skb))
- return vlan_hwaccel_receive_skb(skb, grp, vlan_tci)
- ? GRO_DROP : GRO_NORMAL;
-
- skb_gro_reset_offset(skb);
-
- return napi_skb_finish(vlan_gro_common(napi, grp, vlan_tci, skb), skb);
+ __vlan_hwaccel_put_tag(skb, vlan_tci);
+ return napi_gro_receive(napi, skb);
}
EXPORT_SYMBOL(vlan_gro_receive);
gro_result_t vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
unsigned int vlan_tci)
{
- struct sk_buff *skb = napi_frags_skb(napi);
-
- if (!skb)
- return GRO_DROP;
-
- if (netpoll_rx_on(skb)) {
- skb->protocol = eth_type_trans(skb, skb->dev);
- return vlan_hwaccel_receive_skb(skb, grp, vlan_tci)
- ? GRO_DROP : GRO_NORMAL;
- }
-
- return napi_frags_finish(napi, skb,
- vlan_gro_common(napi, grp, vlan_tci, skb));
+ __vlan_hwaccel_put_tag(napi->skb, vlan_tci);
+ return napi_gro_frags(napi);
}
EXPORT_SYMBOL(vlan_gro_frags);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index f54251e..14e3d1f 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -158,7 +158,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
vlan_id = vlan_tci & VLAN_VID_MASK;
rcu_read_lock();
- vlan_dev = __find_vlan_dev(dev, vlan_id);
+ vlan_dev = vlan_find_dev(dev, vlan_id);
/* If the VLAN device is defined, we use it.
* If not, and the VID is 0, it is a 802.1p packet (not
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
index a39d92d..e724720 100644
--- a/net/bridge/netfilter/ebt_vlan.c
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -119,10 +119,10 @@ static int ebt_vlan_mt_check(const struct xt_mtchk_param *par)
* 0 - The null VLAN ID.
* 1 - The default Port VID (PVID)
* 0x0FFF - Reserved for implementation use.
- * if_vlan.h: VLAN_GROUP_ARRAY_LEN 4096. */
+ * if_vlan.h: VLAN_N_VID 4096. */
if (GET_BITMASK(EBT_VLAN_ID)) {
if (!!info->id) { /* if id!=0 => check vid range */
- if (info->id > VLAN_GROUP_ARRAY_LEN) {
+ if (info->id > VLAN_N_VID) {
pr_debug("id %d is out of range (1-4096)\n",
info->id);
return -EINVAL;
diff --git a/net/core/dev.c b/net/core/dev.c
index 04972a4..9586aff 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1692,7 +1692,12 @@ static bool can_checksum_protocol(unsigned long features, __be16 protocol)
static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb)
{
- if (can_checksum_protocol(dev->features, skb->protocol))
+ int features = dev->features;
+
+ if (vlan_tx_tag_present(skb))
+ features &= dev->vlan_features;
+
+ if (can_checksum_protocol(features, skb->protocol))
return true;
if (skb->protocol == htons(ETH_P_8021Q)) {
@@ -1791,6 +1796,16 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
__be16 type = skb->protocol;
int err;
+ if (type == htons(ETH_P_8021Q)) {
+ struct vlan_ethhdr *veh;
+
+ if (unlikely(!pskb_may_pull(skb, VLAN_ETH_HLEN)))
+ return ERR_PTR(-EINVAL);
+
+ veh = (struct vlan_ethhdr *)skb->data;
+ type = veh->h_vlan_encapsulated_proto;
+ }
+
skb_reset_mac_header(skb);
skb->mac_len = skb->network_header - skb->mac_header;
__skb_pull(skb, skb->mac_len);
@@ -1962,9 +1977,14 @@ static inline void skb_orphan_try(struct sk_buff *skb)
static inline int skb_needs_linearize(struct sk_buff *skb,
struct net_device *dev)
{
+ int features = dev->features;
+
+ if (skb->protocol == htons(ETH_P_8021Q) || vlan_tx_tag_present(skb))
+ features &= dev->vlan_features;
+
return skb_is_nonlinear(skb) &&
- ((skb_has_frag_list(skb) && !(dev->features & NETIF_F_FRAGLIST)) ||
- (skb_shinfo(skb)->nr_frags && (!(dev->features & NETIF_F_SG) ||
+ ((skb_has_frag_list(skb) && !(features & NETIF_F_FRAGLIST)) ||
+ (skb_shinfo(skb)->nr_frags && (!(features & NETIF_F_SG) ||
illegal_highdma(dev, skb))));
}
@@ -1987,6 +2007,15 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
skb_orphan_try(skb);
+ if (vlan_tx_tag_present(skb) &&
+ !(dev->features & NETIF_F_HW_VLAN_TX)) {
+ skb = __vlan_put_tag(skb, vlan_tx_tag_get(skb));
+ if (unlikely(!skb))
+ goto out;
+
+ skb->vlan_tci = 0;
+ }
+
if (netif_needs_gso(dev, skb)) {
if (unlikely(dev_gso_segment(skb)))
goto out_kfree_skb;
@@ -2048,6 +2077,7 @@ out_kfree_gso_skb:
skb->destructor = DEV_GSO_CB(skb)->destructor;
out_kfree_skb:
kfree_skb(skb);
+out:
return rc;
}
@@ -2893,8 +2923,8 @@ static int __netif_receive_skb(struct sk_buff *skb)
if (!netdev_tstamp_prequeue)
net_timestamp_check(skb);
- if (vlan_tx_tag_present(skb))
- vlan_hwaccel_do_receive(skb);
+ if (vlan_tx_tag_present(skb) && vlan_hwaccel_do_receive(skb))
+ return NET_RX_DROP;
/* if we've gotten here through NAPI, check netpoll */
if (netpoll_receive_skb(skb))
@@ -3232,6 +3262,7 @@ __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
unsigned long diffs;
diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
+ diffs |= p->vlan_tci ^ skb->vlan_tci;
diffs |= compare_ether_header(skb_mac_header(p),
skb_gro_mac_header(skb));
NAPI_GRO_CB(p)->same_flow = !diffs;
@@ -3291,6 +3322,7 @@ void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb)
{
__skb_pull(skb, skb_headlen(skb));
skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb));
+ skb->vlan_tci = 0;
napi->skb = skb;
}
--
1.7.0.4
^ permalink raw reply related
* [RFC PATCH 3/7] bnx2: Update bnx2 to use new vlan accleration.
From: Jesse Gross @ 2010-10-13 20:02 UTC (permalink / raw)
To: davem; +Cc: netdev, Michael Chan
In-Reply-To: <1287000177-7126-1-git-send-email-jesse@nicira.com>
Make the bnx2 driver use the new vlan accleration model.
Signed-off-by: Jesse Gross <jesse@nicira.com>
CC: Michael Chan <mchan@broadcom.com>
---
drivers/net/bnx2.c | 75 +++------------------------------------------------
drivers/net/bnx2.h | 4 ---
2 files changed, 5 insertions(+), 74 deletions(-)
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index ae894bc..2d306f4 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -37,9 +37,6 @@
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/if_vlan.h>
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define BCM_VLAN 1
-#endif
#include <net/ip.h>
#include <net/tcp.h>
#include <net/checksum.h>
@@ -3087,8 +3084,6 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
struct sw_bd *rx_buf, *next_rx_buf;
struct sk_buff *skb;
dma_addr_t dma_addr;
- u16 vtag = 0;
- int hw_vlan __maybe_unused = 0;
sw_ring_cons = RX_RING_IDX(sw_cons);
sw_ring_prod = RX_RING_IDX(sw_prod);
@@ -3168,23 +3163,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
goto next_rx;
if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) &&
- !(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) {
- vtag = rx_hdr->l2_fhdr_vlan_tag;
-#ifdef BCM_VLAN
- if (bp->vlgrp)
- hw_vlan = 1;
- else
-#endif
- {
- struct vlan_ethhdr *ve = (struct vlan_ethhdr *)
- __skb_push(skb, 4);
-
- memmove(ve, skb->data + 4, ETH_ALEN * 2);
- ve->h_vlan_proto = htons(ETH_P_8021Q);
- ve->h_vlan_TCI = htons(vtag);
- len += 4;
- }
- }
+ !(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG))
+ __vlan_hwaccel_put_tag(skb, rx_hdr->l2_fhdr_vlan_tag);
skb->protocol = eth_type_trans(skb, bp->dev);
@@ -3211,14 +3191,7 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
skb->rxhash = rx_hdr->l2_fhdr_hash;
skb_record_rx_queue(skb, bnapi - &bp->bnx2_napi[0]);
-
-#ifdef BCM_VLAN
- if (hw_vlan)
- vlan_gro_receive(&bnapi->napi, bp->vlgrp, vtag, skb);
- else
-#endif
- napi_gro_receive(&bnapi->napi, skb);
-
+ napi_gro_receive(&bnapi->napi, skb);
rx_pkt++;
next_rx:
@@ -3533,13 +3506,6 @@ bnx2_set_rx_mode(struct net_device *dev)
rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN;
-#ifdef BCM_VLAN
- if (!bp->vlgrp && (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
- rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
-#else
- if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)
- rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
-#endif
if (dev->flags & IFF_PROMISC) {
/* Promiscuous mode. */
rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS;
@@ -6365,29 +6331,6 @@ bnx2_tx_timeout(struct net_device *dev)
schedule_work(&bp->reset_task);
}
-#ifdef BCM_VLAN
-/* Called with rtnl_lock */
-static void
-bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
-{
- struct bnx2 *bp = netdev_priv(dev);
-
- if (netif_running(dev))
- bnx2_netif_stop(bp, false);
-
- bp->vlgrp = vlgrp;
-
- if (!netif_running(dev))
- return;
-
- bnx2_set_rx_mode(dev);
- if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)
- bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1);
-
- bnx2_netif_start(bp, false);
-}
-#endif
-
/* Called with netif_tx_lock.
* bnx2_tx_int() runs without netif_tx_lock unless it needs to call
* netif_wake_queue().
@@ -6428,12 +6371,11 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
}
-#ifdef BCM_VLAN
- if (bp->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
vlan_tag_flags |=
(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
}
-#endif
+
if ((mss = skb_shinfo(skb)->gso_size)) {
u32 tcp_opt_len;
struct iphdr *iph;
@@ -8318,9 +8260,6 @@ static const struct net_device_ops bnx2_netdev_ops = {
.ndo_set_mac_address = bnx2_change_mac_addr,
.ndo_change_mtu = bnx2_change_mtu,
.ndo_tx_timeout = bnx2_tx_timeout,
-#ifdef BCM_VLAN
- .ndo_vlan_rx_register = bnx2_vlan_rx_register,
-#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = poll_bnx2,
#endif
@@ -8328,9 +8267,7 @@ static const struct net_device_ops bnx2_netdev_ops = {
static void inline vlan_features_add(struct net_device *dev, unsigned long flags)
{
-#ifdef BCM_VLAN
dev->vlan_features |= flags;
-#endif
}
static int __devinit
@@ -8379,9 +8316,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->features |= NETIF_F_IPV6_CSUM;
vlan_features_add(dev, NETIF_F_IPV6_CSUM);
}
-#ifdef BCM_VLAN
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
vlan_features_add(dev, NETIF_F_TSO | NETIF_F_TSO_ECN);
if (CHIP_NUM(bp) == CHIP_NUM_5709) {
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index efdfbc2..4f44db6 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6742,10 +6742,6 @@ struct bnx2 {
struct bnx2_napi bnx2_napi[BNX2_MAX_MSIX_VEC];
-#ifdef BCM_VLAN
- struct vlan_group *vlgrp;
-#endif
-
u32 rx_buf_use_size; /* useable size */
u32 rx_buf_size; /* with alignment */
u32 rx_copy_thresh;
--
1.7.0.4
^ permalink raw reply related
* [RFC PATCH 0/7] Move vlan acceleration into networking core.
From: Jesse Gross @ 2010-10-13 20:02 UTC (permalink / raw)
To: davem; +Cc: netdev
Hardware vlan acceleration behaves fairly differently from other types of
offloading, which limits its usefulness. This patch series aims to bring
it more in line with other common forms of acceleration, such as checksum
offloading and TSO. In doing this it eliminates common driver bugs, increases
flexibility, and improves performance, while reducing the number of lines of
code.
The first four patches can be applied immediately, while the last three need
to wait until all drivers that support vlan acceleration are updated. If
people agree that this patch set makes sense I will go ahead and switch over
the dozen or so drivers that would need to change.
Jesse Gross (7):
ebtables: Allow filtering of hardware accelerated vlan frames.
vlan: Centralize handling of hardware acceleration.
bnx2: Update bnx2 to use new vlan accleration.
ixgbe: Update ixgbe to use new vlan accleration.
lro: Remove explicit vlan support.
bonding: Update bonding for new vlan model.
vlan: Remove accleration legacy functions.
drivers/net/bnx2.c | 75 ++--------------------
drivers/net/bnx2.h | 4 -
drivers/net/bonding/bond_alb.c | 8 +--
drivers/net/bonding/bond_ipv6.c | 5 +-
drivers/net/bonding/bond_main.c | 134 ++++++++-------------------------------
drivers/net/bonding/bonding.h | 1 -
drivers/net/ixgbe/ixgbe.h | 4 +-
drivers/net/ixgbe/ixgbe_main.c | 60 +++++-------------
include/linux/if_vlan.h | 87 ++++++++------------------
include/linux/inet_lro.h | 20 ------
include/linux/netdevice.h | 20 +++---
net/8021q/vlan.c | 100 +++++++-----------------------
net/8021q/vlan.h | 17 -----
net/8021q/vlan_core.c | 132 ++++++--------------------------------
net/8021q/vlan_dev.c | 2 +-
net/bridge/br_netfilter.c | 16 +++--
net/bridge/netfilter/ebt_vlan.c | 42 +++++++-----
net/bridge/netfilter/ebtables.c | 15 +++-
net/core/dev.c | 42 +++++++++++--
net/ipv4/inet_lro.c | 74 +++------------------
20 files changed, 225 insertions(+), 633 deletions(-)
^ permalink raw reply
* [RFC PATCH 1/7] ebtables: Allow filtering of hardware accelerated vlan frames.
From: Jesse Gross @ 2010-10-13 20:02 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1287000177-7126-1-git-send-email-jesse@nicira.com>
An upcoming commit will allow packets with hardware vlan acceleration
information to be passed though more parts of the network stack, including
packets trunked through the bridge. This adds support for matching and
filtering those packets through ebtables.
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
net/bridge/br_netfilter.c | 16 +++++++++-------
net/bridge/netfilter/ebt_vlan.c | 38 +++++++++++++++++++++++---------------
net/bridge/netfilter/ebtables.c | 15 +++++++++++----
3 files changed, 43 insertions(+), 26 deletions(-)
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 7f9ce96..d6a4fec 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -64,22 +64,24 @@ static int brnf_filter_pppoe_tagged __read_mostly = 0;
static inline __be16 vlan_proto(const struct sk_buff *skb)
{
- return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
+ if (skb->protocol == htons(ETH_P_8021Q))
+ return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
+ else if (vlan_tx_tag_present(skb))
+ return skb->protocol;
+ else
+ return 0;
}
#define IS_VLAN_IP(skb) \
- (skb->protocol == htons(ETH_P_8021Q) && \
- vlan_proto(skb) == htons(ETH_P_IP) && \
+ (vlan_proto(skb) == htons(ETH_P_IP) && \
brnf_filter_vlan_tagged)
#define IS_VLAN_IPV6(skb) \
- (skb->protocol == htons(ETH_P_8021Q) && \
- vlan_proto(skb) == htons(ETH_P_IPV6) &&\
+ (vlan_proto(skb) == htons(ETH_P_IPV6) &&\
brnf_filter_vlan_tagged)
#define IS_VLAN_ARP(skb) \
- (skb->protocol == htons(ETH_P_8021Q) && \
- vlan_proto(skb) == htons(ETH_P_ARP) && \
+ (vlan_proto(skb) == htons(ETH_P_ARP) && \
brnf_filter_vlan_tagged)
static inline __be16 pppoe_proto(const struct sk_buff *skb)
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
index 87b53b3..a39d92d 100644
--- a/net/bridge/netfilter/ebt_vlan.c
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -39,8 +39,6 @@ static bool
ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct ebt_vlan_info *info = par->matchinfo;
- const struct vlan_hdr *fp;
- struct vlan_hdr _frame;
unsigned short TCI; /* Whole TCI, given from parsed frame */
unsigned short id; /* VLAN ID, given from frame TCI */
@@ -48,21 +46,31 @@ ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par)
/* VLAN encapsulated Type/Length field, given from orig frame */
__be16 encap;
- fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
- if (fp == NULL)
- return false;
-
- /* Tag Control Information (TCI) consists of the following elements:
- * - User_priority. The user_priority field is three bits in length,
- * interpreted as a binary number.
- * - Canonical Format Indicator (CFI). The Canonical Format Indicator
- * (CFI) is a single bit flag value. Currently ignored.
- * - VLAN Identifier (VID). The VID is encoded as
- * an unsigned binary number. */
- TCI = ntohs(fp->h_vlan_TCI);
+ if (skb->protocol == htons(ETH_P_8021Q)) {
+ const struct vlan_hdr *fp;
+ struct vlan_hdr _frame;
+
+ fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
+ if (fp == NULL)
+ return false;
+
+ /* Tag Control Information (TCI) consists of the following elements:
+ * - User_priority. The user_priority field is three bits in length,
+ * interpreted as a binary number.
+ * - Canonical Format Indicator (CFI). The Canonical Format Indicator
+ * (CFI) is a single bit flag value. Currently ignored.
+ * - VLAN Identifier (VID). The VID is encoded as
+ * an unsigned binary number. */
+ TCI = ntohs(fp->h_vlan_TCI);
+
+ encap = fp->h_vlan_encapsulated_proto;
+ } else {
+ TCI = vlan_tx_tag_get(skb);
+ encap = skb->protocol;
+ }
+
id = TCI & VLAN_VID_MASK;
prio = (TCI >> 13) & 0x7;
- encap = fp->h_vlan_encapsulated_proto;
/* Checking VLAN Identifier (VID) */
if (GET_BITMASK(EBT_VLAN_ID))
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index bcc102e..a1dcf83 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -124,16 +124,23 @@ ebt_dev_check(const char *entry, const struct net_device *device)
#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
/* process standard matches */
static inline int
-ebt_basic_match(const struct ebt_entry *e, const struct ethhdr *h,
+ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *out)
{
+ const struct ethhdr *h = eth_hdr(skb);
+ __be16 ethproto;
int verdict, i;
+ if (vlan_tx_tag_present(skb))
+ ethproto = htons(ETH_P_8021Q);
+ else
+ ethproto = h->h_proto;
+
if (e->bitmask & EBT_802_3) {
- if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
+ if (FWINV2(ntohs(ethproto) >= 1536, EBT_IPROTO))
return 1;
} else if (!(e->bitmask & EBT_NOPROTO) &&
- FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
+ FWINV2(e->ethproto != ethproto, EBT_IPROTO))
return 1;
if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
@@ -213,7 +220,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
base = private->entries;
i = 0;
while (i < nentries) {
- if (ebt_basic_match(point, eth_hdr(skb), in, out))
+ if (ebt_basic_match(point, skb, in, out))
goto letscontinue;
if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &acpar) != 0)
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH -next] sundance: Add initial ethtool stats support
From: Eric Dumazet @ 2010-10-13 19:44 UTC (permalink / raw)
To: Denis Kirjanov; +Cc: netdev, David Miller, Ben Hutchings, Jeff Garzik
In-Reply-To: <4CB59049.6060405@kernel.org>
Le mercredi 13 octobre 2010 à 14:56 +0400, Denis Kirjanov a écrit :
> On 10/13/2010 02:36 PM, Eric Dumazet wrote:
> > Le mercredi 13 octobre 2010 à 14:28 +0400, Denis Kirjanov a écrit :
> >
> >> + u64 tx_defered;
> >> + u64 tx_defered_excessive;
> >
> PATCH -next v5] sundance: Add ethtool stats support
>
> Add ethtool stats support.
>
> Signed-off-by: Denis Kirjanov <dkirjanov@kernel.org>
> ---
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
^ permalink raw reply
* Re: [Bugme-new] [Bug 20292] New: unable to handle kernel NULL pointer dereference in skb_dequeue
From: Andrew Morton @ 2010-10-13 19:33 UTC (permalink / raw)
To: netdev; +Cc: bugzilla-daemon, bugme-daemon, Michal Ostrowski, gvs
In-Reply-To: <bug-20292-10286@https.bugzilla.kernel.org/>
(switched to email. Please respond via emailed reply-to-all, not via the
bugzilla web interface).
On Wed, 13 Oct 2010 19:24:53 GMT
bugzilla-daemon@bugzilla.kernel.org wrote:
> https://bugzilla.kernel.org/show_bug.cgi?id=20292
>
> Summary: unable to handle kernel NULL pointer dereference in
> skb_dequeue
> Product: Networking
> Version: 2.5
> Kernel Version: 2.6.36-rc7
Thanks. Do you know if this is a regression? Did it work OK on 2.6.35?
> Platform: All
> OS/Version: Linux
> Tree: Mainline
> Status: NEW
> Severity: blocking
> Priority: P1
> Component: Other
> AssignedTo: acme@ghostprotocols.net
> ReportedBy: gvs@zemos.net
> Regression: No
>
>
> Created an attachment (id=33512)
> --> (https://bugzilla.kernel.org/attachment.cgi?id=33512)
> Kernel config (gzipped)
>
> I was trying to get pppoe working (the 'pon' command seemed to hang) and then
> this happened:
>
> Oct 13 20:57:07 bes kernel: BUG: unable to handle kernel NULL pointer
> dereference at (null)
> Oct 13 20:57:07 bes kernel: IP: [<c1241674>] skb_dequeue+0x24/0x40
> Oct 13 20:57:07 bes kernel: *pde = 00000000
> Oct 13 20:57:07 bes kernel: Oops: 0002 [#1]
> Oct 13 20:57:07 bes kernel: last sysfs file:
> /sys/devices/virtual/net/ppp0/uevent
> Oct 13 20:57:07 bes kernel: Modules linked in: xt_TCPMSS xt_tcpmss xt_tcpudp
> iptable_mangle pppoe pppox ppp_generic slhc cpufreq_conservative
> cpufreq_userspace cpufreq_powersave fuse ipt_MASQUERADE iptable_nat nf_nat
> nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack iptable_filter ip_tables
> x_tables loop sd_mod usb_storage usblp i2c_viapro uhci_hcd fan ehci_hcd button
> i2c_core
> Oct 13 20:57:07 bes kernel:
> Oct 13 20:57:07 bes kernel: Pid: 5495, comm: pppd Not tainted 2.6.36-rc7 #12
> VX800 /VX800
> Oct 13 20:57:07 bes kernel: EIP: 0060:[<c1241674>] EFLAGS: 00010046 CPU: 0
> Oct 13 20:57:07 bes kernel: EIP is at skb_dequeue+0x24/0x40
> Oct 13 20:57:07 bes kernel: EAX: 00000000 EBX: 00000202 ECX: f6ba4cc0 EDX:
> 00000000
> Oct 13 20:57:07 bes kernel: ESI: f6c93bc0 EDI: f6adfee4 EBP: f6ade000 ESP:
> f6adfe68
> Oct 13 20:57:07 bes kernel: DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
> Oct 13 20:57:07 bes kernel: Process pppd (pid: 5495, ti=f6ade000 task=f70f2200
> task.ti=f6ade000)
> Oct 13 20:57:07 bes kernel: Stack:
> Oct 13 20:57:07 bes kernel: f68836c4 c1243a94 f68836c0 f866825b 00000000
> f72e4a00 f72e4a00 f86761cb
> Oct 13 20:57:07 bes kernel: <0> f72e4a00 f8683c97 c143ea14 ffffffea c12ba92d
> 00000286 f68f7d7c f6adfee4
> Oct 13 20:57:07 bes kernel: <0> f68f7bfc 00000286 00000000 00000000 00000000
> f68f7b9c f6adff68 f6adff64
> Oct 13 20:57:07 bes kernel: Call Trace:
> Oct 13 20:57:07 bes kernel: [<c1243a94>] ? skb_queue_purge+0x14/0x30
> Oct 13 20:57:07 bes kernel: [<f866825b>] ? ppp_destroy_channel+0x1b/0x50
> [ppp_generic]
> Oct 13 20:57:07 bes kernel: [<f86761cb>] ? pppox_unbind_sock+0x1b/0x24 [pppox]
> Oct 13 20:57:07 bes kernel: [<f8683c97>] ? pppoe_connect+0x87/0x4b0 [pppoe]
> Oct 13 20:57:07 bes kernel: [<c12ba92d>] ? schedule_timeout+0xfd/0x150
> Oct 13 20:57:07 bes kernel: [<c123d4d4>] ? sys_connect+0x84/0xd0
> Oct 13 20:57:07 bes kernel: [<c10ba730>] ? do_lock_file_wait+0x30/0xf0
> Oct 13 20:57:07 bes kernel: [<c10ba9f9>] ? fcntl_setlk+0x59/0x1b0
> Oct 13 20:57:07 bes kernel: [<c123e5a4>] ? sys_socketcall+0x294/0x2c0
> Oct 13 20:57:07 bes kernel: [<c1002a10>] ? sysenter_do_call+0x12/0x26
> Oct 13 20:57:07 bes kernel: Code: 81 a8 00 00 00 5b c3 53 9c 5b fa 8b 08 39 c8
> 74 25 85 c9 74 1b 83 68 08 01 8b 11 8b 41 04 c7 01 00 00 00 00 c7 41 04 00 00
> 00 00 <89> 10 89 42 04 53 9d 89 c8 5b c3 31 c9 eb f6 8d b6 00 00 00 00
> Oct 13 20:57:07 bes kernel: EIP: [<c1241674>] skb_dequeue+0x24/0x40 SS:ESP
> 0068:f6adfe68
> Oct 13 20:57:07 bes kernel: CR2: 0000000000000000
> Oct 13 20:57:07 bes kernel: ---[ end trace 4914adf67d1ace25 ]---
>
> Oct 13 20:57:30 bes kernel: BUG: unable to handle kernel NULL pointer
> dereference at (null)
> Oct 13 20:57:30 bes kernel: IP: [<c1241674>] skb_dequeue+0x24/0x40
> Oct 13 20:57:30 bes kernel: *pde = 00000000
> Oct 13 20:57:30 bes kernel: Oops: 0002 [#2]
> Oct 13 20:57:30 bes kernel: last sysfs file:
> /sys/devices/virtual/net/ppp0/uevent
> Oct 13 20:57:30 bes kernel: Modules linked in: xt_TCPMSS xt_tcpmss xt_tcpudp
> iptable_mangle pppoe pppox ppp_generic slhc cpufreq_conservative
> cpufreq_userspace cpufreq_powersave fuse ipt_MASQUERADE iptable_nat nf_nat
> nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack iptable_filter ip_tables
> x_tables loop sd_mod usb_storage usblp i2c_viapro uhci_hcd fan ehci_hcd button
> i2c_core
> Oct 13 20:57:30 bes kernel:
> Oct 13 20:57:30 bes kernel: Pid: 5445, comm: pppd Tainted: G D
> 2.6.36-rc7 #12 VX800 /VX800
> Oct 13 20:57:30 bes kernel: EIP: 0060:[<c1241674>] EFLAGS: 00010046 CPU: 0
> Oct 13 20:57:30 bes kernel: EIP is at skb_dequeue+0x24/0x40
> Oct 13 20:57:30 bes kernel: EAX: 00000000 EBX: 00000202 ECX: f6ae7200 EDX:
> 00000000
> Oct 13 20:57:30 bes kernel: ESI: f6c99080 EDI: f7161ee4 EBP: f7160000 ESP:
> f7161e68
> Oct 13 20:57:30 bes kernel: DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
> Oct 13 20:57:30 bes kernel: Process pppd (pid: 5445, ti=f7160000 task=f7107280
> task.ti=f7160000)
> Oct 13 20:57:30 bes kernel: Stack:
> Oct 13 20:57:30 bes kernel: f6883344 c1243a94 f6883340 f866825b 00000000
> f72e4c00 f72e4c00 f86761cb
> Oct 13 20:57:30 bes kernel: <0> f72e4c00 f8683c97 c143ea14 ffffffea c12ba92d
> 00000286 f68f73bc f7161ee4
> Oct 13 20:57:30 bes kernel: <0> f68f753c 00000286 00000000 00000000 00000000
> f68f759c f7161f68 f7161f64
> Oct 13 20:57:30 bes kernel: [<c1243a94>] ? skb_queue_purge+0x14/0x30
> Oct 13 20:57:30 bes kernel: [<f866825b>] ? ppp_destroy_channel+0x1b/0x50
> [ppp_generic]
> Oct 13 20:57:30 bes kernel: [<f86761cb>] ? pppox_unbind_sock+0x1b/0x24 [pppox]
> Oct 13 20:57:30 bes kernel: [<f8683c97>] ? pppoe_connect+0x87/0x4b0 [pppoe]
> Oct 13 20:57:30 bes kernel: [<c12ba92d>] ? schedule_timeout+0xfd/0x150
> Oct 13 20:57:30 bes kernel: [<c123d4d4>] ? sys_connect+0x84/0xd0
> Oct 13 20:57:30 bes kernel: [<c10ba730>] ? do_lock_file_wait+0x30/0xf0
> Oct 13 20:57:30 bes kernel: [<c10ba9f9>] ? fcntl_setlk+0x59/0x1b0
> Oct 13 20:57:30 bes kernel: [<c123e5a4>] ? sys_socketcall+0x294/0x2c0
> Oct 13 20:57:30 bes kernel: [<c1002a10>] ? sysenter_do_call+0x12/0x26
> Oct 13 20:57:30 bes kernel: Code: 81 a8 00 00 00 5b c3 53 9c 5b fa 8b 08 39 c8
> 74 25 85 c9 74 1b 83 68 08 01 8b 11 8b 41 04 c7 01 00 00 00 00 c7 41 04 00 00
> 00 00 <89> 10 89 42 04 53 9d 89 c8 5b c3 31 c9 eb f6 8d b6 00 00 00 00
> Oct 13 20:57:30 bes kernel: EIP: [<c1241674>] skb_dequeue+0x24/0x40 SS:ESP
> 0068:f7161e68
> Oct 13 20:57:30 bes kernel: CR2: 0000000000000000
> Oct 13 20:57:30 bes kernel: ---[ end trace 4914adf67d1ace26 ]---
> Oct 13 20:57:30 bes kernel: ------------[ cut here ]------------
> Oct 13 20:57:30 bes kernel: WARNING: at kernel/softirq.c:143
> local_bh_enable+0x60/0x90()
> Oct 13 20:57:30 bes kernel: Hardware name: VX800
> Oct 13 20:57:30 bes kernel: Modules linked in: xt_TCPMSS xt_tcpmss xt_tcpudp
> iptable_mangle pppoe pppox ppp_generic slhc cpufreq_conservative
> cpufreq_userspace cpufreq_powersave fuse ipt_MASQUERADE iptable_nat nf_nat
> nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack iptable_filter ip_tables
> x_tables loop sd_mod usb_storage usblp i2c_viapro uhci_hcd fan ehci_hcd button
> i2c_core
> Oct 13 20:57:30 bes kernel: Pid: 5445, comm: pppd Tainted: G D
> 2.6.36-rc7 #12
> Oct 13 20:57:30 bes kernel: Call Trace:
> Oct 13 20:57:30 bes kernel: [<c1028640>] ? local_bh_enable+0x60/0x90
> Oct 13 20:57:30 bes kernel: [<c1028640>] ? local_bh_enable+0x60/0x90
> Oct 13 20:57:30 bes kernel: [<c1023a1e>] ? warn_slowpath_common+0x7e/0xc0
> Oct 13 20:57:30 bes kernel: [<c1028640>] ? local_bh_enable+0x60/0x90
> Oct 13 20:57:30 bes kernel: [<c1023a7b>] ? warn_slowpath_null+0x1b/0x20
> Oct 13 20:57:30 bes kernel: [<c1028640>] ? local_bh_enable+0x60/0x90
> Oct 13 20:57:30 bes kernel: [<c12a5bb5>] ? unix_release_sock+0x45/0x1f0
> Oct 13 20:57:30 bes kernel: [<c123dc4a>] ? sock_release+0x1a/0x80
> Oct 13 20:57:30 bes kernel: [<c123dcbf>] ? sock_close+0xf/0x30
> Oct 13 20:57:30 bes kernel: [<c1089cd9>] ? fput+0xb9/0x200
> Oct 13 20:57:30 bes kernel: [<c1086f7e>] ? filp_close+0x3e/0x70
> Oct 13 20:57:30 bes kernel: [<c10254b2>] ? put_files_struct+0x62/0xb0
> Oct 13 20:57:30 bes kernel: [<c1026c47>] ? do_exit+0x567/0x630
> Oct 13 20:57:30 bes kernel: [<c12ba037>] ? printk+0x17/0x20
> Oct 13 20:57:30 bes kernel: [<c1005477>] ? oops_end+0x87/0x90
> Oct 13 20:57:30 bes kernel: [<c12ba037>] ? printk+0x17/0x20
> Oct 13 20:57:30 bes kernel: [<c10194a2>] ? no_context+0xc2/0x160
> Oct 13 20:57:30 bes kernel: [<c10195a5>] ? __bad_area_nosemaphore+0x65/0x180
> Oct 13 20:57:30 bes kernel: [<c1249a3b>] ? dev_txq_stats_fold+0x8b/0xf0
> Oct 13 20:57:30 bes kernel: [<c117dc80>] ? __nla_reserve+0x40/0x60
> Oct 13 20:57:30 bes kernel: [<c1255c33>] ? rtnl_fill_ifinfo+0x413/0x8d0
> Oct 13 20:57:30 bes kernel: [<c101971a>] ? bad_area+0x3a/0x50
> Oct 13 20:57:30 bes kernel: [<c1019b8e>] ? do_page_fault+0x33e/0x390
> Oct 13 20:57:30 bes kernel: [<c101e6ab>] ? wakeup_preempt_entity+0x3b/0xa0
> Oct 13 20:57:30 bes kernel: [<c101e79a>] ? check_preempt_wakeup+0x8a/0xe0
> Oct 13 20:57:30 bes kernel: [<c1097675>] ? pollwake+0x65/0x80
> Oct 13 20:57:30 bes kernel: [<c1021170>] ? default_wake_function+0x0/0x10
> Oct 13 20:57:30 bes kernel: [<c1019850>] ? do_page_fault+0x0/0x390
> Oct 13 20:57:30 bes kernel: [<c12bbcf0>] ? error_code+0x58/0x60
> Oct 13 20:57:30 bes kernel: [<c1019850>] ? do_page_fault+0x0/0x390
> Oct 13 20:57:30 bes kernel: [<c1241674>] ? skb_dequeue+0x24/0x40
> Oct 13 20:57:30 bes kernel: [<c1243a94>] ? skb_queue_purge+0x14/0x30
> Oct 13 20:57:30 bes kernel: [<f866825b>] ? ppp_destroy_channel+0x1b/0x50
> [ppp_generic]
> Oct 13 20:57:30 bes kernel: [<f86761cb>] ? pppox_unbind_sock+0x1b/0x24 [pppox]
> Oct 13 20:57:30 bes kernel: [<f8683c97>] ? pppoe_connect+0x87/0x4b0 [pppoe]
> Oct 13 20:57:30 bes kernel: [<c12ba92d>] ? schedule_timeout+0xfd/0x150
> Oct 13 20:57:30 bes kernel: [<c123d4d4>] ? sys_connect+0x84/0xd0
> Oct 13 20:57:30 bes kernel: [<c10ba730>] ? do_lock_file_wait+0x30/0xf0
> Oct 13 20:57:30 bes kernel: [<c10ba9f9>] ? fcntl_setlk+0x59/0x1b0
> Oct 13 20:57:30 bes kernel: [<c123e5a4>] ? sys_socketcall+0x294/0x2c0
> Oct 13 20:57:30 bes kernel: [<c1002a10>] ? sysenter_do_call+0x12/0x26
> Oct 13 20:57:30 bes kernel: ---[ end trace 4914adf67d1ace27 ]---
>
> Some other information:
> /proc/version:
> Linux version 2.6.36-rc7 (root@bes) (gcc version 4.3.2 (Debian 4.3.2-1.1) ) #12
> Sun Oct 10 21:12:58 CEST 2010
>
> ver_linux:
> Linux bes 2.6.36-rc7 #12 Sun Oct 10 21:12:58 CEST 2010 i686 GNU/Linux
>
> Gnu C 4.4.5
> Gnu make 3.81
> binutils 2.20.1
> util-linux 2.17.2
> mount support
> module-init-tools 3.12
> e2fsprogs 1.41.12
> PPP 2.4.5
> Linux C Library 2.11.2
> Dynamic linker (ldd) 2.11.2
> Procps 3.2.8
> Net-tools 1.60
> Console-tools 0.2.3
> Sh-utils 8.5
> Modules Loaded cpufreq_conservative cpufreq_userspace cpufreq_powersave
> fuse ppp_generic slhc ipt_MASQUERADE iptable_nat nf_nat nf_conntrack_ipv4
> nf_defrag_ipv4 xt_state nf_conntrack iptable_filter ip_tables x_tables loop
> sd_mod usb_storage usblp i2c_viapro uhci_hcd fan i2c_core ehci_hcd button
>
> cpuinfo:
> processor : 0
> vendor_id : CentaurHauls
> cpu family : 6
> model : 13
> model name : VIA Eden Processor 1600MHz
> stepping : 0
> cpu MHz : 800.000
> cache size : 128 KB
> fdiv_bug : no
> hlt_bug : no
> f00f_bug : no
> coma_bug : no
> fpu : yes
> fpu_exception : yes
> cpuid level : 1
> wp : yes
> flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge cmov pat
> clflush acpi mmx fxsr sse sse2 tm nx pni est tm2 xtpr rng rng_en ace ace_en
> ace2 ace2_en phe phe_en pmm pmm_en
> bogomips : 1599.76
> clflush size : 64
> cache_alignment : 64
> address sizes : 36 bits physical, 32 bits virtual
> power management:
>
> If anything else is needed I'd be happy to assist.
>
^ permalink raw reply
* [PATCH] via-velocity: forced 1000 Mbps mode support.
From: Francois Romieu @ 2010-10-13 19:26 UTC (permalink / raw)
To: David Lv
Cc: netdev, DavidLv, ShirleyHu, AndersMa, David S. Miller,
Seguier Regis
In-Reply-To: <AANLkTinn8UQfOoPgf=13jfvD5Ld6p4GhT7jpyYmXKT9X@mail.gmail.com>
Full duplex only. Half duplex 1000 Mbps is not supported.
Signed-off-by: David Lv <DavidLv@viatech.com.cn>
Acked-by: Francois Romieu <romieu@fr.zoreil.com>
Tested-by: Seguier Regis <rseguier@e-teleport.net>
---
David (Lv), your mail agent apparently wrapped some more-than-80-columns lines
in the patch, thus making it unusable. I fixed it.
drivers/net/via-velocity.c | 82 ++++++++++++++++++++++++++++++++++++++++---
drivers/net/via-velocity.h | 5 ++-
2 files changed, 79 insertions(+), 8 deletions(-)
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index f534123..b21a3d9 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -312,13 +312,14 @@ VELOCITY_PARAM(flow_control, "Enable flow control ability");
#define MED_LNK_DEF 0
#define MED_LNK_MIN 0
-#define MED_LNK_MAX 4
+#define MED_LNK_MAX 5
/* speed_duplex[] is used for setting the speed and duplex mode of NIC.
0: indicate autonegotiation for both speed and duplex mode
1: indicate 100Mbps half duplex mode
2: indicate 100Mbps full duplex mode
3: indicate 10Mbps half duplex mode
4: indicate 10Mbps full duplex mode
+ 5: indicate 1000Mbps full duplex mode
Note:
if EEPROM have been set to the force mode, this option is ignored
@@ -617,6 +618,9 @@ static u32 velocity_get_opt_media_mode(struct velocity_info *vptr)
case SPD_DPX_10_HALF:
status = VELOCITY_SPEED_10;
break;
+ case SPD_DPX_1000_FULL:
+ status = VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL;
+ break;
}
vptr->mii_status = status;
return status;
@@ -922,6 +926,7 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status)
/* enable AUTO-NEGO mode */
mii_set_auto_on(vptr);
} else {
+ u16 CTRL1000;
u16 ANAR;
u8 CHIPGCR;
@@ -936,7 +941,11 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status)
BYTE_REG_BITS_ON(CHIPGCR_FCMODE, ®s->CHIPGCR);
CHIPGCR = readb(®s->CHIPGCR);
- CHIPGCR &= ~CHIPGCR_FCGMII;
+
+ if (mii_status & VELOCITY_SPEED_1000)
+ CHIPGCR |= CHIPGCR_FCGMII;
+ else
+ CHIPGCR &= ~CHIPGCR_FCGMII;
if (mii_status & VELOCITY_DUPLEX_FULL) {
CHIPGCR |= CHIPGCR_FCFDX;
@@ -952,7 +961,13 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status)
BYTE_REG_BITS_ON(TCR_TB2BDIS, ®s->TCR);
}
- MII_REG_BITS_OFF(ADVERTISE_1000FULL | ADVERTISE_1000HALF, MII_CTRL1000, vptr->mac_regs);
+ velocity_mii_read(vptr->mac_regs, MII_CTRL1000, &CTRL1000);
+ CTRL1000 &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+ if ((mii_status & VELOCITY_SPEED_1000) &&
+ (mii_status & VELOCITY_DUPLEX_FULL)) {
+ CTRL1000 |= ADVERTISE_1000FULL;
+ }
+ velocity_mii_write(vptr->mac_regs, MII_CTRL1000, CTRL1000);
if (!(mii_status & VELOCITY_DUPLEX_FULL) && (mii_status & VELOCITY_SPEED_10))
BYTE_REG_BITS_OFF(TESTCFG_HBDIS, ®s->TESTCFG);
@@ -967,7 +982,7 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status)
ANAR |= ADVERTISE_100FULL;
else
ANAR |= ADVERTISE_100HALF;
- } else {
+ } else if (mii_status & VELOCITY_SPEED_10) {
if (mii_status & VELOCITY_DUPLEX_FULL)
ANAR |= ADVERTISE_10FULL;
else
@@ -1013,6 +1028,9 @@ static void velocity_print_link_status(struct velocity_info *vptr)
} else {
VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name);
switch (vptr->options.spd_dpx) {
+ case SPD_DPX_1000_FULL:
+ VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps full duplex\n");
+ break;
case SPD_DPX_100_HALF:
VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps half duplex\n");
break;
@@ -3170,6 +3188,37 @@ static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full;
+
+ cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
+ if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
+ cmd->advertising |=
+ ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full;
+ } else {
+ switch (vptr->options.spd_dpx) {
+ case SPD_DPX_1000_FULL:
+ cmd->advertising |= ADVERTISED_1000baseT_Full;
+ break;
+ case SPD_DPX_100_HALF:
+ cmd->advertising |= ADVERTISED_100baseT_Half;
+ break;
+ case SPD_DPX_100_FULL:
+ cmd->advertising |= ADVERTISED_100baseT_Full;
+ break;
+ case SPD_DPX_10_HALF:
+ cmd->advertising |= ADVERTISED_10baseT_Half;
+ break;
+ case SPD_DPX_10_FULL:
+ cmd->advertising |= ADVERTISED_10baseT_Full;
+ break;
+ default:
+ break;
+ }
+ }
if (status & VELOCITY_SPEED_1000)
cmd->speed = SPEED_1000;
else if (status & VELOCITY_SPEED_100)
@@ -3200,14 +3249,35 @@ static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd
curr_status &= (~VELOCITY_LINK_FAIL);
new_status |= ((cmd->autoneg) ? VELOCITY_AUTONEG_ENABLE : 0);
+ new_status |= ((cmd->speed == SPEED_1000) ? VELOCITY_SPEED_1000 : 0);
new_status |= ((cmd->speed == SPEED_100) ? VELOCITY_SPEED_100 : 0);
new_status |= ((cmd->speed == SPEED_10) ? VELOCITY_SPEED_10 : 0);
new_status |= ((cmd->duplex == DUPLEX_FULL) ? VELOCITY_DUPLEX_FULL : 0);
- if ((new_status & VELOCITY_AUTONEG_ENABLE) && (new_status != (curr_status | VELOCITY_AUTONEG_ENABLE)))
+ if ((new_status & VELOCITY_AUTONEG_ENABLE) &&
+ (new_status != (curr_status | VELOCITY_AUTONEG_ENABLE))) {
ret = -EINVAL;
- else
+ } else {
+ enum speed_opt spd_dpx;
+
+ if (new_status & VELOCITY_AUTONEG_ENABLE)
+ spd_dpx = SPD_DPX_AUTO;
+ else if ((new_status & VELOCITY_SPEED_1000) &&
+ (new_status & VELOCITY_DUPLEX_FULL)) {
+ spd_dpx = SPD_DPX_1000_FULL;
+ } else if (new_status & VELOCITY_SPEED_100)
+ spd_dpx = (new_status & VELOCITY_DUPLEX_FULL) ?
+ SPD_DPX_100_FULL : SPD_DPX_100_HALF;
+ else if (new_status & VELOCITY_SPEED_10)
+ spd_dpx = (new_status & VELOCITY_DUPLEX_FULL) ?
+ SPD_DPX_10_FULL : SPD_DPX_10_HALF;
+ else
+ return -EOPNOTSUPP;
+
+ vptr->options.spd_dpx = spd_dpx;
+
velocity_set_media_mode(vptr, new_status);
+ }
return ret;
}
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index f7b33ae..df55f6c 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -848,7 +848,7 @@ enum velocity_owner {
* Bits in CHIPGCR register
*/
-#define CHIPGCR_FCGMII 0x80
+#define CHIPGCR_FCGMII 0x80 /* enable GMII mode */
#define CHIPGCR_FCFDX 0x40
#define CHIPGCR_FCRESV 0x20
#define CHIPGCR_FCMODE 0x10
@@ -1390,7 +1390,8 @@ enum speed_opt {
SPD_DPX_100_HALF = 1,
SPD_DPX_100_FULL = 2,
SPD_DPX_10_HALF = 3,
- SPD_DPX_10_FULL = 4
+ SPD_DPX_10_FULL = 4,
+ SPD_DPX_1000_FULL = 5
};
enum velocity_init_type {
--
1.7.2.3
^ permalink raw reply related
* Re: [patch] IPVS: ip_vs_dbg_callid() is only needed for debugging
From: Patrick McHardy @ 2010-10-13 19:23 UTC (permalink / raw)
To: Simon Horman
Cc: lvs-devel, netdev, netfilter-devel, Wensong Zhang,
Julian Anastasov
In-Reply-To: <20101007012325.GA32392@verge.net.au>
Am 07.10.2010 03:23, schrieb Simon Horman:
> ip_vs_dbg_callid() and IP_VS_DEBUG_CALLID() are only needed
> it CONFIG_IP_VS_DEBUG is defined.
>
> This resolves the following build warning when CONFIG_IP_VS_DEBUG is
> not defined.
>
> net/netfilter/ipvs/ip_vs_pe_sip.c:11: warning: 'ip_vs_dbg_callid' defined but not used
Applied, thanks Simon.
^ permalink raw reply
* Re: Question about PHY-less board and "fixed_phy"
From: Grant Edwards @ 2010-10-13 19:21 UTC (permalink / raw)
To: netdev
In-Reply-To: <4CB6032A.8020908@caviumnetworks.com>
On 2010-10-13, David Daney <ddaney@caviumnetworks.com> wrote:
> On 10/13/2010 09:55 AM, Grant Edwards wrote:
>
>> I'm working with an Atmel ARM9 board (macb driver), that doesn't have
>> a PHY.
>>
>> The MAC is connected to a switch via MII. That MII link is hard-wired
>> to be 100M full-duplex.
>>
>>> From what I've been able to google, the "fixed_phy" driver is intended
>> for this situation. But from looking at the fixed.c source code it
>> appears to provide an emulated MDIO bus.
>>
>> I don't want an emulated MDIO bus.
>>
>> I have a real, working MDIO bus.
>>
>> What I don't have is a PHY.
>>
>> The switch presents a bunch of logical slave devices (23, IIRC)
>> attached to the MDIO bus, and I need use the MDIO bus to access those
>> "devices" (mainly from user-space via ioctl() calls). If I use the
>> fixed_phy driver, it appears that it will hide the real MDIO bus and
>> replace it with a fake one that's connected to a fake set of PHY
>> registers. That means I won't be able to access the the registers in
>> the switch to which my MAC is connected.
>>
>> The ethernet/phy architecture seems to be based on several assumptions
>> that aren't true in my case:
>>
>> 1) Every MAC is connected to a PHY.
>
> As long as you handle calling netif_carrier_{on,off}() and some of
> the ndo_do_ioctl commands, I don't think you need a PHY.
Thanks. I'll look into that.
>> 2) An MDIO bus is a point-to-point link between the MAC and the PHY.
>
> This I don't think is the case. See phy_connect() for example. It
> certianly allows for multiple PHYs per bus.
>
> We have a SOC device (Octeon) that has many PHYs on a single MDIO
> bus, and have a separate MDIO bus driver (mdio-octeon.c) that is
> shared between all the Ethernet devices/drivers.
Do you bypass the ioctl code in phy.c that ignores the device id in
the request and instead routes all read/write operations to the PHY's
id?
>> 3) The MDIO bus belongs to the PHY.
>
> ??, The mdio bus lock is taken for some operations, but how does it
> 'belong to' the PHY?
I said that because the ioctl() to do read/write operations on the
mdio bus is a "phy" ioctl() that is handled by phy.c code (in the
drivers I've looked at), and it overwrites any user-provided device ID
with that of the PHY, thus turning the mdio bus into a point-to-point
link to the PHY whose use is controlled by the PHY driver. In my mind
I guess that equates to the mdio bus "belonging to" the PHY.
It looks like I need to change the macb driver to handle those ioctl
requests directly instead of having the phy.c code handle them.
>> 4) It's OK to go out and read arbitrary registers from every device
>> on the MDIO bus when that bus is registered using mdiobus_register().
>
> You can set the struct mii_bus phy_mask element to prevent probing of
> specific addresses.
Ah, I hadn't figured that out yet.
Thanks for the hints!
--
Grant Edwards grant.b.edwards Yow! I know things about
at TROY DONAHUE that can't
gmail.com even be PRINTED!!
^ permalink raw reply
* [patch] gianfar: fix double lock typo
From: Dan Carpenter @ 2010-10-13 19:19 UTC (permalink / raw)
To: Sandeep Gopalpet; +Cc: David S. Miller, netdev, kernel-janitors
This should be a _restore() instead of a _save().
Signed-off-by: Dan Carpenter <error27@gmail.com>
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index ae8e5d3..5c566eb 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -538,7 +538,7 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
unlock_tx_qs(priv);
unlock_rx_qs(priv);
- local_irq_save(flags);
+ local_irq_restore(flags);
for (i = 0; i < priv->num_rx_queues; i++)
gfar_clean_rx_ring(priv->rx_queue[i],
^ permalink raw reply related
* [patch] ns83820: spin_lock_irq() => spin_lock()
From: Dan Carpenter @ 2010-10-13 19:18 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller, kernel-janitors, mingo
This is essentially cosmetic. At this point the IRQs are already
disabled because we called spin_lock_irq(&dev->rx_info.lock).
The real bug here was fixed back in 2006 in 3a10ccebe: "[PATCH] lock
validator: fix ns83820.c irq-flags bug". Prior to that patch, it was
a "spin_lock_irq is not nestable" type bug. The 2006 patch changes the
unlock to not re-enable IRQs, which eliminates the potential deadlock.
But this bit was missed. We should change the lock function as well so
it balances nicely.
Signed-off-by: Dan Carpenter <error27@gmail.com>
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 3bbd0aa..84134c7 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -772,7 +772,7 @@ static int ns83820_setup_rx(struct net_device *ndev)
phy_intr(ndev);
/* Okay, let it rip */
- spin_lock_irq(&dev->misc_lock);
+ spin_lock(&dev->misc_lock);
dev->IMR_cache |= ISR_PHY;
dev->IMR_cache |= ISR_RXRCMP;
//dev->IMR_cache |= ISR_RXERR;
^ permalink raw reply related
* Re: Question about PHY-less board and "fixed_phy"
From: David Daney @ 2010-10-13 19:06 UTC (permalink / raw)
To: Grant Edwards; +Cc: netdev
In-Reply-To: <i94oag$epv$1@dough.gmane.org>
On 10/13/2010 09:55 AM, Grant Edwards wrote:
>
> I'm working with an Atmel ARM9 board (macb driver), that doesn't have
> a PHY.
>
> The MAC is connected to a switch via MII. That MII link is hard-wired
> to be 100M full-duplex.
>
>> From what I've been able to google, the "fixed_phy" driver is intended
> for this situation. But from looking at the fixed.c source code it
> appears to provide an emulated MDIO bus.
>
> I don't want an emulated MDIO bus.
>
> I have a real, working MDIO bus.
>
> What I don't have is a PHY.
>
> The switch presents a bunch of logical slave devices (23, IIRC)
> attached to the MDIO bus, and I need use the MDIO bus to access those
> "devices" (mainly from user-space via ioctl() calls). If I use the
> fixed_phy driver, it appears that it will hide the real MDIO bus and
> replace it with a fake one that's connected to a fake set of PHY
> registers. That means I won't be able to access the the registers in
> the switch to which my MAC is connected.
>
> The ethernet/phy architecture seems to be based on several assumptions
> that aren't true in my case:
>
> 1) Every MAC is connected to a PHY.
As long as you handle calling netif_carrier_{on,off}() and some of the
ndo_do_ioctl commands, I don't think you need a PHY.
>
> 2) An MDIO bus is a point-to-point link between the MAC and the PHY.
This I don't think is the case. See phy_connect() for example. It
certianly allows for multiple PHYs per bus.
We have a SOC device (Octeon) that has many PHYs on a single MDIO bus,
and have a separate MDIO bus driver (mdio-octeon.c) that is shared
between all the Ethernet devices/drivers.
>
> 3) The MDIO bus belongs to the PHY.
>
??, The mdio bus lock is taken for some operations, but how does it
'belong to' the PHY?
> 4) It's OK to go out and read arbitrary registers from every device
> on the MDIO bus when that bus is registered using mdiobus_register().
>
You can set the struct mii_bus phy_mask element to prevent probing of
specific addresses.
> [Hmm, #4 may be true in my case, but it seems like a dangerous assumption.]
>
> Anyway, I'm confused on how the MAC/PHY architecture is meant to deal
> with the case where there is no PHY, but there are real devices
> attached to a real MDIO bus which needs to be accessed both from the
> Ethernet driver and from userspace using the normal user-space ioctl()
> call.
>
> Do I need to write my own "fixed_phy" driver that presents a virtual
> PHY without putting a fake MDIO bus in place?
>
> How _do_ you present a virtual PHY without faking an MDIO bus?
>
> Do I need _two_ MDIO buses, the real one that is used to communicate
> with the switch chip and a fake one that's used to talk to a fake PHY?
> If so, how do I associate two MDIO buses with a single Ethernet
> interface?
>
> How do you register an mdio bus without having every device on the bus
> accessed?
>
> Can anybody loan me a clue?
>
> Another thing I don't understand is that it looks to me like the
> ioctl() to access devices on the mdio bus is handled by the PHY driver
> when it should be handled by the Ethernet driver: the MDIO bus belongs
> to the MAC, not the PHY.
>
> The PHY driver apparently ignores the device ID specified by the user
> and forces the device ID to that of the PHY, thus cutting of access to
> any other devices on the bus. [I've worked around that by kludging
> the Ethernet driver's mdio_read/write routines so that I can specify
> the device ID by placing it in the upper 8 bits of the 16-bit register
> number (which is left unchanged as it passes through the PHY driver).]
>
> This doesn't make sense to me. Why provide a device ID in the ioctl()
> API, and then overwrite it as the request passes through the PHY
> driver to the Ethernet driver. Why are ioctl() MDIO register
> read/write requests that are done on an Ethernet interface passed
> through the PHY driver?
>
> I've read and re-read the phy.txt file under Documentation, and I've
> looked at the fixed_phy source and sources of drivers where it is
> used, but I'm still in the dark...
>
^ permalink raw reply
* [PATCH net-next] fib: avoid false sharing on fib_table_hash
From: Eric Dumazet @ 2010-10-13 18:22 UTC (permalink / raw)
To: David Miller; +Cc: netdev
While doing profile analysis, I found fib_hash_table was sometime in a
cache line shared by a possibly often written kernel structure.
(CONFIG_IP_ROUTE_MULTIPATH || !CONFIG_IPV6_MULTIPLE_TABLES)
It's hard to detect because not easily reproductible.
Make sure we allocate a full cache line to keep this shared in all cpus
caches.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
We probably need a generic kernel function, but it might take time...
net/ipv4/fib_frontend.c | 11 +++++------
net/ipv6/ip6_fib.c | 9 ++++++---
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 919f2ad..3df057e 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -1016,16 +1016,15 @@ static struct notifier_block fib_netdev_notifier = {
static int __net_init ip_fib_net_init(struct net *net)
{
int err;
- unsigned int i;
+ size_t size = sizeof(struct hlist_head) * FIB_TABLE_HASHSZ;
+
+ /* Avoid false sharing : Use at least a full cache line */
+ size = max_t(size_t, size, L1_CACHE_BYTES);
- net->ipv4.fib_table_hash = kzalloc(
- sizeof(struct hlist_head)*FIB_TABLE_HASHSZ, GFP_KERNEL);
+ net->ipv4.fib_table_hash = kzalloc(size, GFP_KERNEL);
if (net->ipv4.fib_table_hash == NULL)
return -ENOMEM;
- for (i = 0; i < FIB_TABLE_HASHSZ; i++)
- INIT_HLIST_HEAD(&net->ipv4.fib_table_hash[i]);
-
err = fib4_rules_init(net);
if (err < 0)
goto fail;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index b6a5859..de38211 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1500,15 +1500,18 @@ static void fib6_gc_timer_cb(unsigned long arg)
static int __net_init fib6_net_init(struct net *net)
{
+ size_t size = sizeof(struct hlist_head) * FIB6_TABLE_HASHSZ;
+
setup_timer(&net->ipv6.ip6_fib_timer, fib6_gc_timer_cb, (unsigned long)net);
net->ipv6.rt6_stats = kzalloc(sizeof(*net->ipv6.rt6_stats), GFP_KERNEL);
if (!net->ipv6.rt6_stats)
goto out_timer;
- net->ipv6.fib_table_hash = kcalloc(FIB6_TABLE_HASHSZ,
- sizeof(*net->ipv6.fib_table_hash),
- GFP_KERNEL);
+ /* Avoid false sharing : Use at least a full cache line */
+ size = max_t(size_t, size, L1_CACHE_BYTES);
+
+ net->ipv6.fib_table_hash = kzalloc(size, GFP_KERNEL);
if (!net->ipv6.fib_table_hash)
goto out_rt6_stats;
^ permalink raw reply related
* Re: [PATCH net-next 5/5] tipc: clean out all instances of #if 0'd unused code
From: Neil Horman @ 2010-10-13 17:23 UTC (permalink / raw)
To: Paul Gortmaker; +Cc: davem, netdev, allan.stephens
In-Reply-To: <4CB5E79B.4060507@windriver.com>
On Wed, Oct 13, 2010 at 01:08:43PM -0400, Paul Gortmaker wrote:
> On 10-10-13 12:26 PM, Neil Horman wrote:
> > On Tue, Oct 12, 2010 at 08:25:58PM -0400, Paul Gortmaker wrote:
> >> Remove all instances of legacy, or as yet to be implemented code
> >> that is currently living within an #if 0 ... #endif block.
> >> In the rare instance that some of it be needed in the future,
> >> it can still be dragged out of history, but there is no need
> >> for it to sit in mainline.
> >>
> >> Signed-off-by: Paul Gortmaker<paul.gortmaker@windriver.com>
> > Acked-by: Neil Horman<nhorman@tuxdriver.com>
> >
>
> Thanks for all the reviews. As I'd indicated a while back, I
> am by far no TIPC expert, so it may take me a bit to digest
> it and rework things on 1 --> 4. That will probably put them
> into the "for-38" net-next timeframe, as I'm guessing net-next
> that is destined for 2.6.37 will close in a day or two.
>
No problem, Most of what I identified I don't think is strictly a tipc related
issue, they're more just correct usage of various primitives (i.e. don't
initalize a work queue every time right before you schedule it), and use
list_add/list_del, instead of just munging data structures onto a list). Most
looks pretty easy to correct I think. Allan can probably help you out if tipc
specific knoweldge is needed.
Neil
> This cleanup patch (patch #5) doesn't explicitly depend on
> the other 4 bearer related patches, so it can be applied
> at whatever time is most convenient for Dave.
>
> Paul.
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [PATCH net-next 5/5] tipc: clean out all instances of #if 0'd unused code
From: Paul Gortmaker @ 2010-10-13 17:08 UTC (permalink / raw)
To: Neil Horman; +Cc: davem, netdev, allan.stephens
In-Reply-To: <20101013162652.GF31379@hmsreliant.think-freely.org>
On 10-10-13 12:26 PM, Neil Horman wrote:
> On Tue, Oct 12, 2010 at 08:25:58PM -0400, Paul Gortmaker wrote:
>> Remove all instances of legacy, or as yet to be implemented code
>> that is currently living within an #if 0 ... #endif block.
>> In the rare instance that some of it be needed in the future,
>> it can still be dragged out of history, but there is no need
>> for it to sit in mainline.
>>
>> Signed-off-by: Paul Gortmaker<paul.gortmaker@windriver.com>
> Acked-by: Neil Horman<nhorman@tuxdriver.com>
>
Thanks for all the reviews. As I'd indicated a while back, I
am by far no TIPC expert, so it may take me a bit to digest
it and rework things on 1 --> 4. That will probably put them
into the "for-38" net-next timeframe, as I'm guessing net-next
that is destined for 2.6.37 will close in a day or two.
This cleanup patch (patch #5) doesn't explicitly depend on
the other 4 bearer related patches, so it can be applied
at whatever time is most convenient for Dave.
Paul.
^ permalink raw reply
* Question about PHY-less board and "fixed_phy"
From: Grant Edwards @ 2010-10-13 16:55 UTC (permalink / raw)
To: netdev
I'm working with an Atmel ARM9 board (macb driver), that doesn't have
a PHY.
The MAC is connected to a switch via MII. That MII link is hard-wired
to be 100M full-duplex.
>From what I've been able to google, the "fixed_phy" driver is intended
for this situation. But from looking at the fixed.c source code it
appears to provide an emulated MDIO bus.
I don't want an emulated MDIO bus.
I have a real, working MDIO bus.
What I don't have is a PHY.
The switch presents a bunch of logical slave devices (23, IIRC)
attached to the MDIO bus, and I need use the MDIO bus to access those
"devices" (mainly from user-space via ioctl() calls). If I use the
fixed_phy driver, it appears that it will hide the real MDIO bus and
replace it with a fake one that's connected to a fake set of PHY
registers. That means I won't be able to access the the registers in
the switch to which my MAC is connected.
The ethernet/phy architecture seems to be based on several assumptions
that aren't true in my case:
1) Every MAC is connected to a PHY.
2) An MDIO bus is a point-to-point link between the MAC and the PHY.
3) The MDIO bus belongs to the PHY.
4) It's OK to go out and read arbitrary registers from every device
on the MDIO bus when that bus is registered using mdiobus_register().
[Hmm, #4 may be true in my case, but it seems like a dangerous assumption.]
Anyway, I'm confused on how the MAC/PHY architecture is meant to deal
with the case where there is no PHY, but there are real devices
attached to a real MDIO bus which needs to be accessed both from the
Ethernet driver and from userspace using the normal user-space ioctl()
call.
Do I need to write my own "fixed_phy" driver that presents a virtual
PHY without putting a fake MDIO bus in place?
How _do_ you present a virtual PHY without faking an MDIO bus?
Do I need _two_ MDIO buses, the real one that is used to communicate
with the switch chip and a fake one that's used to talk to a fake PHY?
If so, how do I associate two MDIO buses with a single Ethernet
interface?
How do you register an mdio bus without having every device on the bus
accessed?
Can anybody loan me a clue?
Another thing I don't understand is that it looks to me like the
ioctl() to access devices on the mdio bus is handled by the PHY driver
when it should be handled by the Ethernet driver: the MDIO bus belongs
to the MAC, not the PHY.
The PHY driver apparently ignores the device ID specified by the user
and forces the device ID to that of the PHY, thus cutting of access to
any other devices on the bus. [I've worked around that by kludging
the Ethernet driver's mdio_read/write routines so that I can specify
the device ID by placing it in the upper 8 bits of the 16-bit register
number (which is left unchanged as it passes through the PHY driver).]
This doesn't make sense to me. Why provide a device ID in the ioctl()
API, and then overwrite it as the request passes through the PHY
driver to the Ethernet driver. Why are ioctl() MDIO register
read/write requests that are done on an Ethernet interface passed
through the PHY driver?
I've read and re-read the phy.txt file under Documentation, and I've
looked at the fixed_phy source and sources of drivers where it is
used, but I'm still in the dark...
--
Grant Edwards grant.b.edwards Yow! Somewhere in Tenafly,
at New Jersey, a chiropractor
gmail.com is viewing "Leave it to
Beaver"!
^ permalink raw reply
* [PATCH net-next] fib_trie: use fls() instead of open coded loop
From: Eric Dumazet @ 2010-10-13 16:56 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Robert Olsson
fib_table_lookup() might use fls() to speedup an open coded loop.
Noticed while doing a profile analysis.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
net/ipv4/fib_trie.c | 16 ++++------------
1 file changed, 4 insertions(+), 12 deletions(-)
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 271c89b..31494f3 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1384,8 +1384,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
t_key cindex = 0;
int current_prefix_length = KEYLENGTH;
struct tnode *cn;
- t_key node_prefix, key_prefix, pref_mismatch;
- int mp;
+ t_key pref_mismatch;
rcu_read_lock();
@@ -1500,10 +1499,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
* matching prefix.
*/
- node_prefix = mask_pfx(cn->key, cn->pos);
- key_prefix = mask_pfx(key, cn->pos);
- pref_mismatch = key_prefix^node_prefix;
- mp = 0;
+ pref_mismatch = mask_pfx(cn->key ^ key, cn->pos);
/*
* In short: If skipped bits in this node do not match
@@ -1511,13 +1507,9 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
* state.directly.
*/
if (pref_mismatch) {
- while (!(pref_mismatch & (1<<(KEYLENGTH-1)))) {
- mp++;
- pref_mismatch = pref_mismatch << 1;
- }
- key_prefix = tkey_extract_bits(cn->key, mp, cn->pos-mp);
+ int mp = KEYLENGTH - fls(pref_mismatch);
- if (key_prefix != 0)
+ if (tkey_extract_bits(cn->key, mp, cn->pos - mp) != 0)
goto backtrace;
if (current_prefix_length >= cn->pos)
^ permalink raw reply related
* Re: [PATCH] net: allow FEC driver to use fixed PHY support
From: David Miller @ 2010-10-13 16:56 UTC (permalink / raw)
To: gerg; +Cc: netdev, gerg
In-Reply-To: <201010120703.o9C735Jd026818@goober.internal.moreton.com.au>
From: Greg Ungerer <gerg@snapgear.com>
Date: Tue, 12 Oct 2010 17:03:05 +1000
> At least one board using the FEC driver does not have a conventional
> PHY attached to it, it is directly connected to a somewhat simple
> ethernet switch (the board is the SnapGear/LITE, and the attached
> 4-port ethernet switch is a RealTek RTL8305). This switch does not
> present the usual register interface of a PHY, it presents nothing.
> So a PHY scan will find nothing - it finds ID's of 0 for each PHY
> on the attached MII bus.
>
> After the FEC driver was changed to use phylib for supporting PHYs
> it no longer works on this particular board/switch setup.
>
> Add code support to use a fixed phy if no PHY is found on the MII bus.
> This is based on the way the cpmac.c driver solved this same problem.
>
> Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Applied, thanks Greg.
^ permalink raw reply
* Re: linux-next: Tree for October 13 (net/3c59x)
From: David Miller @ 2010-10-13 16:54 UTC (permalink / raw)
To: randy.dunlap; +Cc: sfr, netdev, linux-next, linux-kernel
In-Reply-To: <20101013093836.1ee6f2f9.randy.dunlap@oracle.com>
From: Randy Dunlap <randy.dunlap@oracle.com>
Date: Wed, 13 Oct 2010 09:38:36 -0700
> On Wed, 13 Oct 2010 15:45:22 +1100 Stephen Rothwell wrote:
>
>> Hi all,
>>
>> Changes since 20101012:
>
>
> when CONFIG_PCI is not enabled:
>
> drivers/net/3c59x.c:3211: error:request for member 'current_state' in something not a structure or union
Like all the other PCI interfaces that NOP out into empty inlines when
CONFIG_PCI is not enabled, it would be nice to have an interface that
provides pci_dev->current_state in a similar fashion so we don't have
to add a bunch of ifdefs here.
^ permalink raw reply
* Re: [PATCH] b44: fix resume, request_irq after hw reset
From: David Miller @ 2010-10-13 16:46 UTC (permalink / raw)
To: james
Cc: zambrano, jpirko, fujita.tomonori, hauke, Larry.Finger, netdev,
linux-kernel
In-Reply-To: <201010120022.13171.james@albanarts.com>
From: James Hogan <james@albanarts.com>
Date: Tue, 12 Oct 2010 00:22:12 +0100
> @@ -2309,6 +2303,12 @@ static int b44_resume(struct ssb_device *sdev)
> netif_device_attach(bp->dev);
> spin_unlock_irq(&bp->lock);
>
> + rc = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
> + if (rc) {
> + netdev_err(dev, "request_irq failed\n");
> + return rc;
> + }
> +
> b44_enable_ints(bp);
> netif_wake_queue(dev);
Since you've moved the request_irq() down, you'll need to adjust
the error handling so that it undoes side effects made by this
function up until this point.
F.e. netif_device_attach() has to be undone for one thing.
Next, b44_init_rings() allocates memory that you must now free.
Etc. etc. etc.
This change is not so simple. :-)
^ permalink raw reply
* Re: linux-next: Tree for October 13 (net/3c59x)
From: Randy Dunlap @ 2010-10-13 16:38 UTC (permalink / raw)
To: Stephen Rothwell, netdev; +Cc: linux-next, LKML
In-Reply-To: <20101013154522.7b087a20.sfr@canb.auug.org.au>
On Wed, 13 Oct 2010 15:45:22 +1100 Stephen Rothwell wrote:
> Hi all,
>
> Changes since 20101012:
when CONFIG_PCI is not enabled:
drivers/net/3c59x.c:3211: error:request for member 'current_state' in something not a structure or union
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
^ permalink raw reply
* Re: [PATCH net-next 5/5] tipc: clean out all instances of #if 0'd unused code
From: Neil Horman @ 2010-10-13 16:26 UTC (permalink / raw)
To: Paul Gortmaker; +Cc: davem, netdev, allan.stephens
In-Reply-To: <1286929558-2954-5-git-send-email-paul.gortmaker@windriver.com>
On Tue, Oct 12, 2010 at 08:25:58PM -0400, Paul Gortmaker wrote:
> Remove all instances of legacy, or as yet to be implemented code
> that is currently living within an #if 0 ... #endif block.
> In the rare instance that some of it be needed in the future,
> it can still be dragged out of history, but there is no need
> for it to sit in mainline.
>
> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
^ permalink raw reply
* Re: [PATCH net-next 4/5] tipc: Rework data structures that track neighboring nodes and links
From: Neil Horman @ 2010-10-13 16:24 UTC (permalink / raw)
To: Paul Gortmaker; +Cc: davem, netdev, allan.stephens
In-Reply-To: <1286929558-2954-4-git-send-email-paul.gortmaker@windriver.com>
On Tue, Oct 12, 2010 at 08:25:57PM -0400, Paul Gortmaker wrote:
> From: Allan Stephens <allan.stephens@windriver.com>
>
> Convert existing linked list of neighboring nodes to a standard
> doubly-linked list. Add counters that track total number of nodes
> in list and total number of links to these nodes, thereby allowing
> configuration message replies to allocate only space based on
> the actual number of nodes and links rather than the worst case.
>
> Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
> ---
> net/tipc/bcast.c | 5 ++-
> net/tipc/link.c | 3 +-
> net/tipc/node.c | 60 ++++++++++++++++++++++++++---------------------------
> net/tipc/node.h | 5 +--
> 4 files changed, 36 insertions(+), 37 deletions(-)
>
NAK, this is completely broken. You're casting tipc_node structure as
struct list_heads. That basically makes the first 64 (or 128 bits on 64 bit
arches) act like a list_heads prev and next pointers. So if you use node like a
list head, you're corrupting those first 64 or 128 bits. If you modify
node->addr, node->lock, etc, you're corrupting your list pointers. What you
want is an empty list head pointer defined somewhere to serve as the head of
your list, and to use the node_list member that you added to tipc_node to serve
as your list member in the use of list_add, list_del and list_for_each_entry
calls.
Neil
> diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
> index ba6dcb2..e006678 100644
> --- a/net/tipc/bcast.c
> +++ b/net/tipc/bcast.c
> @@ -454,10 +454,11 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
> tipc_node_unlock(node);
> spin_lock_bh(&bc_lock);
> bcl->stats.recv_nacks++;
> - bcl->owner->next = node; /* remember requestor */
> + /* remember retransmit requester */
> + bcl->owner->node_list.next =
> + (struct list_head *)node;
> bclink_retransmit_pkt(msg_bcgap_after(msg),
> msg_bcgap_to(msg));
> - bcl->owner->next = NULL;
> spin_unlock_bh(&bc_lock);
> } else {
> tipc_bclink_peek_nack(msg_destnode(msg),
> diff --git a/net/tipc/link.c b/net/tipc/link.c
> index 54bd99d..13bc0b6 100644
> --- a/net/tipc/link.c
> +++ b/net/tipc/link.c
> @@ -1652,7 +1652,8 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf)
> tipc_printf(TIPC_OUTPUT, "Outstanding acks: %lu\n",
> (unsigned long) TIPC_SKB_CB(buf)->handle);
>
> - n_ptr = l_ptr->owner->next;
> + /* recover retransmit requester */
> + n_ptr = (struct tipc_node *)l_ptr->owner->node_list.next;
> tipc_node_lock(n_ptr);
>
> tipc_addr_string_fill(addr_string, n_ptr->addr);
> diff --git a/net/tipc/node.c b/net/tipc/node.c
> index 7c49cd0..944b480 100644
> --- a/net/tipc/node.c
> +++ b/net/tipc/node.c
> @@ -50,7 +50,9 @@ void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str);
> static void node_lost_contact(struct tipc_node *n_ptr);
> static void node_established_contact(struct tipc_node *n_ptr);
>
> -struct tipc_node *tipc_nodes = NULL; /* sorted list of nodes within cluster */
> +static LIST_HEAD(nodes_list); /* sorted list of neighboring nodes */
> +static int node_count; /* number of neighboring nodes that exist */
> +static int link_count; /* number of unicast links node currently has */
>
> static DEFINE_SPINLOCK(node_create_lock);
>
> @@ -70,11 +72,11 @@ struct tipc_node *tipc_node_create(u32 addr)
> {
> struct cluster *c_ptr;
> struct tipc_node *n_ptr;
> - struct tipc_node **curr_node;
> + struct tipc_node *new_n_ptr;
>
> spin_lock_bh(&node_create_lock);
>
> - for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
> + list_for_each_entry(n_ptr, &nodes_list, node_list) {
> if (addr < n_ptr->addr)
> break;
> if (addr == n_ptr->addr) {
> @@ -83,8 +85,8 @@ struct tipc_node *tipc_node_create(u32 addr)
> }
> }
>
> - n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC);
> - if (!n_ptr) {
> + new_n_ptr = kzalloc(sizeof(*new_n_ptr), GFP_ATOMIC);
> + if (!new_n_ptr) {
> spin_unlock_bh(&node_create_lock);
> warn("Node creation failed, no memory\n");
> return NULL;
> @@ -96,28 +98,22 @@ struct tipc_node *tipc_node_create(u32 addr)
> }
> if (!c_ptr) {
> spin_unlock_bh(&node_create_lock);
> - kfree(n_ptr);
> + kfree(new_n_ptr);
> return NULL;
> }
>
> - n_ptr->addr = addr;
> - spin_lock_init(&n_ptr->lock);
> - INIT_LIST_HEAD(&n_ptr->nsub);
> - n_ptr->owner = c_ptr;
> - tipc_cltr_attach_node(c_ptr, n_ptr);
> - n_ptr->last_router = -1;
> + new_n_ptr->addr = addr;
> + spin_lock_init(&new_n_ptr->lock);
> + INIT_LIST_HEAD(&new_n_ptr->nsub);
> + new_n_ptr->owner = c_ptr;
> + tipc_cltr_attach_node(c_ptr, new_n_ptr);
> + new_n_ptr->last_router = -1;
> +
> + list_add_tail(&new_n_ptr->node_list, &n_ptr->node_list);
> + node_count++;
>
> - /* Insert node into ordered list */
> - for (curr_node = &tipc_nodes; *curr_node;
> - curr_node = &(*curr_node)->next) {
> - if (addr < (*curr_node)->addr) {
> - n_ptr->next = *curr_node;
> - break;
> - }
> - }
> - (*curr_node) = n_ptr;
> spin_unlock_bh(&node_create_lock);
> - return n_ptr;
> + return new_n_ptr;
> }
>
> void tipc_node_delete(struct tipc_node *n_ptr)
> @@ -136,6 +132,8 @@ void tipc_node_delete(struct tipc_node *n_ptr)
> #endif
>
> dbg("node %x deleted\n", n_ptr->addr);
> + node_count--;
> + list_del(&n_ptr->node_list);
> kfree(n_ptr);
> }
>
> @@ -275,6 +273,7 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr)
> n_ptr->links[bearer_id] = l_ptr;
> tipc_net.zones[tipc_zone(l_ptr->addr)]->links++;
> n_ptr->link_cnt++;
> + link_count++;
> return n_ptr;
> }
> err("Attempt to establish second link on <%s> to %s\n",
> @@ -289,6 +288,7 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr)
> n_ptr->links[l_ptr->b_ptr->identity] = NULL;
> tipc_net.zones[tipc_zone(l_ptr->addr)]->links--;
> n_ptr->link_cnt--;
> + link_count--;
> }
>
> /*
> @@ -619,7 +619,7 @@ u32 tipc_available_nodes(const u32 domain)
> u32 cnt = 0;
>
> read_lock_bh(&tipc_net_lock);
> - for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
> + list_for_each_entry(n_ptr, &nodes_list, node_list) {
> if (!tipc_in_scope(domain, n_ptr->addr))
> continue;
> if (tipc_node_is_up(n_ptr))
> @@ -646,15 +646,14 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
> " (network address)");
>
> read_lock_bh(&tipc_net_lock);
> - if (!tipc_nodes) {
> + if (!node_count) {
> read_unlock_bh(&tipc_net_lock);
> return tipc_cfg_reply_none();
> }
>
> - /* For now, get space for all other nodes
> - (will need to modify this when slave nodes are supported */
> + /* Get space for all neighboring nodes */
>
> - payload_size = TLV_SPACE(sizeof(node_info)) * (tipc_max_nodes - 1);
> + payload_size = TLV_SPACE(sizeof(node_info)) * node_count;
> if (payload_size > 32768u) {
> read_unlock_bh(&tipc_net_lock);
> return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
> @@ -668,7 +667,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
>
> /* Add TLVs for all nodes in scope */
>
> - for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
> + list_for_each_entry(n_ptr, &nodes_list, node_list) {
> if (!tipc_in_scope(domain, n_ptr->addr))
> continue;
> node_info.addr = htonl(n_ptr->addr);
> @@ -704,8 +703,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
>
> /* Get space for all unicast links + multicast link */
>
> - payload_size = TLV_SPACE(sizeof(link_info)) *
> - (tipc_net.zones[tipc_zone(tipc_own_addr)]->links + 1);
> + payload_size = TLV_SPACE(sizeof(link_info)) * (link_count + 1);
> if (payload_size > 32768u) {
> read_unlock_bh(&tipc_net_lock);
> return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
> @@ -726,7 +724,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
>
> /* Add TLVs for any other links in scope */
>
> - for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
> + list_for_each_entry(n_ptr, &nodes_list, node_list) {
> u32 i;
>
> if (!tipc_in_scope(domain, n_ptr->addr))
> diff --git a/net/tipc/node.h b/net/tipc/node.h
> index 45f3db3..26715dc 100644
> --- a/net/tipc/node.h
> +++ b/net/tipc/node.h
> @@ -47,7 +47,7 @@
> * @addr: network address of node
> * @lock: spinlock governing access to structure
> * @owner: pointer to cluster that node belongs to
> - * @next: pointer to next node in sorted list of cluster's nodes
> + * @node_list: adjacent entries in sorted list of nodes
> * @nsub: list of "node down" subscriptions monitoring node
> * @active_links: pointers to active links to node
> * @links: pointers to all links to node
> @@ -73,7 +73,7 @@ struct tipc_node {
> u32 addr;
> spinlock_t lock;
> struct cluster *owner;
> - struct tipc_node *next;
> + struct list_head node_list;
> struct list_head nsub;
> struct link *active_links[2];
> struct link *links[MAX_BEARERS];
> @@ -96,7 +96,6 @@ struct tipc_node {
> } bclink;
> };
>
> -extern struct tipc_node *tipc_nodes;
> extern u32 tipc_own_tag;
>
> struct tipc_node *tipc_node_create(u32 addr);
> --
> 1.7.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [-next Oct 13] Build failure drivers/s390/net/ctcm_mpc.o
From: David Miller @ 2010-10-13 16:12 UTC (permalink / raw)
To: sachinp; +Cc: netdev, linux-next, linux-s390, ursula.braun, eric.dumazet
In-Reply-To: <4CB5CB9C.9030603@in.ibm.com>
From: Sachin Sant <sachinp@in.ibm.com>
Date: Wed, 13 Oct 2010 20:39:16 +0530
> Today's next fails to build on a s390 box with following
> error
>
> drivers/s390/net/ctcm_mpc.c: In function ctc_mpc_dealloc_ch:
> drivers/s390/net/ctcm_mpc.c:541: error: struct net_device has no
> member named refcnt
This should fix it:
--------------------
s390: ctcm_mpc: Fix build after netdev refcount changes.
Reported-by: Sachin Sant <sachinp@in.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/s390/net/ctcm_mpc.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index 2861e78..b64881f 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -540,7 +540,7 @@ void ctc_mpc_dealloc_ch(int port_num)
CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_DEBUG,
"%s: %s: refcount = %d\n",
- CTCM_FUNTAIL, dev->name, atomic_read(&dev->refcnt));
+ CTCM_FUNTAIL, dev->name, netdev_refcnt_read(dev));
fsm_deltimer(&priv->restart_timer);
grp->channels_terminating = 0;
--
1.7.3.1
^ permalink raw reply related
* Re: [PATCH net-next] net: allocate skbs on local node
From: Christoph Lameter @ 2010-10-13 16:00 UTC (permalink / raw)
To: David Rientjes
Cc: Pekka Enberg, Andrew Morton, Eric Dumazet, David Miller, netdev,
Michael Chan, Eilon Greenstein, Christoph Hellwig, LKML,
Nick Piggin
In-Reply-To: <alpine.DEB.2.00.1010121234380.10165@chino.kir.corp.google.com>
On Tue, 12 Oct 2010, David Rientjes wrote:
> > Take the unified as a SLAB cleanup instead? Then at least we have
> > a large common code base and just differentiate through the locking
> > mechanism?
> >
>
> Will you be adding the extensive slub debugging to slab then? It would be
> a shame to lose it because one allocator is chosen over another for
> performance reasons and then we need to recompile to debug issues as they
> arise.
Well basically we would copy SLUB to SLAB apply unification patches to
SLAB instead of SLUBB. We first have to make sure that the unified patches
have the same performance as SLAB.
It maybe much better to isolate the debug features and general bootstrap
from the particulars of the allocation strategy of either SLUB or SLAB.
That way a common code base exists and it would be easier to add different
allocation strategies.
Basically have slab.c with the basic functions and then slab_queueing.c
and slab_noqueue.c for SLAB/SLUB with the particulars of the allocation
strategy?
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox