Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[cascardo/linux.git] / drivers / net / ethernet / broadcom / bcmsysport.c
index d9b9170..9ae3697 100644 (file)
@@ -139,6 +139,15 @@ static int bcm_sysport_set_rx_csum(struct net_device *dev,
        else
                reg &= ~RXCHK_SKIP_FCS;
 
+       /* If Broadcom tags are enabled (e.g: using a switch), make
+        * sure we tell the RXCHK hardware to expect a 4-bytes Broadcom
+        * tag after the Ethernet MAC Source Address.
+        */
+       if (netdev_uses_dsa(dev))
+               reg |= RXCHK_BRCM_TAG_EN;
+       else
+               reg &= ~RXCHK_BRCM_TAG_EN;
+
        rxchk_writel(priv, reg, RXCHK_CONTROL);
 
        return 0;
@@ -427,7 +436,8 @@ static int bcm_sysport_set_wol(struct net_device *dev,
        /* Flag the device and relevant IRQ as wakeup capable */
        if (wol->wolopts) {
                device_set_wakeup_enable(kdev, 1);
-               enable_irq_wake(priv->wol_irq);
+               if (priv->wol_irq_disabled)
+                       enable_irq_wake(priv->wol_irq);
                priv->wol_irq_disabled = 0;
        } else {
                device_set_wakeup_enable(kdev, 0);
@@ -848,7 +858,8 @@ static irqreturn_t bcm_sysport_wol_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int bcm_sysport_insert_tsb(struct sk_buff *skb, struct net_device *dev)
+static struct sk_buff *bcm_sysport_insert_tsb(struct sk_buff *skb,
+                                             struct net_device *dev)
 {
        struct sk_buff *nskb;
        struct bcm_tsb *tsb;
@@ -864,7 +875,7 @@ static int bcm_sysport_insert_tsb(struct sk_buff *skb, struct net_device *dev)
                if (!nskb) {
                        dev->stats.tx_errors++;
                        dev->stats.tx_dropped++;
-                       return -ENOMEM;
+                       return NULL;
                }
                skb = nskb;
        }
@@ -883,7 +894,7 @@ static int bcm_sysport_insert_tsb(struct sk_buff *skb, struct net_device *dev)
                        ip_proto = ipv6_hdr(skb)->nexthdr;
                        break;
                default:
-                       return 0;
+                       return skb;
                }
 
                /* Get the checksum offset and the L4 (transport) offset */
@@ -902,7 +913,7 @@ static int bcm_sysport_insert_tsb(struct sk_buff *skb, struct net_device *dev)
                tsb->l4_ptr_dest_map = csum_info;
        }
 
-       return 0;
+       return skb;
 }
 
 static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
@@ -936,8 +947,8 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
 
        /* Insert TSB and checksum infos */
        if (priv->tsb_en) {
-               ret = bcm_sysport_insert_tsb(skb, dev);
-               if (ret) {
+               skb = bcm_sysport_insert_tsb(skb, dev);
+               if (!skb) {
                        ret = NETDEV_TX_OK;
                        goto out;
                }
@@ -1069,16 +1080,19 @@ static void bcm_sysport_adj_link(struct net_device *dev)
        if (!phydev->pause)
                cmd_bits |= CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE;
 
-       if (changed) {
+       if (!changed)
+               return;
+
+       if (phydev->link) {
                reg = umac_readl(priv, UMAC_CMD);
                reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
                        CMD_HD_EN | CMD_RX_PAUSE_IGNORE |
                        CMD_TX_PAUSE_IGNORE);
                reg |= cmd_bits;
                umac_writel(priv, reg, UMAC_CMD);
-
-               phy_print_status(priv->phydev);
        }
+
+       phy_print_status(priv->phydev);
 }
 
 static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,