Commit b0e1e646 authored by David S. Miller's avatar David S. Miller

netdev: Move rest of qdisc state into struct netdev_queue

Now qdisc, qdisc_sleeping, and qdisc_list also live there.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 555353cf
...@@ -287,7 +287,7 @@ isdn_net_unbind_channel(isdn_net_local * lp) ...@@ -287,7 +287,7 @@ isdn_net_unbind_channel(isdn_net_local * lp)
BEWARE! This chunk of code cannot be called from hardware BEWARE! This chunk of code cannot be called from hardware
interrupt handler. I hope it is true. --ANK interrupt handler. I hope it is true. --ANK
*/ */
qdisc_reset(lp->netdev->dev->qdisc); qdisc_reset(lp->netdev->dev->tx_queue.qdisc);
} }
lp->dialstate = 0; lp->dialstate = 0;
dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL; dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
......
...@@ -451,6 +451,9 @@ static inline void napi_synchronize(const struct napi_struct *n) ...@@ -451,6 +451,9 @@ static inline void napi_synchronize(const struct napi_struct *n)
struct netdev_queue { struct netdev_queue {
spinlock_t lock; spinlock_t lock;
struct net_device *dev; struct net_device *dev;
struct Qdisc *qdisc;
struct Qdisc *qdisc_sleeping;
struct list_head qdisc_list;
}; };
/* /*
...@@ -634,13 +637,6 @@ struct net_device ...@@ -634,13 +637,6 @@ struct net_device
struct Qdisc *qdisc_ingress; struct Qdisc *qdisc_ingress;
/*
* Cache line mostly used on queue transmit path (qdisc)
*/
/* device queue lock */
struct Qdisc *qdisc;
struct Qdisc *qdisc_sleeping;
struct list_head qdisc_list;
unsigned long tx_queue_len; /* Max frames per queue allowed */ unsigned long tx_queue_len; /* Max frames per queue allowed */
/* Partially transmitted GSO packet. */ /* Partially transmitted GSO packet. */
......
...@@ -223,7 +223,7 @@ int irda_device_is_receiving(struct net_device *dev); ...@@ -223,7 +223,7 @@ int irda_device_is_receiving(struct net_device *dev);
/* Interface for internal use */ /* Interface for internal use */
static inline int irda_device_txqueue_empty(const struct net_device *dev) static inline int irda_device_txqueue_empty(const struct net_device *dev)
{ {
return skb_queue_empty(&dev->qdisc->q); return skb_queue_empty(&dev->tx_queue.qdisc->q);
} }
int irda_device_set_raw_mode(struct net_device* self, int status); int irda_device_set_raw_mode(struct net_device* self, int status);
struct net_device *alloc_irdadev(int sizeof_priv); struct net_device *alloc_irdadev(int sizeof_priv);
......
...@@ -1720,14 +1720,14 @@ int dev_queue_xmit(struct sk_buff *skb) ...@@ -1720,14 +1720,14 @@ int dev_queue_xmit(struct sk_buff *skb)
* also serializes access to the device queue. * also serializes access to the device queue.
*/ */
q = rcu_dereference(dev->qdisc); q = rcu_dereference(txq->qdisc);
#ifdef CONFIG_NET_CLS_ACT #ifdef CONFIG_NET_CLS_ACT
skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS); skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS);
#endif #endif
if (q->enqueue) { if (q->enqueue) {
/* Grab device queue */ /* Grab device queue */
spin_lock(&txq->lock); spin_lock(&txq->lock);
q = dev->qdisc; q = txq->qdisc;
if (q->enqueue) { if (q->enqueue) {
/* reset queue_mapping to zero */ /* reset queue_mapping to zero */
skb_set_queue_mapping(skb, 0); skb_set_queue_mapping(skb, 0);
......
...@@ -79,8 +79,10 @@ static void rfc2863_policy(struct net_device *dev) ...@@ -79,8 +79,10 @@ static void rfc2863_policy(struct net_device *dev)
static int linkwatch_urgent_event(struct net_device *dev) static int linkwatch_urgent_event(struct net_device *dev)
{ {
struct netdev_queue *txq = &dev->tx_queue;
return netif_running(dev) && netif_carrier_ok(dev) && return netif_running(dev) && netif_carrier_ok(dev) &&
dev->qdisc != dev->qdisc_sleeping; txq->qdisc != txq->qdisc_sleeping;
} }
...@@ -181,7 +183,9 @@ static void __linkwatch_run_queue(int urgent_only) ...@@ -181,7 +183,9 @@ static void __linkwatch_run_queue(int urgent_only)
rfc2863_policy(dev); rfc2863_policy(dev);
if (dev->flags & IFF_UP) { if (dev->flags & IFF_UP) {
if (netif_carrier_ok(dev)) { if (netif_carrier_ok(dev)) {
WARN_ON(dev->qdisc_sleeping == &noop_qdisc); struct netdev_queue *txq = &dev->tx_queue;
WARN_ON(txq->qdisc_sleeping == &noop_qdisc);
dev_activate(dev); dev_activate(dev);
} else } else
dev_deactivate(dev); dev_deactivate(dev);
......
...@@ -605,6 +605,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, ...@@ -605,6 +605,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
int type, u32 pid, u32 seq, u32 change, int type, u32 pid, u32 seq, u32 change,
unsigned int flags) unsigned int flags)
{ {
struct netdev_queue *txq;
struct ifinfomsg *ifm; struct ifinfomsg *ifm;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
struct net_device_stats *stats; struct net_device_stats *stats;
...@@ -635,8 +636,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, ...@@ -635,8 +636,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
if (dev->master) if (dev->master)
NLA_PUT_U32(skb, IFLA_MASTER, dev->master->ifindex); NLA_PUT_U32(skb, IFLA_MASTER, dev->master->ifindex);
if (dev->qdisc_sleeping) txq = &dev->tx_queue;
NLA_PUT_STRING(skb, IFLA_QDISC, dev->qdisc_sleeping->ops->id); if (txq->qdisc_sleeping)
NLA_PUT_STRING(skb, IFLA_QDISC, txq->qdisc_sleeping->ops->id);
if (1) { if (1) {
struct rtnl_link_ifmap map = { struct rtnl_link_ifmap map = {
......
...@@ -231,7 +231,8 @@ const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTER ...@@ -231,7 +231,8 @@ const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTER
/* Check if a valid qdisc is available */ /* Check if a valid qdisc is available */
static inline int addrconf_qdisc_ok(struct net_device *dev) static inline int addrconf_qdisc_ok(struct net_device *dev)
{ {
return (dev->qdisc != &noop_qdisc); struct netdev_queue *txq = &dev->tx_queue;
return (txq->qdisc != &noop_qdisc);
} }
/* Check if a route is valid prefix route */ /* Check if a route is valid prefix route */
......
...@@ -574,9 +574,10 @@ static struct Qdisc_ops wme_qdisc_ops __read_mostly = ...@@ -574,9 +574,10 @@ static struct Qdisc_ops wme_qdisc_ops __read_mostly =
void ieee80211_install_qdisc(struct net_device *dev) void ieee80211_install_qdisc(struct net_device *dev)
{ {
struct netdev_queue *txq = &dev->tx_queue;
struct Qdisc *qdisc; struct Qdisc *qdisc;
qdisc = qdisc_create_dflt(dev, &dev->tx_queue, qdisc = qdisc_create_dflt(dev, txq,
&wme_qdisc_ops, TC_H_ROOT); &wme_qdisc_ops, TC_H_ROOT);
if (!qdisc) { if (!qdisc) {
printk(KERN_ERR "%s: qdisc installation failed\n", dev->name); printk(KERN_ERR "%s: qdisc installation failed\n", dev->name);
...@@ -587,15 +588,17 @@ void ieee80211_install_qdisc(struct net_device *dev) ...@@ -587,15 +588,17 @@ void ieee80211_install_qdisc(struct net_device *dev)
qdisc->handle = 0x80010000; qdisc->handle = 0x80010000;
qdisc_lock_tree(dev); qdisc_lock_tree(dev);
list_add_tail(&qdisc->list, &dev->qdisc_list); list_add_tail(&qdisc->list, &txq->qdisc_list);
dev->qdisc_sleeping = qdisc; txq->qdisc_sleeping = qdisc;
qdisc_unlock_tree(dev); qdisc_unlock_tree(dev);
} }
int ieee80211_qdisc_installed(struct net_device *dev) int ieee80211_qdisc_installed(struct net_device *dev)
{ {
return dev->qdisc_sleeping->ops == &wme_qdisc_ops; struct netdev_queue *txq = &dev->tx_queue;
return txq->qdisc_sleeping->ops == &wme_qdisc_ops;
} }
...@@ -614,8 +617,9 @@ int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, ...@@ -614,8 +617,9 @@ int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
struct sta_info *sta, u16 tid) struct sta_info *sta, u16 tid)
{ {
int i; int i;
struct netdev_queue *txq = &local->mdev->tx_queue;
struct ieee80211_sched_data *q = struct ieee80211_sched_data *q =
qdisc_priv(local->mdev->qdisc_sleeping); qdisc_priv(txq->qdisc_sleeping);
DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac);
/* prepare the filter and save it for the SW queue /* prepare the filter and save it for the SW queue
...@@ -655,8 +659,9 @@ void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local, ...@@ -655,8 +659,9 @@ void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
u8 requeue) u8 requeue)
{ {
struct ieee80211_hw *hw = &local->hw; struct ieee80211_hw *hw = &local->hw;
struct netdev_queue *txq = &local->mdev->tx_queue;
struct ieee80211_sched_data *q = struct ieee80211_sched_data *q =
qdisc_priv(local->mdev->qdisc_sleeping); qdisc_priv(txq->qdisc_sleeping);
int agg_queue = sta->tid_to_tx_q[tid]; int agg_queue = sta->tid_to_tx_q[tid];
/* return the qdisc to the pool */ /* return the qdisc to the pool */
...@@ -671,7 +676,8 @@ void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local, ...@@ -671,7 +676,8 @@ void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
void ieee80211_requeue(struct ieee80211_local *local, int queue) void ieee80211_requeue(struct ieee80211_local *local, int queue)
{ {
struct Qdisc *root_qd = local->mdev->qdisc_sleeping; struct netdev_queue *txq = &local->mdev->tx_queue;
struct Qdisc *root_qd = txq->qdisc_sleeping;
struct ieee80211_sched_data *q = qdisc_priv(root_qd); struct ieee80211_sched_data *q = qdisc_priv(root_qd);
struct Qdisc *qdisc = q->queues[queue]; struct Qdisc *qdisc = q->queues[queue];
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
......
...@@ -166,7 +166,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -166,7 +166,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
/* Find qdisc */ /* Find qdisc */
if (!parent) { if (!parent) {
q = dev->qdisc_sleeping; struct netdev_queue *dev_queue = &dev->tx_queue;
q = dev_queue->qdisc_sleeping;
parent = q->handle; parent = q->handle;
} else { } else {
q = qdisc_lookup(dev, TC_H_MAJ(t->tcm_parent)); q = qdisc_lookup(dev, TC_H_MAJ(t->tcm_parent));
...@@ -390,6 +391,7 @@ static int tcf_node_dump(struct tcf_proto *tp, unsigned long n, ...@@ -390,6 +391,7 @@ static int tcf_node_dump(struct tcf_proto *tp, unsigned long n,
static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct netdev_queue *dev_queue;
int t; int t;
int s_t; int s_t;
struct net_device *dev; struct net_device *dev;
...@@ -408,8 +410,9 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -408,8 +410,9 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
return skb->len; return skb->len;
dev_queue = &dev->tx_queue;
if (!tcm->tcm_parent) if (!tcm->tcm_parent)
q = dev->qdisc_sleeping; q = dev_queue->qdisc_sleeping;
else else
q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent)); q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent));
if (!q) if (!q)
......
...@@ -185,9 +185,10 @@ EXPORT_SYMBOL(unregister_qdisc); ...@@ -185,9 +185,10 @@ EXPORT_SYMBOL(unregister_qdisc);
struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
{ {
struct netdev_queue *dev_queue = &dev->tx_queue;
struct Qdisc *q; struct Qdisc *q;
list_for_each_entry(q, &dev->qdisc_list, list) { list_for_each_entry(q, &dev_queue->qdisc_list, list) {
if (q->handle == handle) if (q->handle == handle)
return q; return q;
} }
...@@ -441,6 +442,7 @@ static u32 qdisc_alloc_handle(struct net_device *dev) ...@@ -441,6 +442,7 @@ static u32 qdisc_alloc_handle(struct net_device *dev)
static struct Qdisc * static struct Qdisc *
dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc) dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc)
{ {
struct netdev_queue *dev_queue;
struct Qdisc *oqdisc; struct Qdisc *oqdisc;
if (dev->flags & IFF_UP) if (dev->flags & IFF_UP)
...@@ -459,8 +461,8 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc) ...@@ -459,8 +461,8 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc)
} }
} else { } else {
dev_queue = &dev->tx_queue;
oqdisc = dev->qdisc_sleeping; oqdisc = dev_queue->qdisc_sleeping;
/* Prune old scheduler */ /* Prune old scheduler */
if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
...@@ -469,8 +471,8 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc) ...@@ -469,8 +471,8 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc)
/* ... and graft new one */ /* ... and graft new one */
if (qdisc == NULL) if (qdisc == NULL)
qdisc = &noop_qdisc; qdisc = &noop_qdisc;
dev->qdisc_sleeping = qdisc; dev_queue->qdisc_sleeping = qdisc;
dev->qdisc = &noop_qdisc; dev_queue->qdisc = &noop_qdisc;
} }
qdisc_unlock_tree(dev); qdisc_unlock_tree(dev);
...@@ -633,7 +635,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, ...@@ -633,7 +635,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
} }
} }
qdisc_lock_tree(dev); qdisc_lock_tree(dev);
list_add_tail(&sch->list, &dev->qdisc_list); list_add_tail(&sch->list, &dev_queue->qdisc_list);
qdisc_unlock_tree(dev); qdisc_unlock_tree(dev);
return sch; return sch;
...@@ -740,7 +742,8 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -740,7 +742,8 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
q = dev->qdisc_ingress; q = dev->qdisc_ingress;
} }
} else { } else {
q = dev->qdisc_sleeping; struct netdev_queue *dev_queue = &dev->tx_queue;
q = dev_queue->qdisc_sleeping;
} }
if (!q) if (!q)
return -ENOENT; return -ENOENT;
...@@ -814,7 +817,8 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -814,7 +817,8 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
q = dev->qdisc_ingress; q = dev->qdisc_ingress;
} }
} else { } else {
q = dev->qdisc_sleeping; struct netdev_queue *dev_queue = &dev->tx_queue;
q = dev_queue->qdisc_sleeping;
} }
/* It may be default qdisc, ignore it */ /* It may be default qdisc, ignore it */
...@@ -1015,12 +1019,14 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1015,12 +1019,14 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
read_lock(&dev_base_lock); read_lock(&dev_base_lock);
idx = 0; idx = 0;
for_each_netdev(&init_net, dev) { for_each_netdev(&init_net, dev) {
struct netdev_queue *dev_queue;
if (idx < s_idx) if (idx < s_idx)
goto cont; goto cont;
if (idx > s_idx) if (idx > s_idx)
s_q_idx = 0; s_q_idx = 0;
q_idx = 0; q_idx = 0;
list_for_each_entry(q, &dev->qdisc_list, list) { dev_queue = &dev->tx_queue;
list_for_each_entry(q, &dev_queue->qdisc_list, list) {
if (q_idx < s_q_idx) { if (q_idx < s_q_idx) {
q_idx++; q_idx++;
continue; continue;
...@@ -1054,6 +1060,7 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1054,6 +1060,7 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct netdev_queue *dev_queue;
struct tcmsg *tcm = NLMSG_DATA(n); struct tcmsg *tcm = NLMSG_DATA(n);
struct nlattr *tca[TCA_MAX + 1]; struct nlattr *tca[TCA_MAX + 1];
struct net_device *dev; struct net_device *dev;
...@@ -1091,6 +1098,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -1091,6 +1098,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
/* Step 1. Determine qdisc handle X:0 */ /* Step 1. Determine qdisc handle X:0 */
dev_queue = &dev->tx_queue;
if (pid != TC_H_ROOT) { if (pid != TC_H_ROOT) {
u32 qid1 = TC_H_MAJ(pid); u32 qid1 = TC_H_MAJ(pid);
...@@ -1101,7 +1109,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -1101,7 +1109,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
} else if (qid1) { } else if (qid1) {
qid = qid1; qid = qid1;
} else if (qid == 0) } else if (qid == 0)
qid = dev->qdisc_sleeping->handle; qid = dev_queue->qdisc_sleeping->handle;
/* Now qid is genuine qdisc handle consistent /* Now qid is genuine qdisc handle consistent
both with parent and child. both with parent and child.
...@@ -1112,7 +1120,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -1112,7 +1120,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
pid = TC_H_MAKE(qid, pid); pid = TC_H_MAKE(qid, pid);
} else { } else {
if (qid == 0) if (qid == 0)
qid = dev->qdisc_sleeping->handle; qid = dev_queue->qdisc_sleeping->handle;
} }
/* OK. Locate qdisc */ /* OK. Locate qdisc */
...@@ -1248,6 +1256,7 @@ static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walk ...@@ -1248,6 +1256,7 @@ static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walk
static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct netdev_queue *dev_queue;
int t; int t;
int s_t; int s_t;
struct net_device *dev; struct net_device *dev;
...@@ -1266,7 +1275,8 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1266,7 +1275,8 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
s_t = cb->args[0]; s_t = cb->args[0];
t = 0; t = 0;
list_for_each_entry(q, &dev->qdisc_list, list) { dev_queue = &dev->tx_queue;
list_for_each_entry(q, &dev_queue->qdisc_list, list) {
if (t < s_t || !q->ops->cl_ops || if (t < s_t || !q->ops->cl_ops ||
(tcm->tcm_parent && (tcm->tcm_parent &&
TC_H_MAJ(tcm->tcm_parent) != q->handle)) { TC_H_MAJ(tcm->tcm_parent) != q->handle)) {
......
...@@ -122,7 +122,7 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb, ...@@ -122,7 +122,7 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb,
* *
* __LINK_STATE_QDISC_RUNNING guarantees only one CPU can process this * __LINK_STATE_QDISC_RUNNING guarantees only one CPU can process this
* device at a time. queue->lock serializes queue accesses for * device at a time. queue->lock serializes queue accesses for
* this device AND dev->qdisc pointer itself. * this device AND txq->qdisc pointer itself.
* *
* netif_tx_lock serializes accesses to device driver. * netif_tx_lock serializes accesses to device driver.
* *
...@@ -138,7 +138,8 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb, ...@@ -138,7 +138,8 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb,
*/ */
static inline int qdisc_restart(struct net_device *dev) static inline int qdisc_restart(struct net_device *dev)
{ {
struct Qdisc *q = dev->qdisc; struct netdev_queue *txq = &dev->tx_queue;
struct Qdisc *q = txq->qdisc;
struct sk_buff *skb; struct sk_buff *skb;
int ret = NETDEV_TX_BUSY; int ret = NETDEV_TX_BUSY;
...@@ -148,15 +149,15 @@ static inline int qdisc_restart(struct net_device *dev) ...@@ -148,15 +149,15 @@ static inline int qdisc_restart(struct net_device *dev)
/* And release queue */ /* And release queue */
spin_unlock(&q->dev_queue->lock); spin_unlock(&txq->lock);
HARD_TX_LOCK(dev, smp_processor_id()); HARD_TX_LOCK(dev, smp_processor_id());
if (!netif_subqueue_stopped(dev, skb)) if (!netif_subqueue_stopped(dev, skb))
ret = dev_hard_start_xmit(skb, dev); ret = dev_hard_start_xmit(skb, dev);
HARD_TX_UNLOCK(dev); HARD_TX_UNLOCK(dev);
spin_lock(&q->dev_queue->lock); spin_lock(&txq->lock);
q = dev->qdisc; q = txq->qdisc;
switch (ret) { switch (ret) {
case NETDEV_TX_OK: case NETDEV_TX_OK:
...@@ -207,9 +208,10 @@ void __qdisc_run(struct net_device *dev) ...@@ -207,9 +208,10 @@ void __qdisc_run(struct net_device *dev)
static void dev_watchdog(unsigned long arg) static void dev_watchdog(unsigned long arg)
{ {
struct net_device *dev = (struct net_device *)arg; struct net_device *dev = (struct net_device *)arg;
struct netdev_queue *txq = &dev->tx_queue;
netif_tx_lock(dev); netif_tx_lock(dev);
if (dev->qdisc != &noop_qdisc) { if (txq->qdisc != &noop_qdisc) {
if (netif_device_present(dev) && if (netif_device_present(dev) &&
netif_running(dev) && netif_running(dev) &&
netif_carrier_ok(dev)) { netif_carrier_ok(dev)) {
...@@ -539,53 +541,63 @@ EXPORT_SYMBOL(qdisc_destroy); ...@@ -539,53 +541,63 @@ EXPORT_SYMBOL(qdisc_destroy);
void dev_activate(struct net_device *dev) void dev_activate(struct net_device *dev)
{ {
struct netdev_queue *txq = &dev->tx_queue;
/* No queueing discipline is attached to device; /* No queueing discipline is attached to device;
create default one i.e. pfifo_fast for devices, create default one i.e. pfifo_fast for devices,
which need queueing and noqueue_qdisc for which need queueing and noqueue_qdisc for
virtual interfaces virtual interfaces
*/ */
if (dev->qdisc_sleeping == &noop_qdisc) { if (txq->qdisc_sleeping == &noop_qdisc) {
struct Qdisc *qdisc; struct Qdisc *qdisc;
if (dev->tx_queue_len) { if (dev->tx_queue_len) {
qdisc = qdisc_create_dflt(dev, &dev->tx_queue, qdisc = qdisc_create_dflt(dev, txq,
&pfifo_fast_ops, &pfifo_fast_ops,
TC_H_ROOT); TC_H_ROOT);
if (qdisc == NULL) { if (qdisc == NULL) {
printk(KERN_INFO "%s: activation failed\n", dev->name); printk(KERN_INFO "%s: activation failed\n", dev->name);
return; return;
} }
list_add_tail(&qdisc->list, &dev->qdisc_list); list_add_tail(&qdisc->list, &txq->qdisc_list);
} else { } else {
qdisc = &noqueue_qdisc; qdisc = &noqueue_qdisc;
} }
dev->qdisc_sleeping = qdisc; txq->qdisc_sleeping = qdisc;
} }
if (!netif_carrier_ok(dev)) if (!netif_carrier_ok(dev))
/* Delay activation until next carrier-on event */ /* Delay activation until next carrier-on event */
return; return;
spin_lock_bh(&dev->tx_queue.lock); spin_lock_bh(&txq->lock);
rcu_assign_pointer(dev->qdisc, dev->qdisc_sleeping); rcu_assign_pointer(txq->qdisc, txq->qdisc_sleeping);
if (dev->qdisc != &noqueue_qdisc) { if (txq->qdisc != &noqueue_qdisc) {
dev->trans_start = jiffies; dev->trans_start = jiffies;
dev_watchdog_up(dev); dev_watchdog_up(dev);
} }
spin_unlock_bh(&dev->tx_queue.lock); spin_unlock_bh(&txq->lock);
}
static void dev_deactivate_queue(struct net_device *dev,
struct netdev_queue *dev_queue,
struct Qdisc *qdisc_default)
{
struct Qdisc *qdisc = dev_queue->qdisc;
if (qdisc) {
dev_queue->qdisc = qdisc_default;
qdisc_reset(qdisc);
}
} }
void dev_deactivate(struct net_device *dev) void dev_deactivate(struct net_device *dev)
{ {
struct Qdisc *qdisc;
struct sk_buff *skb; struct sk_buff *skb;
int running; int running;
spin_lock_bh(&dev->tx_queue.lock); spin_lock_bh(&dev->tx_queue.lock);
qdisc = dev->qdisc; dev_deactivate_queue(dev, &dev->tx_queue, &noop_qdisc);
dev->qdisc = &noop_qdisc;
qdisc_reset(qdisc);
skb = dev->gso_skb; skb = dev->gso_skb;
dev->gso_skb = NULL; dev->gso_skb = NULL;
...@@ -622,32 +634,44 @@ void dev_deactivate(struct net_device *dev) ...@@ -622,32 +634,44 @@ void dev_deactivate(struct net_device *dev)
} while (WARN_ON_ONCE(running)); } while (WARN_ON_ONCE(running));
} }
static void dev_init_scheduler_queue(struct net_device *dev,
struct netdev_queue *dev_queue,
struct Qdisc *qdisc)
{
dev_queue->qdisc = qdisc;
dev_queue->qdisc_sleeping = qdisc;
INIT_LIST_HEAD(&dev_queue->qdisc_list);
}
void dev_init_scheduler(struct net_device *dev) void dev_init_scheduler(struct net_device *dev)
{ {
qdisc_lock_tree(dev); qdisc_lock_tree(dev);
dev->qdisc = &noop_qdisc; dev_init_scheduler_queue(dev, &dev->tx_queue, &noop_qdisc);
dev->qdisc_sleeping = &noop_qdisc; dev_init_scheduler_queue(dev, &dev->rx_queue, NULL);
INIT_LIST_HEAD(&dev->qdisc_list);
qdisc_unlock_tree(dev); qdisc_unlock_tree(dev);
setup_timer(&dev->watchdog_timer, dev_watchdog, (unsigned long)dev); setup_timer(&dev->watchdog_timer, dev_watchdog, (unsigned long)dev);
} }
void dev_shutdown(struct net_device *dev) static void dev_shutdown_scheduler_queue(struct net_device *dev,
struct netdev_queue *dev_queue,
struct Qdisc *qdisc_default)
{ {
struct Qdisc *qdisc; struct Qdisc *qdisc = dev_queue->qdisc_sleeping;
if (qdisc) {
dev_queue->qdisc = qdisc_default;
dev_queue->qdisc_sleeping = qdisc_default;
qdisc_lock_tree(dev);
qdisc = dev->qdisc_sleeping;
dev->qdisc = &noop_qdisc;
dev->qdisc_sleeping = &noop_qdisc;
qdisc_destroy(qdisc);
#if defined(CONFIG_NET_SCH_INGRESS) || defined(CONFIG_NET_SCH_INGRESS_MODULE)
if ((qdisc = dev->qdisc_ingress) != NULL) {
dev->qdisc_ingress = NULL;
qdisc_destroy(qdisc); qdisc_destroy(qdisc);
} }
#endif }
void dev_shutdown(struct net_device *dev)
{
qdisc_lock_tree(dev);
dev_shutdown_scheduler_queue(dev, &dev->tx_queue, &noop_qdisc);
dev_shutdown_scheduler_queue(dev, &dev->rx_queue, NULL);
BUG_TRAP(!timer_pending(&dev->watchdog_timer)); BUG_TRAP(!timer_pending(&dev->watchdog_timer));
qdisc_unlock_tree(dev); qdisc_unlock_tree(dev);
} }
...@@ -180,7 +180,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) ...@@ -180,7 +180,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
* skb will be queued. * skb will be queued.
*/ */
if (count > 1 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) { if (count > 1 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
struct Qdisc *rootq = qdisc_dev(sch)->qdisc; struct Qdisc *rootq = qdisc_dev(sch)->tx_queue.qdisc;
u32 dupsave = q->duplicate; /* prevent duplicating a dup... */ u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
q->duplicate = 0; q->duplicate = 0;
......
...@@ -107,17 +107,19 @@ static struct sk_buff * ...@@ -107,17 +107,19 @@ static struct sk_buff *
teql_dequeue(struct Qdisc* sch) teql_dequeue(struct Qdisc* sch)
{ {
struct teql_sched_data *dat = qdisc_priv(sch); struct teql_sched_data *dat = qdisc_priv(sch);
struct netdev_queue *dat_queue;
struct sk_buff *skb; struct sk_buff *skb;
skb = __skb_dequeue(&dat->q); skb = __skb_dequeue(&dat->q);
dat_queue = &dat->m->dev->tx_queue;
if (skb == NULL) { if (skb == NULL) {
struct net_device *m = qdisc_dev(dat->m->dev->qdisc); struct net_device *m = qdisc_dev(dat_queue->qdisc);
if (m) { if (m) {
dat->m->slaves = sch; dat->m->slaves = sch;
netif_wake_queue(m); netif_wake_queue(m);
} }
} }
sch->q.qlen = dat->q.qlen + dat->m->dev->qdisc->q.qlen; sch->q.qlen = dat->q.qlen + dat_queue->qdisc->q.qlen;
return skb; return skb;
} }
...@@ -155,7 +157,7 @@ teql_destroy(struct Qdisc* sch) ...@@ -155,7 +157,7 @@ teql_destroy(struct Qdisc* sch)
if (q == master->slaves) { if (q == master->slaves) {
master->slaves = NULL; master->slaves = NULL;
spin_lock_bh(&master->dev->tx_queue.lock); spin_lock_bh(&master->dev->tx_queue.lock);
qdisc_reset(master->dev->qdisc); qdisc_reset(master->dev->tx_queue.qdisc);
spin_unlock_bh(&master->dev->tx_queue.lock); spin_unlock_bh(&master->dev->tx_queue.lock);
} }
} }
...@@ -216,7 +218,7 @@ static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt) ...@@ -216,7 +218,7 @@ static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt)
static int static int
__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev) __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev)
{ {
struct teql_sched_data *q = qdisc_priv(dev->qdisc); struct teql_sched_data *q = qdisc_priv(dev->tx_queue.qdisc);
struct neighbour *mn = skb->dst->neighbour; struct neighbour *mn = skb->dst->neighbour;
struct neighbour *n = q->ncache; struct neighbour *n = q->ncache;
...@@ -252,7 +254,7 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device * ...@@ -252,7 +254,7 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *
static inline int teql_resolve(struct sk_buff *skb, static inline int teql_resolve(struct sk_buff *skb,
struct sk_buff *skb_res, struct net_device *dev) struct sk_buff *skb_res, struct net_device *dev)
{ {
if (dev->qdisc == &noop_qdisc) if (dev->tx_queue.qdisc == &noop_qdisc)
return -ENODEV; return -ENODEV;
if (dev->header_ops == NULL || if (dev->header_ops == NULL ||
...@@ -284,7 +286,7 @@ static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -284,7 +286,7 @@ static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev)
do { do {
struct net_device *slave = qdisc_dev(q); struct net_device *slave = qdisc_dev(q);
if (slave->qdisc_sleeping != q) if (slave->tx_queue.qdisc_sleeping != q)
continue; continue;
if (netif_queue_stopped(slave) || if (netif_queue_stopped(slave) ||
__netif_subqueue_stopped(slave, subq) || __netif_subqueue_stopped(slave, subq) ||
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment