generic: ar8216: add detach callback
authorGabor Juhos <juhosg@openwrt.org>
Thu, 7 Feb 2013 15:18:32 +0000 (15:18 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Thu, 7 Feb 2013 15:18:32 +0000 (15:18 +0000)
The current code uses the 'remove' callback to disable
packet mangle on the underlying ethernet device.
However the attached_dev is always NULL when the
'remove' callback is called by phylib, and this causes
NULL pointer dereference, like this:

  [  475.300000] CPU 0 Unable to handle kernel paging request at virtual address 000000f0, epc == 801cdcf0, ra == 801c7eac
  [  475.310000] Oops[#1]:
  [  475.310000] Cpu 0
  [  475.310000] $ 0   : 00000000 00000000 00000000 00000001
  [  475.310000] $ 4   : 828dde00 00000005 828dde08 ffffffff
  [  475.310000] $ 8   : 00380081 00380081 82902a40 00000001
  [  475.310000] $12   : 00000037 00370081 00000001 00000000
  [  475.310000] $16   : 82865000 828dde08 828dde00 00000001
  [  475.310000] $20   : 00000080 00460000 00000002 77151448
  [  475.310000] $24   : 00000000 801abfd4
  [  475.310000] $28   : 82cc2000 82cc3d58 0053c3c4 801c7eac
  [  475.310000] Hi    : 00000007
  [  475.310000] Lo    : 00000004
  [  475.310000] epc   : 801cdcf0 ar8216_remove+0x1c/0x94
  [  475.310000]     Tainted: G           O
  [  475.310000] ra    : 801c7eac phy_remove+0x4c/0x6c
  [  475.310000] Status: 1000cc03    KERNEL EXL IE
  [  475.310000] Cause : 00800008
  [  475.310000] BadVA : 000000f0
  [  475.310000] PrId  : 00019750 (MIPS 74Kc)
  [  475.310000] Modules linked in: ath79_wdt ledtrig_usbdev ledtrig_netdev ag71xx(-) nf_nat_irc nf_nat_ftp nf_conntrack_irc nf_conntrack_ft
  p ipt_MASQUERADE iptable_nat xt_nat nf_nat_ipv4 nf_nat pppoext_conntrack xt_CT iptable_raw xt_state nf_conntrack_ipv4 nf_defrag_ipv4 nf_co
  nntrack ehci_hcd pppox ipt_REJECT xt_TCPMSS xt_LOG xt_comment xt_multiport xt_mac xt_limit iptable_mangle iptable_filter ip_tables xt_tcpu
  dp x_tables ppp_async ppp_generic slhc ath9k(O) ath9k_common(O) ath9k_hw(O) ath(O) mac80211(O) usbcore usb_common nls_base crc_ccitt cfg80
  211(O) compat(O) arc4 crypto_blkcipher aead ledtrig_timer ledtrig_default_on leds_gpio gpio_button_hotplug(O)
  [  475.310000] Process rmmod (pid: 1160, threadinfo=82cc2000, task=83969920, tls=7747c440)
  [  475.310000] Stack : 828dde08 802f5004 802f4680 00000001 828ddf70 801c7eac 802f4680 801ad6d8
          82902940 00000000 828dde08 802f5004 802f4680 801ad770 00000002 80269d94
          00000000 00000001 00000080 828dde08 828dde3c 801ad7fc 82902940 00000000
          83859100 00000000 8384dd2c 8384dd2c 828dde08 801ad230 82902800 00000000
          00000000 001a0041 828dde08 828dde08 802e80e8 801aac44 00000080 00460000
          ...
  [  475.310000] Call Trace:
  [  475.310000] [<801cdcf0>] ar8216_remove+0x1c/0x94
  [  475.310000] [<801c7eac>] phy_remove+0x4c/0x6c
  [  475.310000] [<801ad770>] __device_release_driver+0x6c/0xd0
  [  475.310000] [<801ad7fc>] device_release_driver+0x28/0x40
  [  475.310000] [<801ad230>] bus_remove_device+0xd8/0x10c
  [  475.310000] [<801aac44>] device_del+0x110/0x170
  [  475.310000] [<801aacb8>] device_unregister+0x14/0x28
  [  475.310000] [<801c92b0>] mdiobus_unregister+0x4c/0x70
  [  475.310000] [<82913060>] ag71xx_remove_ar8216_header+0xdc/0x5a8 [ag71xx]
  [  475.310000]
  [  475.310000]
  Code: 1200001c  8c82017c  ac800128 <8c4500f03c03ffdf  3463ffff 00a31824  ac4300f0  ac4000e0

Add a detach callback and disable packet mangling in
that to fix the problem.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
SVN-Revision: 35511

target/linux/generic/files/drivers/net/phy/ar8216.c

index cf28af0c766f595eccf8bb9b8fa3f40f09255cd1..a27d6501868c2f4ccb3a2fb316de01fb50a94e37 100644 (file)
@@ -1976,19 +1976,28 @@ ar8216_probe(struct phy_device *pdev)
 }
 
 static void
-ar8216_remove(struct phy_device *pdev)
+ar8216_detach(struct phy_device *pdev)
 {
-       struct ar8216_priv *priv = pdev->priv;
        struct net_device *dev = pdev->attached_dev;
 
-       if (!priv)
+       if (!dev)
                return;
 
-       pdev->priv = NULL;
-
+       dev->phy_ptr = NULL;
        dev->priv_flags &= ~IFF_NO_IP_ALIGN;
        dev->eth_mangle_rx = NULL;
        dev->eth_mangle_tx = NULL;
+}
+
+static void
+ar8216_remove(struct phy_device *pdev)
+{
+       struct ar8216_priv *priv = pdev->priv;
+
+       if (!priv)
+               return;
+
+       pdev->priv = NULL;
 
        if (pdev->addr == 0)
                unregister_switch(&priv->dev);
@@ -2004,6 +2013,7 @@ static struct phy_driver ar8216_driver = {
        .features       = PHY_BASIC_FEATURES,
        .probe          = ar8216_probe,
        .remove         = ar8216_remove,
+       .detach         = ar8216_detach,
        .config_init    = &ar8216_config_init,
        .config_aneg    = &ar8216_config_aneg,
        .read_status    = &ar8216_read_status,