ltq-ptm: Support 1508-byte MTU for RFC4638
[openwrt/openwrt.git] / package / kernel / lantiq / ltq-ptm / src / ifxmips_ptm_vdsl.c
index 9c25c154b54f9c8b29688f0a3588c463df0497a3..bc27c270d825543dfab270ed9767402af5f6ceb4 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/ioctl.h>
 #include <linux/etherdevice.h>
 #include <linux/interrupt.h>
+#include <linux/netdevice.h>
 
 #include "ifxmips_ptm_vdsl.h"
 #include <lantiq_soc.h>
@@ -66,13 +67,14 @@ unsigned long cgu_get_pp32_clock(void)
        return rate;
 }
 
-static void ptm_setup(struct net_device *);
+static void ptm_setup(struct net_device *, int);
 static struct net_device_stats *ptm_get_stats(struct net_device *);
 static int ptm_open(struct net_device *);
 static int ptm_stop(struct net_device *);
   static unsigned int ptm_poll(int, unsigned int);
   static int ptm_napi_poll(struct napi_struct *, int);
 static int ptm_hard_start_xmit(struct sk_buff *, struct net_device *);
+static int ptm_change_mtu(struct net_device *, int);
 static int ptm_ioctl(struct net_device *, struct ifreq *, int);
 static void ptm_tx_timeout(struct net_device *);
 
@@ -113,7 +115,7 @@ static struct net_device_ops g_ptm_netdev_ops = {
     .ndo_start_xmit      = ptm_hard_start_xmit,
     .ndo_validate_addr   = eth_validate_addr,
     .ndo_set_mac_address = eth_mac_addr,
-    .ndo_change_mtu      = eth_change_mtu,
+    .ndo_change_mtu      = ptm_change_mtu,
     .ndo_do_ioctl        = ptm_ioctl,
     .ndo_tx_timeout      = ptm_tx_timeout,
 };
@@ -134,9 +136,10 @@ unsigned int ifx_ptm_dbg_enable = DBG_ENABLE_MASK_ERR;
  * ####################################
  */
 
-static void ptm_setup(struct net_device *dev)
+static void ptm_setup(struct net_device *dev, int ndev)
 {
-    int ndev = 0;
+    netif_carrier_off(dev);
+
     dev->netdev_ops      = &g_ptm_netdev_ops;
     netif_napi_add(dev, &g_ptm_priv_data.itf[ndev].napi, ptm_napi_poll, 16);
     dev->watchdog_timeo  = ETH_WATCHDOG_TIMEOUT;
@@ -356,6 +359,15 @@ PTM_HARD_START_XMIT_FAIL:
     return 0;
 }
 
+static int ptm_change_mtu(struct net_device *dev, int mtu)
+{
+       /* Allow up to 1508 bytes, for RFC4638 */
+        if (mtu < 68 || mtu > ETH_DATA_LEN + 8)
+                return -EINVAL;
+        dev->mtu = mtu;
+        return 0;
+}
+
 static int ptm_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
     ASSERT(dev == g_net_dev[0], "incorrect device");
@@ -889,6 +901,8 @@ static inline void clear_tables(void)
 
 static int ptm_showtime_enter(struct port_cell_info *port_cell, void *xdata_addr)
 {
+       int i;
+
        ASSERT(port_cell != NULL, "port_cell is NULL");
        ASSERT(xdata_addr != NULL, "xdata_addr is NULL");
 
@@ -897,6 +911,9 @@ static int ptm_showtime_enter(struct port_cell_info *port_cell, void *xdata_addr
 
        g_showtime = 1;
 
+       for ( i = 0; i < ARRAY_SIZE(g_net_dev); i++ )
+               netif_carrier_on(g_net_dev[i]);
+
        IFX_REG_W32(0x0F, UTP_CFG);
 
        //#ifdef CONFIG_VR9
@@ -910,6 +927,8 @@ static int ptm_showtime_enter(struct port_cell_info *port_cell, void *xdata_addr
 
 static int ptm_showtime_exit(void)
 {
+       int i;
+
        if ( !g_showtime )
                return -1;
 
@@ -919,6 +938,9 @@ static int ptm_showtime_exit(void)
 
        IFX_REG_W32(0x00, UTP_CFG);
 
+       for ( i = 0; i < ARRAY_SIZE(g_net_dev); i++ )
+               netif_carrier_off(g_net_dev[i]);
+
        g_showtime = 0;
 
        //  TODO: ReTX clean state
@@ -952,9 +974,10 @@ static int ifx_ptm_init(void)
     }
 
     for ( i = 0; i < ARRAY_SIZE(g_net_dev); i++ ) {
-        g_net_dev[i] = alloc_netdev(0, g_net_dev_name[i], ether_setup, ptm_setup);
+        g_net_dev[i] = alloc_netdev(0, g_net_dev_name[i], NET_NAME_UNKNOWN, ether_setup);
         if ( g_net_dev[i] == NULL )
             goto ALLOC_NETDEV_FAIL;
+        ptm_setup(g_net_dev[i], i);
     }
 
     for ( i = 0; i < ARRAY_SIZE(g_net_dev); i++ ) {
@@ -964,7 +987,11 @@ static int ifx_ptm_init(void)
     }
 
     /*  register interrupt handler  */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0)
+    ret = request_irq(PPE_MAILBOX_IGU1_INT, mailbox_irq_handler, 0, "ptm_mailbox_isr", &g_ptm_priv_data);
+#else
     ret = request_irq(PPE_MAILBOX_IGU1_INT, mailbox_irq_handler, IRQF_DISABLED, "ptm_mailbox_isr", &g_ptm_priv_data);
+#endif
     if ( ret ) {
         if ( ret == -EBUSY ) {
             err("IRQ may be occupied by other driver, please reconfig to disable it.");