Commit 569943d0 authored by David S. Miller's avatar David S. Miller

Merge branch 'mv643xx'

Sebastian Hesselbarth says:

====================
This patch set comprises some one-liners to fix issues with repeated
loading and unloading of a modular mv643xx_eth driver.

First two patches take care of the periodic port statistic timer, that
updates statistics by reading port registers using add_timer/mod_timer.

Patch 1 moves timer re-schedule from mib_counters_update to the timer
callback. As mib_counters_update is also called from non-timer context,
this ensures the timer is reactivated from timer context only.

Patch 2 moves initial timer schedule from _probe() time to right before
the port is actually started as the corresponding del_timer_sync is at
_stop() time. This fixes a regression, where unloading the driver from a
non-started eth device can cause the timer to access deallocated mem.

Patch 3 adds an assignment of the ports device_node to the corresponding
self-created platform_device. This is required to allow fixups based on
the device_node's compatible string later. Actually, it is also a potential
regression because we already check compatible string for Kirkwood, but
does not (yet) rely on the fixup.

All patches are based on v3.12-rc3 and have been tested on Kirkwood-based
Seagate Dockstar.

Patches 1 and 2 can also possibly queued up for -stable.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e18503f4 b5d82db8
...@@ -1131,15 +1131,13 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) ...@@ -1131,15 +1131,13 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
p->rx_discard += rdlp(mp, RX_DISCARD_FRAME_CNT); p->rx_discard += rdlp(mp, RX_DISCARD_FRAME_CNT);
p->rx_overrun += rdlp(mp, RX_OVERRUN_FRAME_CNT); p->rx_overrun += rdlp(mp, RX_OVERRUN_FRAME_CNT);
spin_unlock_bh(&mp->mib_counters_lock); spin_unlock_bh(&mp->mib_counters_lock);
mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
} }
static void mib_counters_timer_wrapper(unsigned long _mp) static void mib_counters_timer_wrapper(unsigned long _mp)
{ {
struct mv643xx_eth_private *mp = (void *)_mp; struct mv643xx_eth_private *mp = (void *)_mp;
mib_counters_update(mp); mib_counters_update(mp);
mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
} }
...@@ -2237,6 +2235,7 @@ static int mv643xx_eth_open(struct net_device *dev) ...@@ -2237,6 +2235,7 @@ static int mv643xx_eth_open(struct net_device *dev)
mp->int_mask |= INT_TX_END_0 << i; mp->int_mask |= INT_TX_END_0 << i;
} }
add_timer(&mp->mib_counters_timer);
port_start(mp); port_start(mp);
wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX);
...@@ -2534,6 +2533,7 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev, ...@@ -2534,6 +2533,7 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,
if (!ppdev) if (!ppdev)
return -ENOMEM; return -ENOMEM;
ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
ppdev->dev.of_node = pnp;
ret = platform_device_add_resources(ppdev, &res, 1); ret = platform_device_add_resources(ppdev, &res, 1);
if (ret) if (ret)
...@@ -2916,7 +2916,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) ...@@ -2916,7 +2916,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
mp->mib_counters_timer.data = (unsigned long)mp; mp->mib_counters_timer.data = (unsigned long)mp;
mp->mib_counters_timer.function = mib_counters_timer_wrapper; mp->mib_counters_timer.function = mib_counters_timer_wrapper;
mp->mib_counters_timer.expires = jiffies + 30 * HZ; mp->mib_counters_timer.expires = jiffies + 30 * HZ;
add_timer(&mp->mib_counters_timer);
spin_lock_init(&mp->mib_counters_lock); spin_lock_init(&mp->mib_counters_lock);
......
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