Changeset 38306


Ignore:
Timestamp:
2013-10-06T20:31:32+02:00 (4 years ago)
Author:
hauke
Message:

brcm47xx: b44: fix some problems with the phy

  • do not try initialize a unused phy
  • some improvements to the phylib patch
  • do not turn the phy off when mac is off

Signed-off-by: Hauke Mehrtens <hauke@…>

Location:
trunk/target/linux/brcm47xx/patches-3.10
Files:
4 added
1 deleted
1 edited
2 moved

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/brcm47xx/patches-3.10/200-b44-add-support-for-Byte-Queue-Limits.patch

    r38305 r38306  
    1 From: Hauke Mehrtens <hauke@hauke-m.de> 
    2 b44: add support for Byte Queue Limits 
    3  
    41--- a/drivers/net/ethernet/broadcom/b44.c 
    52+++ b/drivers/net/ethernet/broadcom/b44.c 
    6 @@ -622,6 +622,7 @@ static void b44_timer(unsigned long __op 
     3@@ -596,6 +596,7 @@ static void b44_timer(unsigned long __op 
    74 static void b44_tx(struct b44 *bp) 
    85 { 
     
    129        cur  = br32(bp, B44_DMATX_STAT) & DMATX_STAT_CDMASK; 
    1310        cur /= sizeof(struct dma_desc); 
    14 @@ -638,9 +639,14 @@ static void b44_tx(struct b44 *bp) 
     11@@ -612,9 +613,14 @@ static void b44_tx(struct b44 *bp) 
    1512                                 skb->len, 
    1613                                 DMA_TO_DEVICE); 
     
    2724        if (netif_queue_stopped(bp->dev) && 
    2825            TX_BUFFS_AVAIL(bp) > B44_TX_WAKEUP_THRESH) 
    29 @@ -1044,6 +1050,8 @@ static netdev_tx_t b44_start_xmit(struct 
     26@@ -1018,6 +1024,8 @@ static netdev_tx_t b44_start_xmit(struct 
    3027        if (bp->flags & B44_FLAG_REORDER_BUG) 
    3128                br32(bp, B44_DMATX_PTR); 
     
    3633                netif_stop_queue(dev); 
    3734  
    38 @@ -1442,6 +1450,8 @@ static void b44_init_hw(struct b44 *bp, 
     35@@ -1416,6 +1424,8 @@ static void b44_init_hw(struct b44 *bp, 
    3936  
    4037        val = br32(bp, B44_ENET_CTRL); 
    4138        bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE)); 
    42 +        
     39+ 
    4340+       netdev_reset_queue(bp->dev); 
    4441 } 
  • trunk/target/linux/brcm47xx/patches-3.10/205-b44-add-phylib-support.patch

    r38305 r38306  
     1From 46e5460f446109565b3f4a0cb728171d74bce33b Mon Sep 17 00:00:00 2001 
     2From: Hauke Mehrtens <hauke@hauke-m.de> 
     3Date: Thu, 3 Oct 2013 22:07:11 +0200 
     4Subject: [PATCH 5/6] b44: add phylib support 
     5 
     6Most of the older home routers based on the Broadcom BCM47XX SoC series 
     7are using a MAC that is supported by b44. On most of these routers not 
     8the internal PHY of this MAC core is used, but a switch sometimes on an 
     9external chip or integrated into the same SoC as the Ethernet core. 
     10For this switch a special PHY driver is needed which should not be 
     11integrated into b44 as the same switches are also used by other 
     12Broadcom home networking SoCs which are using different Ethernet MAC 
     13drivers. This was tested with the b53 switch driver which is currently 
     14on its way to mainline. 
     15 
     16With this patch we scan the mdio bus when the sprom or nvram says that 
     17the PHY address is 30, if a PHY was found at this address b44 uses it. 
     18 
     19This was tested with a BCM4704, BCM4712 and BCM5354. 
     20 
     21Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> 
     22--- 
     23 drivers/net/ethernet/broadcom/Kconfig |    1 + 
     24 drivers/net/ethernet/broadcom/b44.c   |  183 ++++++++++++++++++++++++++++++++- 
     25 drivers/net/ethernet/broadcom/b44.h   |    5 + 
     26 3 files changed, 186 insertions(+), 3 deletions(-) 
     27 
    128--- a/drivers/net/ethernet/broadcom/Kconfig 
    229+++ b/drivers/net/ethernet/broadcom/Kconfig 
     
    1138--- a/drivers/net/ethernet/broadcom/b44.c 
    1239+++ b/drivers/net/ethernet/broadcom/b44.c 
    13 @@ -29,6 +29,7 @@ 
     40@@ -6,6 +6,7 @@ 
     41  * Copyright (C) 2006 Felix Fietkau (nbd@openwrt.org) 
     42  * Copyright (C) 2006 Broadcom Corporation. 
     43  * Copyright (C) 2007 Michael Buesch <m@bues.ch> 
     44+ * Copyright (C) 2013 Hauke Mehrtens <hauke@hauke-m.de> 
     45  * 
     46  * Distribute under GPL. 
     47  */ 
     48@@ -29,6 +30,7 @@ 
    1449 #include <linux/dma-mapping.h> 
    1550 #include <linux/ssb/ssb.h> 
     
    1954 #include <asm/uaccess.h> 
    2055 #include <asm/io.h> 
    21 @@ -300,21 +301,23 @@ static inline int b44_writephy(struct b4 
     56@@ -316,6 +318,23 @@ static void b44_mdio_write_mii(struct ne 
     57        __b44_writephy(bp, phy_id, location, val); 
    2258 } 
    2359  
    24  /* miilib interface */ 
    25 -static int b44_mii_read(struct net_device *dev, int phy_id, int location) 
    26 +static int b44_mii_read(struct mii_bus *bus, int phy_id, int location) 
     60+static int b44_mdio_read_phylib(struct mii_bus *bus, int phy_id, int location) 
     61+{ 
     62+       u32 val; 
     63+       struct b44 *bp = bus->priv; 
     64+       int rc = __b44_readphy(bp, phy_id, location, &val); 
     65+       if (rc) 
     66+               return 0xffffffff; 
     67+       return val; 
     68+} 
     69+ 
     70+static int b44_mdio_write_phylib(struct mii_bus *bus, int phy_id, int location, 
     71+                                u16 val) 
     72+{ 
     73+       struct b44 *bp = bus->priv; 
     74+       return __b44_writephy(bp, phy_id, location, val); 
     75+} 
     76+ 
     77 static int b44_phy_reset(struct b44 *bp) 
    2778 { 
    2879        u32 val; 
    29 -       struct b44 *bp = netdev_priv(dev); 
    30 +       struct b44 *bp = bus->priv; 
    31         int rc = __b44_readphy(bp, phy_id, location, &val); 
    32         if (rc) 
    33                 return 0xffffffff; 
    34         return val; 
    35  } 
    36   
    37 -static void b44_mii_write(struct net_device *dev, int phy_id, int location, 
    38 -                        int val) 
    39 +static int b44_mii_write(struct mii_bus *bus, int phy_id, int location, 
    40 +                        u16 val) 
    41  { 
    42 -       struct b44 *bp = netdev_priv(dev); 
    43 +       struct b44 *bp = bus->priv; 
    44         __b44_writephy(bp, phy_id, location, val); 
    45 + 
    46 +       return 0; 
    47  } 
    48   
    49  static int b44_phy_reset(struct b44 *bp) 
    50 @@ -1831,102 +1834,24 @@ static int b44_get_settings(struct net_d 
     80@@ -1805,6 +1824,11 @@ static int b44_get_settings(struct net_d 
    5181 { 
    5282        struct b44 *bp = netdev_priv(dev); 
    5383  
    54 -       cmd->supported = (SUPPORTED_Autoneg); 
    55 -       cmd->supported |= (SUPPORTED_100baseT_Half | 
    56 -                         SUPPORTED_100baseT_Full | 
    57 -                         SUPPORTED_10baseT_Half | 
    58 -                         SUPPORTED_10baseT_Full | 
    59 -                         SUPPORTED_MII); 
    60 - 
    61 -       cmd->advertising = 0; 
    62 -       if (bp->flags & B44_FLAG_ADV_10HALF) 
    63 -               cmd->advertising |= ADVERTISED_10baseT_Half; 
    64 -       if (bp->flags & B44_FLAG_ADV_10FULL) 
    65 -               cmd->advertising |= ADVERTISED_10baseT_Full; 
    66 -       if (bp->flags & B44_FLAG_ADV_100HALF) 
    67 -               cmd->advertising |= ADVERTISED_100baseT_Half; 
    68 -       if (bp->flags & B44_FLAG_ADV_100FULL) 
    69 -               cmd->advertising |= ADVERTISED_100baseT_Full; 
    70 -       cmd->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause; 
    71 -       ethtool_cmd_speed_set(cmd, ((bp->flags & B44_FLAG_100_BASE_T) ? 
    72 -                                   SPEED_100 : SPEED_10)); 
    73 -       cmd->duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ? 
    74 -               DUPLEX_FULL : DUPLEX_HALF; 
    75 -       cmd->port = 0; 
    76 -       cmd->phy_address = bp->phy_addr; 
    77 -       cmd->transceiver = (bp->flags & B44_FLAG_INTERNAL_PHY) ? 
    78 -               XCVR_INTERNAL : XCVR_EXTERNAL; 
    79 -       cmd->autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ? 
    80 -               AUTONEG_DISABLE : AUTONEG_ENABLE; 
    81 -       if (cmd->autoneg == AUTONEG_ENABLE) 
    82 -               cmd->advertising |= ADVERTISED_Autoneg; 
    83 -       if (!netif_running(dev)){ 
    84 -               ethtool_cmd_speed_set(cmd, 0); 
    85 -               cmd->duplex = 0xff; 
    86 -       } 
    87 -       cmd->maxtxpkt = 0; 
    88 -       cmd->maxrxpkt = 0; 
    89 -       return 0; 
    90 +       return phy_ethtool_gset(bp->phydev, cmd); 
    91  } 
    92   
     84+       if (bp->has_phy) { 
     85+               BUG_ON(!bp->phydev); 
     86+               return phy_ethtool_gset(bp->phydev, cmd); 
     87+       } 
     88+ 
     89        cmd->supported = (SUPPORTED_Autoneg); 
     90        cmd->supported |= (SUPPORTED_100baseT_Half | 
     91                          SUPPORTED_100baseT_Full | 
     92@@ -1846,7 +1870,23 @@ static int b44_get_settings(struct net_d 
    9393 static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 
    9494 { 
    9595        struct b44 *bp = netdev_priv(dev); 
    9696-       u32 speed = ethtool_cmd_speed(cmd); 
    97 - 
    98 -       /* We do not support gigabit. */ 
    99 -       if (cmd->autoneg == AUTONEG_ENABLE) { 
    100 -               if (cmd->advertising & 
    101 -                   (ADVERTISED_1000baseT_Half | 
    102 -                    ADVERTISED_1000baseT_Full)) 
    103 -                       return -EINVAL; 
    104 -       } else if ((speed != SPEED_100 && 
    105 -                   speed != SPEED_10) || 
    106 -                  (cmd->duplex != DUPLEX_HALF && 
    107 -                   cmd->duplex != DUPLEX_FULL)) { 
    108 -                       return -EINVAL; 
    109 -       } 
     97+       u32 speed; 
    11098+       int ret; 
    111   
    112         spin_lock_irq(&bp->lock); 
    113   
    114 -       if (cmd->autoneg == AUTONEG_ENABLE) { 
    115 -               bp->flags &= ~(B44_FLAG_FORCE_LINK | 
    116 -                              B44_FLAG_100_BASE_T | 
    117 -                              B44_FLAG_FULL_DUPLEX | 
    118 -                              B44_FLAG_ADV_10HALF | 
    119 -                              B44_FLAG_ADV_10FULL | 
    120 -                              B44_FLAG_ADV_100HALF | 
    121 -                              B44_FLAG_ADV_100FULL); 
    122 -               if (cmd->advertising == 0) { 
    123 -                       bp->flags |= (B44_FLAG_ADV_10HALF | 
    124 -                                     B44_FLAG_ADV_10FULL | 
    125 -                                     B44_FLAG_ADV_100HALF | 
    126 -                                     B44_FLAG_ADV_100FULL); 
    127 -               } else { 
    128 -                       if (cmd->advertising & ADVERTISED_10baseT_Half) 
    129 -                               bp->flags |= B44_FLAG_ADV_10HALF; 
    130 -                       if (cmd->advertising & ADVERTISED_10baseT_Full) 
    131 -                               bp->flags |= B44_FLAG_ADV_10FULL; 
    132 -                       if (cmd->advertising & ADVERTISED_100baseT_Half) 
    133 -                               bp->flags |= B44_FLAG_ADV_100HALF; 
    134 -                       if (cmd->advertising & ADVERTISED_100baseT_Full) 
    135 -                               bp->flags |= B44_FLAG_ADV_100FULL; 
    136 -               } 
    137 -       } else { 
    138 -               bp->flags |= B44_FLAG_FORCE_LINK; 
    139 -               bp->flags &= ~(B44_FLAG_100_BASE_T | B44_FLAG_FULL_DUPLEX); 
    140 -               if (speed == SPEED_100) 
    141 -                       bp->flags |= B44_FLAG_100_BASE_T; 
    142 -               if (cmd->duplex == DUPLEX_FULL) 
    143 -                       bp->flags |= B44_FLAG_FULL_DUPLEX; 
    144 -       } 
    145 - 
    146         if (netif_running(dev)) 
    147                 b44_setup_phy(bp); 
    148   
    149 +       ret = phy_ethtool_sset(bp->phydev, cmd); 
    150 + 
    151         spin_unlock_irq(&bp->lock); 
    152   
    153 -       return 0; 
    154 +       return ret; 
    155  } 
    156   
    157  static void b44_get_ringparam(struct net_device *dev, 
    158 @@ -2102,20 +2027,74 @@ static const struct ethtool_ops b44_etht 
     99+ 
     100+       if (bp->has_phy) { 
     101+               BUG_ON(!bp->phydev); 
     102+               spin_lock_irq(&bp->lock); 
     103+               if (netif_running(dev)) 
     104+                       b44_setup_phy(bp); 
     105+ 
     106+               ret = phy_ethtool_sset(bp->phydev, cmd); 
     107+ 
     108+               spin_unlock_irq(&bp->lock); 
     109+ 
     110+               return ret; 
     111+       } 
     112+ 
     113+       speed = ethtool_cmd_speed(cmd); 
     114  
     115        /* We do not support gigabit. */ 
     116        if (cmd->autoneg == AUTONEG_ENABLE) { 
     117@@ -2076,7 +2116,6 @@ static const struct ethtool_ops b44_etht 
    159118  
    160119 static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 
     
    164123        int err = -EINVAL; 
    165124  
    166         if (!netif_running(dev)) 
     125@@ -2084,7 +2123,12 @@ static int b44_ioctl(struct net_device * 
    167126                goto out; 
    168127  
    169 +       if (!bp->phydev) 
    170 +               return -EINVAL; 
    171 + 
    172128        spin_lock_irq(&bp->lock); 
    173129-       err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL); 
    174 +       err = phy_mii_ioctl(bp->phydev, ifr, cmd); 
     130+       if (bp->has_phy) { 
     131+               BUG_ON(bp->phydev); 
     132+               err = phy_mii_ioctl(bp->phydev, ifr, cmd); 
     133+       } else { 
     134+               err = generic_mii_ioctl(&bp->mii_if, if_mii(ifr), cmd, NULL); 
     135+       } 
    175136        spin_unlock_irq(&bp->lock); 
    176137 out: 
    177138        return err; 
    178  } 
     139@@ -2146,6 +2190,124 @@ static const struct net_device_ops b44_n 
     140 #endif 
     141 }; 
    179142  
    180143+static void b44_adjust_link(struct net_device *dev) 
     
    201164+} 
    202165+ 
    203 +static int b44_mii_probe(struct net_device *dev) 
    204 +{ 
    205 +       struct b44 *bp = netdev_priv(dev); 
    206 +       struct phy_device *phydev = NULL; 
    207 +       char phy_id[MII_BUS_ID_SIZE + 3]; 
    208 + 
    209 +       /* connect to PHY */ 
    210 +       snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, 
    211 +                bp->mii_bus->id, bp->phy_addr); 
    212 + 
    213 +       phydev = phy_connect(dev, phy_id, &b44_adjust_link, 
    214 +                            PHY_INTERFACE_MODE_MII); 
    215 +       if (IS_ERR(phydev)) { 
    216 +               netdev_err(dev, "could not attach PHY: %s\n", phy_id); 
    217 +               bp->phy_addr = B44_PHY_ADDR_NO_PHY; 
    218 +               return PTR_ERR(phydev); 
    219 +       } 
     166+static int b44_register_phy_one(struct b44 *bp) 
     167+{ 
     168+       struct mii_bus *mii_bus; 
     169+       struct ssb_device *sdev = bp->sdev; 
     170+       struct phy_device *phydev; 
     171+       int err; 
     172+ 
     173+       mii_bus = mdiobus_alloc(); 
     174+       if (!mii_bus) { 
     175+               dev_err(sdev->dev, "mdiobus_alloc() failed\n"); 
     176+               err = -ENOMEM; 
     177+               goto err_out; 
     178+       } 
     179+ 
     180+       mii_bus->priv = bp; 
     181+       mii_bus->read = b44_mdio_read_phylib; 
     182+       mii_bus->write = b44_mdio_write_phylib; 
     183+       mii_bus->name = "b44_eth_mii"; 
     184+       mii_bus->parent = sdev->dev; 
     185+       mii_bus->phy_mask = ~(1 << bp->phy_addr); 
     186+       snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%x", instance); 
     187+       mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); 
     188+       if (!mii_bus->irq) { 
     189+               dev_err(sdev->dev, "mii_bus irq allocation failed\n"); 
     190+               err = -ENOMEM; 
     191+               goto err_out_mdiobus; 
     192+       } 
     193+ 
     194+       memset(mii_bus->irq, PHY_POLL, sizeof(int) * PHY_MAX_ADDR); 
     195+ 
     196+       bp->mii_bus = mii_bus; 
     197+ 
     198+       err = mdiobus_register(mii_bus); 
     199+       if (err) { 
     200+               dev_err(sdev->dev, "failed to register MII bus\n"); 
     201+               goto err_out_mdiobus_irq; 
     202+       } 
     203+ 
     204+       phydev = bp->mii_bus->phy_map[bp->phy_addr]; 
     205+       if (!phydev) { 
     206+               dev_err(sdev->dev, "could not find PHY at %i\n", bp->phy_addr); 
     207+               err = -ENODEV; 
     208+               goto err_out_mdiobus_unregister; 
     209+       } 
     210+ 
     211+       err = phy_connect_direct(bp->dev, phydev, &b44_adjust_link, 
     212+                                PHY_INTERFACE_MODE_MII); 
     213+       if (err < 0) { 
     214+               dev_err(sdev->dev, "could not attach PHY at %i\n", 
     215+                       bp->phy_addr); 
     216+               goto err_out_mdiobus_unregister; 
     217+       } 
     218+ 
     219+       /* mask with MAC supported features */ 
     220+       phydev->supported &= (SUPPORTED_10baseT_Half | 
     221+                             SUPPORTED_10baseT_Full | 
     222+                             SUPPORTED_100baseT_Half | 
     223+                             SUPPORTED_100baseT_Full | 
     224+                             SUPPORTED_Autoneg | 
     225+                             SUPPORTED_MII); 
     226+       phydev->advertising = phydev->supported; 
    220227+ 
    221228+       bp->phydev = phydev; 
     
    224231+       bp->phy_addr = phydev->addr; 
    225232+ 
    226 +       netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n", 
    227 +                   phydev->drv->name, dev_name(&phydev->dev)); 
     233+       dev_info(sdev->dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n", 
     234+                phydev->drv->name, dev_name(&phydev->dev)); 
    228235+ 
    229236+       return 0; 
    230 +} 
    231 + 
    232  static int b44_get_invariants(struct b44 *bp) 
    233  { 
    234         struct ssb_device *sdev = bp->sdev; 
    235 @@ -2235,12 +2214,40 @@ static int b44_init_one(struct ssb_devic 
    236                 goto err_out_powerdown; 
    237         } 
    238   
    239 -       bp->mii_if.dev = dev; 
    240 -       bp->mii_if.mdio_read = b44_mii_read; 
    241 -       bp->mii_if.mdio_write = b44_mii_write; 
    242 -       bp->mii_if.phy_id = bp->phy_addr; 
    243 -       bp->mii_if.phy_id_mask = 0x1f; 
    244 -       bp->mii_if.reg_num_mask = 0x1f; 
    245 +       bp->mii_bus = mdiobus_alloc(); 
    246 +       if (!bp->mii_bus) { 
    247 +               dev_err(sdev->dev, "mdiobus_alloc() failed\n"); 
    248 +               err = -ENOMEM; 
    249 +               goto err_out_powerdown; 
    250 +       } 
    251 + 
    252 +       bp->mii_bus->priv = bp; 
    253 +       bp->mii_bus->read = b44_mii_read; 
    254 +       bp->mii_bus->write = b44_mii_write; 
    255 +       bp->mii_bus->name = "b44_eth_mii"; 
    256 +       bp->mii_bus->parent = sdev->dev; 
    257 +       bp->mii_bus->phy_mask = ~(1 << bp->phy_addr); 
    258 +       snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%x", instance); 
    259 +       bp->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); 
    260 +       if (!bp->mii_bus->irq) { 
    261 +               dev_err(sdev->dev, "mii_bus irq allocation failed\n"); 
    262 +               err = -ENOMEM; 
    263 +               goto err_out_mdiobus; 
    264 +       } 
    265 + 
    266 +       memset(bp->mii_bus->irq, PHY_POLL, sizeof(int) * PHY_MAX_ADDR); 
    267 + 
    268 +       err = mdiobus_register(bp->mii_bus); 
    269 +       if (err) { 
    270 +               dev_err(sdev->dev, "failed to register MII bus\n"); 
    271 +               goto err_out_mdiobus_irq; 
    272 +       } 
    273 + 
    274 +       err = b44_mii_probe(dev); 
    275 +       if (err) { 
    276 +               dev_err(sdev->dev, "failed to probe MII bus\n"); 
    277 +               goto err_out_mdiobus_unregister; 
    278 +       } 
    279   
    280         /* By default, advertise all speed/duplex settings. */ 
    281         bp->flags |= (B44_FLAG_ADV_10HALF | B44_FLAG_ADV_10FULL | 
    282 @@ -2272,6 +2279,16 @@ static int b44_init_one(struct ssb_devic 
     237+ 
     238+err_out_mdiobus_unregister: 
     239+       mdiobus_unregister(mii_bus); 
     240+ 
     241+err_out_mdiobus_irq: 
     242+       kfree(mii_bus->irq); 
     243+ 
     244+err_out_mdiobus: 
     245+       mdiobus_free(mii_bus); 
     246+ 
     247+err_out: 
     248+       return err; 
     249+} 
     250+ 
     251+static void b44_unregister_phy_one(struct b44 *bp) 
     252+{ 
     253+       struct mii_bus *mii_bus = bp->mii_bus; 
     254+ 
     255+       phy_disconnect(bp->phydev); 
     256+       mdiobus_unregister(mii_bus); 
     257+       kfree(mii_bus->irq); 
     258+       mdiobus_free(mii_bus); 
     259+} 
     260+ 
     261 static int b44_init_one(struct ssb_device *sdev, 
     262                        const struct ssb_device_id *ent) 
     263 { 
     264@@ -2246,10 +2408,22 @@ static int b44_init_one(struct ssb_devic 
     265        if (b44_phy_reset(bp) < 0) 
     266                bp->phy_addr = B44_PHY_ADDR_NO_LOACL_PHY; 
     267  
     268+       bp->has_phy = bp->phy_addr == B44_PHY_ADDR_NO_LOACL_PHY; 
     269+ 
     270+       if (bp->has_phy) { 
     271+               err = b44_register_phy_one(bp); 
     272+               if (err) { 
     273+                       dev_err(sdev->dev, "Cannot register PHY, aborting\n"); 
     274+                       goto err_out_unregister_netdev; 
     275+               } 
     276+       } 
     277+ 
     278        netdev_info(dev, "%s %pM\n", DRV_DESCRIPTION, dev->dev_addr); 
    283279  
    284280        return 0; 
    285281  
    286 + 
    287 +err_out_mdiobus_unregister: 
    288 +       mdiobus_unregister(bp->mii_bus); 
    289 + 
    290 +err_out_mdiobus_irq: 
    291 +       kfree(bp->mii_bus->irq); 
    292 + 
    293 +err_out_mdiobus: 
    294 +       mdiobus_free(bp->mii_bus); 
    295 + 
     282+err_out_unregister_netdev: 
     283+       unregister_netdev(dev); 
    296284 err_out_powerdown: 
    297285        ssb_bus_may_powerdown(sdev->bus); 
    298286  
    299 @@ -2285,8 +2302,12 @@ out: 
     287@@ -2263,8 +2437,11 @@ out: 
    300288 static void b44_remove_one(struct ssb_device *sdev) 
    301289 { 
     
    304292  
    305293        unregister_netdev(dev); 
    306 +       mdiobus_unregister(bp->mii_bus); 
    307 +       kfree(bp->mii_bus->irq); 
    308 +       mdiobus_free(bp->mii_bus); 
     294+       if (bp->has_phy) 
     295+               b44_unregister_phy_one(bp); 
    309296        ssb_device_disable(sdev, 0); 
    310297        ssb_bus_may_powerdown(sdev->bus); 
     
    312299--- a/drivers/net/ethernet/broadcom/b44.h 
    313300+++ b/drivers/net/ethernet/broadcom/b44.h 
    314 @@ -396,7 +396,10 @@ struct b44 { 
     301@@ -397,6 +397,11 @@ struct b44 { 
    315302        u32                     tx_pending; 
    316303        u8                      phy_addr; 
    317304        u8                      force_copybreak; 
    318 -       struct mii_if_info      mii_if; 
     305+       bool                    has_phy; 
    319306+       struct phy_device       *phydev; 
    320307+       struct mii_bus          *mii_bus; 
    321308+       int                     old_link; 
    322309+       int                     old_duplex; 
     310        struct mii_if_info      mii_if; 
    323311 }; 
    324312  
    325  #endif /* _B44_H */ 
  • trunk/target/linux/brcm47xx/patches-3.10/210-b44_phy_fix.patch

    r37287 r38306  
    11--- a/drivers/net/ethernet/broadcom/b44.c 
    22+++ b/drivers/net/ethernet/broadcom/b44.c 
    3 @@ -410,10 +410,34 @@ static void b44_wap54g10_workaround(stru 
     3@@ -429,10 +429,34 @@ static void b44_wap54g10_workaround(stru 
    44 error: 
    55        pr_warning("PHY: cannot reset MII transceiver isolate bit\n"); 
     
    1313+       /* Toshiba WRC-1000, Siemens SE505 v1, Askey RT-210W, RT-220W */ 
    1414+       if (sdev->bus->sprom.board_num == 100) { 
    15 +               bp->phy_addr = B44_PHY_ADDR_NO_PHY; 
     15+               bp->phy_addr = B44_PHY_ADDR_NO_LOACL_PHY; 
    1616+       } else { 
    1717+               /* WL-HDD */ 
     
    2020+                       if (sdev->bus->sprom.et0phyaddr == 0 && 
    2121+                           sdev->bus->sprom.et1phyaddr == 1) 
    22 +                               bp->phy_addr = B44_PHY_ADDR_NO_PHY; 
     22+                               bp->phy_addr = B44_PHY_ADDR_NO_LOACL_PHY; 
    2323+               } 
    2424+       } 
     
    3636  
    3737 static int b44_setup_phy(struct b44 *bp) 
    38 @@ -422,6 +446,7 @@ static int b44_setup_phy(struct b44 *bp) 
     38@@ -441,6 +465,7 @@ static int b44_setup_phy(struct b44 *bp) 
    3939        int err; 
    4040  
     
    4242+       b44_bcm47xx_workarounds(bp); 
    4343  
    44         if (bp->phy_addr == B44_PHY_ADDR_NO_PHY) 
     44        if (bp->phy_addr == B44_PHY_ADDR_NO_LOACL_PHY) 
    4545                return 0; 
    46 @@ -2101,6 +2126,8 @@ static int b44_get_invariants(struct b44 
     46@@ -2158,6 +2183,8 @@ static int b44_get_invariants(struct b44 
    4747         * valid PHY address. */ 
    4848        bp->phy_addr &= 0x1F; 
Note: See TracChangeset for help on using the changeset viewer.