brcm47xx: bgmac: make it possible to set the devices into promisc mode when it is...
authorHauke Mehrtens <hauke@openwrt.org>
Wed, 6 Feb 2013 14:57:00 +0000 (14:57 +0000)
committerHauke Mehrtens <hauke@openwrt.org>
Wed, 6 Feb 2013 14:57:00 +0000 (14:57 +0000)
This fixes #12927.

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35507 3c298f89-4303-0410-b956-a3cf2f4a3e73

target/linux/brcm47xx/patches-3.6/720-eth-backport.patch [new file with mode: 0644]
target/linux/brcm47xx/patches-3.6/760-bgmac-fixes.patch [new file with mode: 0644]

diff --git a/target/linux/brcm47xx/patches-3.6/720-eth-backport.patch b/target/linux/brcm47xx/patches-3.6/720-eth-backport.patch
new file mode 100644 (file)
index 0000000..98da18a
--- /dev/null
@@ -0,0 +1,94 @@
+commit fa0879e37b59e8e3f130a30a9e6fa515717c5bdd
+Author: Stefan Hajnoczi <stefanha@gmail.com>
+Date:   Mon Jan 21 01:17:22 2013 +0000
+
+    net: split eth_mac_addr for better error handling
+    
+    When we set mac address, software mac address in system and hardware mac
+    address all need to be updated. Current eth_mac_addr() doesn't allow
+    callers to implement error handling nicely.
+    
+    This patch split eth_mac_addr() to prepare part and real commit part,
+    then we can prepare first, and try to change hardware address, then do
+    the real commit if hardware address is set successfully.
+    
+    Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
+    Signed-off-by: Amos Kong <akong@redhat.com>
+    Signed-off-by: David S. Miller <davem@davemloft.net>
+
+--- a/include/linux/etherdevice.h
++++ b/include/linux/etherdevice.h
+@@ -40,6 +40,8 @@ extern int eth_header_cache(const struct
+ extern void eth_header_cache_update(struct hh_cache *hh,
+                                   const struct net_device *dev,
+                                   const unsigned char *haddr);
++extern int eth_prepare_mac_addr_change(struct net_device *dev, void *p);
++extern void eth_commit_mac_addr_change(struct net_device *dev, void *p);
+ extern int eth_mac_addr(struct net_device *dev, void *p);
+ extern int eth_change_mtu(struct net_device *dev, int new_mtu);
+ extern int eth_validate_addr(struct net_device *dev);
+--- a/net/ethernet/eth.c
++++ b/net/ethernet/eth.c
+@@ -278,16 +278,11 @@ void eth_header_cache_update(struct hh_c
+ EXPORT_SYMBOL(eth_header_cache_update);
+ /**
+- * eth_mac_addr - set new Ethernet hardware address
++ * eth_prepare_mac_addr_change - prepare for mac change
+  * @dev: network device
+  * @p: socket address
+- *
+- * Change hardware address of device.
+- *
+- * This doesn't change hardware matching, so needs to be overridden
+- * for most real devices.
+  */
+-int eth_mac_addr(struct net_device *dev, void *p)
++int eth_prepare_mac_addr_change(struct net_device *dev, void *p)
+ {
+       struct sockaddr *addr = p;
+@@ -295,9 +290,43 @@ int eth_mac_addr(struct net_device *dev,
+               return -EBUSY;
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
++      return 0;
++}
++EXPORT_SYMBOL(eth_prepare_mac_addr_change);
++
++/**
++ * eth_commit_mac_addr_change - commit mac change
++ * @dev: network device
++ * @p: socket address
++ */
++void eth_commit_mac_addr_change(struct net_device *dev, void *p)
++{
++      struct sockaddr *addr = p;
++
+       memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+       /* if device marked as NET_ADDR_RANDOM, reset it */
+       dev->addr_assign_type &= ~NET_ADDR_RANDOM;
++}
++EXPORT_SYMBOL(eth_commit_mac_addr_change);
++
++/**
++ * eth_mac_addr - set new Ethernet hardware address
++ * @dev: network device
++ * @p: socket address
++ *
++ * Change hardware address of device.
++ *
++ * This doesn't change hardware matching, so needs to be overridden
++ * for most real devices.
++ */
++int eth_mac_addr(struct net_device *dev, void *p)
++{
++      int ret;
++
++      ret = eth_prepare_mac_addr_change(dev, p);
++      if (ret < 0)
++              return ret;
++      eth_commit_mac_addr_change(dev, p);
+       return 0;
+ }
+ EXPORT_SYMBOL(eth_mac_addr);
diff --git a/target/linux/brcm47xx/patches-3.6/760-bgmac-fixes.patch b/target/linux/brcm47xx/patches-3.6/760-bgmac-fixes.patch
new file mode 100644 (file)
index 0000000..dfe9ccf
--- /dev/null
@@ -0,0 +1,112 @@
+--- a/drivers/net/ethernet/broadcom/bgmac.c
++++ b/drivers/net/ethernet/broadcom/bgmac.c
+@@ -761,6 +761,26 @@ static void bgmac_cmdcfg_maskset(struct
+       udelay(2);
+ }
++static void bgmac_write_mac_address(struct bgmac *bgmac, u8 *addr)
++{
++      u32 tmp;
++
++      tmp = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3];
++      bgmac_write(bgmac, BGMAC_MACADDR_HIGH, tmp);
++      tmp = (addr[4] << 8) | addr[5];
++      bgmac_write(bgmac, BGMAC_MACADDR_LOW, tmp);
++}
++
++static void bgmac_set_rx_mode(struct net_device *net_dev)
++{
++      struct bgmac *bgmac = netdev_priv(net_dev);
++
++      if (net_dev->flags & IFF_PROMISC)
++              bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_PROM, false);
++      else
++              bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_PROM, 0, false);
++}
++
+ #if 0 /* We don't use that regs yet */
+ static void bgmac_chip_stats_update(struct bgmac *bgmac)
+ {
+@@ -889,8 +909,10 @@ static void bgmac_chip_reset(struct bgma
+                       sw_type = et_swtype;
+               } else if (ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == 9) {
+                       sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHYRMII;
+-              } else if (0) {
+-                      /* TODO */
++              } else if ((ci->id != BCMA_CHIP_ID_BCM53572 && ci->pkg == 10) ||
++                         (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == 9)) {
++                      sw_type = BGMAC_CHIPCTL_1_IF_TYPE_RGMII |
++                                BGMAC_CHIPCTL_1_SW_TYPE_RGMII;
+               }
+               bcma_chipco_chipctl_maskset(cc, 1,
+                                           ~(BGMAC_CHIPCTL_1_IF_TYPE_MASK |
+@@ -1004,8 +1026,6 @@ static void bgmac_enable(struct bgmac *b
+ static void bgmac_chip_init(struct bgmac *bgmac, bool full_init)
+ {
+       struct bgmac_dma_ring *ring;
+-      u8 *mac = bgmac->net_dev->dev_addr;
+-      u32 tmp;
+       int i;
+       /* 1 interrupt per received frame */
+@@ -1014,16 +1034,9 @@ static void bgmac_chip_init(struct bgmac
+       /* Enable 802.3x tx flow control (honor received PAUSE frames) */
+       bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_RPI, 0, true);
+-      if (bgmac->net_dev->flags & IFF_PROMISC)
+-              bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_PROM, false);
+-      else
+-              bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_PROM, 0, false);
++      bgmac_set_rx_mode(bgmac->net_dev);
+-      /* Set MAC addr */
+-      tmp = (mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3];
+-      bgmac_write(bgmac, BGMAC_MACADDR_HIGH, tmp);
+-      tmp = (mac[4] << 8) | mac[5];
+-      bgmac_write(bgmac, BGMAC_MACADDR_LOW, tmp);
++      bgmac_write_mac_address(bgmac, bgmac->net_dev->dev_addr);
+       if (bgmac->loopback)
+               bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_ML, true);
+@@ -1160,6 +1173,19 @@ static netdev_tx_t bgmac_start_xmit(stru
+       return bgmac_dma_tx_add(bgmac, ring, skb);
+ }
++static int bgmac_set_mac_address(struct net_device *net_dev, void *addr)
++{
++      struct bgmac *bgmac = netdev_priv(net_dev);
++      int ret;
++
++      ret = eth_prepare_mac_addr_change(net_dev, addr);
++      if (ret < 0)
++              return ret;
++      bgmac_write_mac_address(bgmac, (u8 *)addr);
++      eth_commit_mac_addr_change(net_dev, addr);
++      return 0;
++}
++
+ static int bgmac_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
+ {
+       struct bgmac *bgmac = netdev_priv(net_dev);
+@@ -1190,7 +1216,9 @@ static const struct net_device_ops bgmac
+       .ndo_open               = bgmac_open,
+       .ndo_stop               = bgmac_stop,
+       .ndo_start_xmit         = bgmac_start_xmit,
+-      .ndo_set_mac_address    = eth_mac_addr, /* generic, sets dev_addr */
++      .ndo_set_rx_mode        = bgmac_set_rx_mode,
++      .ndo_set_mac_address    = bgmac_set_mac_address,
++      .ndo_validate_addr      = eth_validate_addr,
+       .ndo_do_ioctl           = bgmac_ioctl,
+ };
+--- a/drivers/net/ethernet/broadcom/bgmac.h
++++ b/drivers/net/ethernet/broadcom/bgmac.h
+@@ -339,7 +339,7 @@
+ #define BGMAC_CHIPCTL_1_SW_TYPE_EPHY          0x00000000
+ #define BGMAC_CHIPCTL_1_SW_TYPE_EPHYMII               0x00000040
+ #define BGMAC_CHIPCTL_1_SW_TYPE_EPHYRMII      0x00000080
+-#define BGMAC_CHIPCTL_1_SW_TYPE_RGMI          0x000000C0
++#define BGMAC_CHIPCTL_1_SW_TYPE_RGMII         0x000000C0
+ #define BGMAC_CHIPCTL_1_RXC_DLL_BYPASS                0x00010000
+ #define BGMAC_SPEED_10                                0x0001