]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
net: macb: Add support for jumbo frames
authorHarini Katakam <harini.katakam@xilinx.com>
Tue, 7 Apr 2015 15:52:31 +0000 (21:22 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Tue, 7 Apr 2015 18:28:15 +0000 (20:28 +0200)
Add support for jumbo frames in driver if support in IP is communicated
via DT property. Update the register settings and masks as required.

Add hook to accept mtu size changes for jumbo.

jumbo_max_length register is set to 16K on reset in Cadence IP but
Zynq Ultrascale MPSoC supports only upto 10K. Hence this register will be
written with value passed from devicetree.

Signed-off-by: Harini Katakam <harinik@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/cadence/macb.h

index 10b8e70bac923b9d19bc009c546d173c36cd5d11..caa94a1b8a0db8cfbb87235b41e26ca004dae60f 100644 (file)
@@ -54,6 +54,8 @@
 #define MACB_MAX_TX_LEN                ((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1))
 #define GEM_MAX_TX_LEN         ((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1))
 
+#define GEM_MTU_MIN_SIZE       68
+
 /*
  * Graceful stop timeouts in us. We should allow up to
  * 1 frame time (10 Mbits/s, full-duplex, ignoring collisions)
@@ -777,7 +779,7 @@ static int gem_rx(struct macb *bp, int budget)
                }
                /* now everything is ready for receiving packet */
                bp->rx_skbuff[entry] = NULL;
-               len = MACB_BFEXT(RX_FRMLEN, ctrl);
+               len = ctrl & bp->rx_frm_len_mask;
 
                netdev_vdbg(bp->dev, "gem_rx %u (len %u)\n", entry, len);
 
@@ -823,7 +825,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
        struct macb_dma_desc *desc;
 
        desc = macb_rx_desc(bp, last_frag);
-       len = MACB_BFEXT(RX_FRMLEN, desc->ctrl);
+       len = desc->ctrl & bp->rx_frm_len_mask;
 
        netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
                macb_rx_ring_wrap(first_frag),
@@ -1611,7 +1613,10 @@ static void macb_init_hw(struct macb *bp)
        config |= MACB_BF(RBOF, NET_IP_ALIGN);  /* Make eth data aligned */
        config |= MACB_BIT(PAE);                /* PAuse Enable */
        config |= MACB_BIT(DRFCS);              /* Discard Rx FCS */
-       config |= MACB_BIT(BIG);                /* Receive oversized frames */
+       if (bp->isjumbo)
+               config |= MACB_BIT(JFRAME);     /* Enable jumbo frames */
+       else
+               config |= MACB_BIT(BIG);        /* Receive oversized frames */
        if (bp->dev->flags & IFF_PROMISC)
                config |= MACB_BIT(CAF);        /* Copy All Frames */
        else if (macb_is_gem(bp) && bp->dev->features & NETIF_F_RXCSUM)
@@ -1620,9 +1625,15 @@ static void macb_init_hw(struct macb *bp)
                config |= MACB_BIT(NBC);        /* No BroadCast */
        config |= macb_dbw(bp);
        macb_writel(bp, NCFGR, config);
+       if (bp->isjumbo && bp->jumbo_max_len)
+               gem_writel(bp, JML, bp->jumbo_max_len);
        bp->speed = SPEED_10;
        bp->duplex = DUPLEX_HALF;
 
+       bp->rx_frm_len_mask = MACB_RX_FRMLEN_MASK;
+       if (bp->isjumbo)
+               bp->rx_frm_len_mask = MACB_RX_JFRMLEN_MASK;
+
        macb_configure_dma(bp);
 
        /* Initialize TX and RX buffers */
@@ -1826,6 +1837,23 @@ static int macb_close(struct net_device *dev)
        return 0;
 }
 
+static int macb_change_mtu(struct net_device *dev, int new_mtu)
+{
+       struct macb *bp = netdev_priv(dev);
+       u32 max_mtu;
+
+       if (netif_running(dev))
+               return -EBUSY;
+
+       max_mtu = gem_readl(bp, JML) - ETH_HLEN - ETH_FCS_LEN;
+       if ((new_mtu > max_mtu) || (new_mtu < GEM_MTU_MIN_SIZE))
+               return -EINVAL;
+
+       dev->mtu = new_mtu;
+
+       return 0;
+}
+
 static void gem_update_stats(struct macb *bp)
 {
        u32 __iomem *reg = bp->regs + GEM_OTX;
@@ -2045,11 +2073,11 @@ static const struct net_device_ops macb_netdev_ops = {
        .ndo_open               = macb_open,
        .ndo_stop               = macb_close,
        .ndo_start_xmit         = macb_start_xmit,
+       .ndo_change_mtu         = macb_change_mtu,
        .ndo_set_rx_mode        = macb_set_rx_mode,
        .ndo_get_stats          = macb_get_stats,
        .ndo_do_ioctl           = macb_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = macb_poll_controller,
@@ -2231,6 +2259,10 @@ static int __init macb_probe(struct platform_device *pdev)
        bp->hclk = hclk;
        bp->tx_clk = tx_clk;
 
+       of_property_read_u32(pdev->dev.of_node, "jumbo-max-len",
+                            &bp->jumbo_max_len);
+       bp->isjumbo = of_property_read_bool(pdev->dev.of_node,
+                                           "jumbo-supported");
        spin_lock_init(&bp->lock);
 
        /* set the queue register mapping once for all: queue0 has a special
index 7d70f77f0418e8e2ff047fb1b194c277e6bc6500..48ff1623c84f55026f61c0b7315259d0cc7a5f1c 100644 (file)
@@ -71,6 +71,7 @@
 #define GEM_NCFGR                              0x0004
 #define GEM_USRIO                              0x000c
 #define GEM_DMACFG                             0x0010
+#define GEM_JML                                0x0048
 #define GEM_HRB                                        0x0080
 #define GEM_HRT                                        0x0084
 #define GEM_SA1B                               0x0088
@@ -466,6 +467,9 @@ struct macb_dma_desc {
 #define MACB_RX_BROADCAST_OFFSET               31
 #define MACB_RX_BROADCAST_SIZE                 1
 
+#define MACB_RX_FRMLEN_MASK                    0xFFF
+#define MACB_RX_JFRMLEN_MASK                   0x3FFF
+
 /* RX checksum offload disabled: bit 24 clear in NCFGR */
 #define GEM_RX_TYPEID_MATCH_OFFSET             22
 #define GEM_RX_TYPEID_MATCH_SIZE               2
@@ -673,6 +677,9 @@ struct macb {
        dma_addr_t skb_physaddr;                /* phys addr from pci_map_single */
        int skb_length;                         /* saved skb length for pci_unmap_single */
        unsigned int            max_tx_length;
+       unsigned int            rx_frm_len_mask;
+       unsigned int            jumbo_max_len;
+       bool                    isjumbo;
 };
 
 extern const struct ethtool_ops macb_ethtool_ops;