summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuo-Fu Tseng <cooldavid@cooldavid.org>2010-03-17 00:09:30 +0000
committerGreg Kroah-Hartman <gregkh@suse.de>2010-04-01 16:01:44 -0700
commit8063440b1299495d330b74d6f88fa6896a8c7eff (patch)
tree9d35861c90e9c8ff6ad8b6d8b4bc885ff0eae1cb
parent53238f89fcbe3626d2520ae1580c5997793827f1 (diff)
jme: Protect vlgrp structure by pause RX actions.
commit bf5e5360fd1df1ae429ebbd81838d7d0879797d1 upstream. Temporary stop the RX IRQ, and disable (sync) tasklet or napi. And restore it after finished the vlgrp pointer assignment. Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/net/jme.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 3da390acef8d..981c9fb58673 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -2087,12 +2087,45 @@ jme_tx_timeout(struct net_device *netdev)
jme_reset_link(jme);
}
+static inline void jme_pause_rx(struct jme_adapter *jme)
+{
+ atomic_dec(&jme->link_changing);
+
+ jme_set_rx_pcc(jme, PCC_OFF);
+ if (test_bit(JME_FLAG_POLL, &jme->flags)) {
+ JME_NAPI_DISABLE(jme);
+ } else {
+ tasklet_disable(&jme->rxclean_task);
+ tasklet_disable(&jme->rxempty_task);
+ }
+}
+
+static inline void jme_resume_rx(struct jme_adapter *jme)
+{
+ struct dynpcc_info *dpi = &(jme->dpi);
+
+ if (test_bit(JME_FLAG_POLL, &jme->flags)) {
+ JME_NAPI_ENABLE(jme);
+ } else {
+ tasklet_hi_enable(&jme->rxclean_task);
+ tasklet_hi_enable(&jme->rxempty_task);
+ }
+ dpi->cur = PCC_P1;
+ dpi->attempt = PCC_P1;
+ dpi->cnt = 0;
+ jme_set_rx_pcc(jme, PCC_P1);
+
+ atomic_inc(&jme->link_changing);
+}
+
static void
jme_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
{
struct jme_adapter *jme = netdev_priv(netdev);
+ jme_pause_rx(jme);
jme->vlgrp = grp;
+ jme_resume_rx(jme);
}
static void