@@ -1357,6 +1357,182 @@ static void mtk_hwlro_rx_uninit(struct mtk_eth *eth)
13571357 mtk_w32 (eth , 0 , MTK_PDMA_LRO_CTRL_DW0 );
13581358}
13591359
1360+ static void mtk_hwlro_val_ipaddr (struct mtk_eth * eth , int idx , __be32 ip )
1361+ {
1362+ u32 reg_val ;
1363+
1364+ reg_val = mtk_r32 (eth , MTK_LRO_CTRL_DW2_CFG (idx ));
1365+
1366+ /* invalidate the IP setting */
1367+ mtk_w32 (eth , (reg_val & ~MTK_RING_MYIP_VLD ), MTK_LRO_CTRL_DW2_CFG (idx ));
1368+
1369+ mtk_w32 (eth , ip , MTK_LRO_DIP_DW0_CFG (idx ));
1370+
1371+ /* validate the IP setting */
1372+ mtk_w32 (eth , (reg_val | MTK_RING_MYIP_VLD ), MTK_LRO_CTRL_DW2_CFG (idx ));
1373+ }
1374+
1375+ static void mtk_hwlro_inval_ipaddr (struct mtk_eth * eth , int idx )
1376+ {
1377+ u32 reg_val ;
1378+
1379+ reg_val = mtk_r32 (eth , MTK_LRO_CTRL_DW2_CFG (idx ));
1380+
1381+ /* invalidate the IP setting */
1382+ mtk_w32 (eth , (reg_val & ~MTK_RING_MYIP_VLD ), MTK_LRO_CTRL_DW2_CFG (idx ));
1383+
1384+ mtk_w32 (eth , 0 , MTK_LRO_DIP_DW0_CFG (idx ));
1385+ }
1386+
1387+ static int mtk_hwlro_get_ip_cnt (struct mtk_mac * mac )
1388+ {
1389+ int cnt = 0 ;
1390+ int i ;
1391+
1392+ for (i = 0 ; i < MTK_MAX_LRO_IP_CNT ; i ++ ) {
1393+ if (mac -> hwlro_ip [i ])
1394+ cnt ++ ;
1395+ }
1396+
1397+ return cnt ;
1398+ }
1399+
1400+ static int mtk_hwlro_add_ipaddr (struct net_device * dev ,
1401+ struct ethtool_rxnfc * cmd )
1402+ {
1403+ struct ethtool_rx_flow_spec * fsp =
1404+ (struct ethtool_rx_flow_spec * )& cmd -> fs ;
1405+ struct mtk_mac * mac = netdev_priv (dev );
1406+ struct mtk_eth * eth = mac -> hw ;
1407+ int hwlro_idx ;
1408+
1409+ if ((fsp -> flow_type != TCP_V4_FLOW ) ||
1410+ (!fsp -> h_u .tcp_ip4_spec .ip4dst ) ||
1411+ (fsp -> location > 1 ))
1412+ return - EINVAL ;
1413+
1414+ mac -> hwlro_ip [fsp -> location ] = htonl (fsp -> h_u .tcp_ip4_spec .ip4dst );
1415+ hwlro_idx = (mac -> id * MTK_MAX_LRO_IP_CNT ) + fsp -> location ;
1416+
1417+ mac -> hwlro_ip_cnt = mtk_hwlro_get_ip_cnt (mac );
1418+
1419+ mtk_hwlro_val_ipaddr (eth , hwlro_idx , mac -> hwlro_ip [fsp -> location ]);
1420+
1421+ return 0 ;
1422+ }
1423+
1424+ static int mtk_hwlro_del_ipaddr (struct net_device * dev ,
1425+ struct ethtool_rxnfc * cmd )
1426+ {
1427+ struct ethtool_rx_flow_spec * fsp =
1428+ (struct ethtool_rx_flow_spec * )& cmd -> fs ;
1429+ struct mtk_mac * mac = netdev_priv (dev );
1430+ struct mtk_eth * eth = mac -> hw ;
1431+ int hwlro_idx ;
1432+
1433+ if (fsp -> location > 1 )
1434+ return - EINVAL ;
1435+
1436+ mac -> hwlro_ip [fsp -> location ] = 0 ;
1437+ hwlro_idx = (mac -> id * MTK_MAX_LRO_IP_CNT ) + fsp -> location ;
1438+
1439+ mac -> hwlro_ip_cnt = mtk_hwlro_get_ip_cnt (mac );
1440+
1441+ mtk_hwlro_inval_ipaddr (eth , hwlro_idx );
1442+
1443+ return 0 ;
1444+ }
1445+
1446+ static void mtk_hwlro_netdev_disable (struct net_device * dev )
1447+ {
1448+ struct mtk_mac * mac = netdev_priv (dev );
1449+ struct mtk_eth * eth = mac -> hw ;
1450+ int i , hwlro_idx ;
1451+
1452+ for (i = 0 ; i < MTK_MAX_LRO_IP_CNT ; i ++ ) {
1453+ mac -> hwlro_ip [i ] = 0 ;
1454+ hwlro_idx = (mac -> id * MTK_MAX_LRO_IP_CNT ) + i ;
1455+
1456+ mtk_hwlro_inval_ipaddr (eth , hwlro_idx );
1457+ }
1458+
1459+ mac -> hwlro_ip_cnt = 0 ;
1460+ }
1461+
1462+ static int mtk_hwlro_get_fdir_entry (struct net_device * dev ,
1463+ struct ethtool_rxnfc * cmd )
1464+ {
1465+ struct mtk_mac * mac = netdev_priv (dev );
1466+ struct ethtool_rx_flow_spec * fsp =
1467+ (struct ethtool_rx_flow_spec * )& cmd -> fs ;
1468+
1469+ /* only tcp dst ipv4 is meaningful, others are meaningless */
1470+ fsp -> flow_type = TCP_V4_FLOW ;
1471+ fsp -> h_u .tcp_ip4_spec .ip4dst = ntohl (mac -> hwlro_ip [fsp -> location ]);
1472+ fsp -> m_u .tcp_ip4_spec .ip4dst = 0 ;
1473+
1474+ fsp -> h_u .tcp_ip4_spec .ip4src = 0 ;
1475+ fsp -> m_u .tcp_ip4_spec .ip4src = 0xffffffff ;
1476+ fsp -> h_u .tcp_ip4_spec .psrc = 0 ;
1477+ fsp -> m_u .tcp_ip4_spec .psrc = 0xffff ;
1478+ fsp -> h_u .tcp_ip4_spec .pdst = 0 ;
1479+ fsp -> m_u .tcp_ip4_spec .pdst = 0xffff ;
1480+ fsp -> h_u .tcp_ip4_spec .tos = 0 ;
1481+ fsp -> m_u .tcp_ip4_spec .tos = 0xff ;
1482+
1483+ return 0 ;
1484+ }
1485+
1486+ static int mtk_hwlro_get_fdir_all (struct net_device * dev ,
1487+ struct ethtool_rxnfc * cmd ,
1488+ u32 * rule_locs )
1489+ {
1490+ struct mtk_mac * mac = netdev_priv (dev );
1491+ int cnt = 0 ;
1492+ int i ;
1493+
1494+ for (i = 0 ; i < MTK_MAX_LRO_IP_CNT ; i ++ ) {
1495+ if (mac -> hwlro_ip [i ]) {
1496+ rule_locs [cnt ] = i ;
1497+ cnt ++ ;
1498+ }
1499+ }
1500+
1501+ cmd -> rule_cnt = cnt ;
1502+
1503+ return 0 ;
1504+ }
1505+
1506+ static netdev_features_t mtk_fix_features (struct net_device * dev ,
1507+ netdev_features_t features )
1508+ {
1509+ if (!(features & NETIF_F_LRO )) {
1510+ struct mtk_mac * mac = netdev_priv (dev );
1511+ int ip_cnt = mtk_hwlro_get_ip_cnt (mac );
1512+
1513+ if (ip_cnt ) {
1514+ netdev_info (dev , "RX flow is programmed, LRO should keep on\n" );
1515+
1516+ features |= NETIF_F_LRO ;
1517+ }
1518+ }
1519+
1520+ return features ;
1521+ }
1522+
1523+ static int mtk_set_features (struct net_device * dev , netdev_features_t features )
1524+ {
1525+ int err = 0 ;
1526+
1527+ if (!((dev -> features ^ features ) & NETIF_F_LRO ))
1528+ return 0 ;
1529+
1530+ if (!(features & NETIF_F_LRO ))
1531+ mtk_hwlro_netdev_disable (dev );
1532+
1533+ return err ;
1534+ }
1535+
13601536/* wait for DMA to finish whatever it is doing before we start using it again */
13611537static int mtk_dma_busy_wait (struct mtk_eth * eth )
13621538{
@@ -1971,6 +2147,62 @@ static void mtk_get_ethtool_stats(struct net_device *dev,
19712147 } while (u64_stats_fetch_retry_irq (& hwstats -> syncp , start ));
19722148}
19732149
2150+ static int mtk_get_rxnfc (struct net_device * dev , struct ethtool_rxnfc * cmd ,
2151+ u32 * rule_locs )
2152+ {
2153+ int ret = - EOPNOTSUPP ;
2154+
2155+ switch (cmd -> cmd ) {
2156+ case ETHTOOL_GRXRINGS :
2157+ if (dev -> features & NETIF_F_LRO ) {
2158+ cmd -> data = MTK_MAX_RX_RING_NUM ;
2159+ ret = 0 ;
2160+ }
2161+ break ;
2162+ case ETHTOOL_GRXCLSRLCNT :
2163+ if (dev -> features & NETIF_F_LRO ) {
2164+ struct mtk_mac * mac = netdev_priv (dev );
2165+
2166+ cmd -> rule_cnt = mac -> hwlro_ip_cnt ;
2167+ ret = 0 ;
2168+ }
2169+ break ;
2170+ case ETHTOOL_GRXCLSRULE :
2171+ if (dev -> features & NETIF_F_LRO )
2172+ ret = mtk_hwlro_get_fdir_entry (dev , cmd );
2173+ break ;
2174+ case ETHTOOL_GRXCLSRLALL :
2175+ if (dev -> features & NETIF_F_LRO )
2176+ ret = mtk_hwlro_get_fdir_all (dev , cmd ,
2177+ rule_locs );
2178+ break ;
2179+ default :
2180+ break ;
2181+ }
2182+
2183+ return ret ;
2184+ }
2185+
2186+ static int mtk_set_rxnfc (struct net_device * dev , struct ethtool_rxnfc * cmd )
2187+ {
2188+ int ret = - EOPNOTSUPP ;
2189+
2190+ switch (cmd -> cmd ) {
2191+ case ETHTOOL_SRXCLSRLINS :
2192+ if (dev -> features & NETIF_F_LRO )
2193+ ret = mtk_hwlro_add_ipaddr (dev , cmd );
2194+ break ;
2195+ case ETHTOOL_SRXCLSRLDEL :
2196+ if (dev -> features & NETIF_F_LRO )
2197+ ret = mtk_hwlro_del_ipaddr (dev , cmd );
2198+ break ;
2199+ default :
2200+ break ;
2201+ }
2202+
2203+ return ret ;
2204+ }
2205+
19742206static const struct ethtool_ops mtk_ethtool_ops = {
19752207 .get_settings = mtk_get_settings ,
19762208 .set_settings = mtk_set_settings ,
@@ -1982,6 +2214,8 @@ static const struct ethtool_ops mtk_ethtool_ops = {
19822214 .get_strings = mtk_get_strings ,
19832215 .get_sset_count = mtk_get_sset_count ,
19842216 .get_ethtool_stats = mtk_get_ethtool_stats ,
2217+ .get_rxnfc = mtk_get_rxnfc ,
2218+ .set_rxnfc = mtk_set_rxnfc ,
19852219};
19862220
19872221static const struct net_device_ops mtk_netdev_ops = {
@@ -1996,6 +2230,8 @@ static const struct net_device_ops mtk_netdev_ops = {
19962230 .ndo_change_mtu = eth_change_mtu ,
19972231 .ndo_tx_timeout = mtk_tx_timeout ,
19982232 .ndo_get_stats64 = mtk_get_stats64 ,
2233+ .ndo_fix_features = mtk_fix_features ,
2234+ .ndo_set_features = mtk_set_features ,
19992235#ifdef CONFIG_NET_POLL_CONTROLLER
20002236 .ndo_poll_controller = mtk_poll_controller ,
20012237#endif
0 commit comments