fjes: Enhance changing MTU related work
authorTaku Izumi <izumi.taku@jp.fujitsu.com>
Fri, 15 Apr 2016 02:25:40 +0000 (11:25 +0900)
committerDavid S. Miller <davem@davemloft.net>
Sun, 17 Apr 2016 01:51:01 +0000 (21:51 -0400)
This patch enhances the fjes_change_mtu() method
by introducing new flag named FJES_RX_MTU_CHANGING_DONE
in rx_status. At the same time, default MTU value is
changed into 65510 bytes.

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/fjes/fjes_hw.c
drivers/net/fjes/fjes_hw.h
drivers/net/fjes/fjes_main.c

index b103adb8d62ecfa9c1b21647d5c2498fa9586c96..e9f494bd70adbddd0c3f27757db301c40cbc2080 100644 (file)
@@ -179,6 +179,8 @@ void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, u8 *mac_addr, u32 mtu)
 
        for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++)
                info->v1i.vlan_id[i] = vlan_id[i];
+
+       info->v1i.rx_status |= FJES_RX_MTU_CHANGING_DONE;
 }
 
 void
@@ -810,7 +812,8 @@ bool fjes_hw_check_mtu(struct epbuf_handler *epbh, u32 mtu)
 {
        union ep_buffer_info *info = epbh->info;
 
-       return (info->v1i.frame_max == FJES_MTU_TO_FRAME_SIZE(mtu));
+       return ((info->v1i.frame_max == FJES_MTU_TO_FRAME_SIZE(mtu)) &&
+               info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE);
 }
 
 bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
@@ -863,6 +866,9 @@ bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh)
 {
        union ep_buffer_info *info = epbh->info;
 
+       if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE))
+               return true;
+
        if (info->v1i.count_max == 0)
                return true;
 
index baee7f59834b230922bfdf02e09463c510f80e40..f40cf0792a39c154f95b5799b98cd9ebda2b65b3 100644 (file)
@@ -57,6 +57,7 @@ struct fjes_hw;
 #define FJES_RX_STOP_REQ_DONE          (0x1)
 #define FJES_RX_STOP_REQ_REQUEST       (0x2)
 #define FJES_RX_POLL_WORK              (0x4)
+#define FJES_RX_MTU_CHANGING_DONE      (0x8)
 
 #define EP_BUFFER_SIZE \
        (((sizeof(union ep_buffer_info) + (128 * (64 * 1024))) \
index e22a86976dcf5a3a2cc2a8878c3ac82218e22800..3c0c1202f237b8f40e781f69a366deb16691d83a 100644 (file)
@@ -481,6 +481,9 @@ static void fjes_tx_stall_task(struct work_struct *work)
 
                        info = adapter->hw.ep_shm_info[epid].tx.info;
 
+                       if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE))
+                               return;
+
                        if (EP_RING_FULL(info->v1i.head, info->v1i.tail,
                                         info->v1i.count_max)) {
                                all_queue_available = 0;
@@ -760,9 +763,11 @@ fjes_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
 
 static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
 {
+       struct fjes_adapter *adapter = netdev_priv(netdev);
        bool running = netif_running(netdev);
-       int ret = 0;
-       int idx;
+       struct fjes_hw *hw = &adapter->hw;
+       int ret = -EINVAL;
+       int idx, epidx;
 
        for (idx = 0; fjes_support_mtu[idx] != 0; idx++) {
                if (new_mtu <= fjes_support_mtu[idx]) {
@@ -770,19 +775,54 @@ static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
                        if (new_mtu == netdev->mtu)
                                return 0;
 
-                       if (running)
-                               fjes_close(netdev);
+                       ret = 0;
+                       break;
+               }
+       }
+
+       if (ret)
+               return ret;
+
+       if (running) {
+               for (epidx = 0; epidx < hw->max_epid; epidx++) {
+                       if (epidx == hw->my_epid)
+                               continue;
+                       hw->ep_shm_info[epidx].tx.info->v1i.rx_status &=
+                               ~FJES_RX_MTU_CHANGING_DONE;
+               }
+               netif_tx_stop_all_queues(netdev);
+               netif_carrier_off(netdev);
+               cancel_work_sync(&adapter->tx_stall_task);
+               napi_disable(&adapter->napi);
+
+               msleep(1000);
 
-                       netdev->mtu = new_mtu;
+               netif_tx_stop_all_queues(netdev);
+       }
 
-                       if (running)
-                               ret = fjes_open(netdev);
+       netdev->mtu = new_mtu;
 
-                       return ret;
+       if (running) {
+               for (epidx = 0; epidx < hw->max_epid; epidx++) {
+                       if (epidx == hw->my_epid)
+                               continue;
+
+                       local_irq_disable();
+                       fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
+                                           netdev->dev_addr,
+                                           netdev->mtu);
+                       local_irq_enable();
+
+                       hw->ep_shm_info[epidx].tx.info->v1i.rx_status |=
+                               FJES_RX_MTU_CHANGING_DONE;
                }
+
+               netif_tx_wake_all_queues(netdev);
+               netif_carrier_on(netdev);
+               napi_enable(&adapter->napi);
        }
 
-       return -EINVAL;
+       return ret;
 }
 
 static int fjes_vlan_rx_add_vid(struct net_device *netdev,
@@ -1204,7 +1244,7 @@ static void fjes_netdev_setup(struct net_device *netdev)
        netdev->watchdog_timeo = FJES_TX_RETRY_INTERVAL;
        netdev->netdev_ops = &fjes_netdev_ops;
        fjes_set_ethtool_ops(netdev);
-       netdev->mtu = fjes_support_mtu[0];
+       netdev->mtu = fjes_support_mtu[3];
        netdev->flags |= IFF_BROADCAST;
        netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
 }