15
15
#include <linux/module.h>
16
16
#include <linux/kernel.h>
17
17
#include <linux/netdevice.h>
18
+ #include <linux/net_dim.h>
18
19
#include <linux/etherdevice.h>
19
20
#include <linux/platform_device.h>
20
21
#include <linux/of.h>
@@ -574,21 +575,55 @@ static int bcm_sysport_set_wol(struct net_device *dev,
574
575
return 0 ;
575
576
}
576
577
578
+ static void bcm_sysport_set_rx_coalesce (struct bcm_sysport_priv * priv )
579
+ {
580
+ u32 reg ;
581
+
582
+ reg = rdma_readl (priv , RDMA_MBDONE_INTR );
583
+ reg &= ~(RDMA_INTR_THRESH_MASK |
584
+ RDMA_TIMEOUT_MASK << RDMA_TIMEOUT_SHIFT );
585
+ reg |= priv -> dim .coal_pkts ;
586
+ reg |= DIV_ROUND_UP (priv -> dim .coal_usecs * 1000 , 8192 ) <<
587
+ RDMA_TIMEOUT_SHIFT ;
588
+ rdma_writel (priv , reg , RDMA_MBDONE_INTR );
589
+ }
590
+
591
+ static void bcm_sysport_set_tx_coalesce (struct bcm_sysport_tx_ring * ring )
592
+ {
593
+ struct bcm_sysport_priv * priv = ring -> priv ;
594
+ u32 reg ;
595
+
596
+ reg = tdma_readl (priv , TDMA_DESC_RING_INTR_CONTROL (ring -> index ));
597
+ reg &= ~(RING_INTR_THRESH_MASK |
598
+ RING_TIMEOUT_MASK << RING_TIMEOUT_SHIFT );
599
+ reg |= ring -> dim .coal_pkts ;
600
+ reg |= DIV_ROUND_UP (ring -> dim .coal_usecs * 1000 , 8192 ) <<
601
+ RING_TIMEOUT_SHIFT ;
602
+ tdma_writel (priv , reg , TDMA_DESC_RING_INTR_CONTROL (ring -> index ));
603
+ }
604
+
577
605
static int bcm_sysport_get_coalesce (struct net_device * dev ,
578
606
struct ethtool_coalesce * ec )
579
607
{
580
608
struct bcm_sysport_priv * priv = netdev_priv (dev );
609
+ struct bcm_sysport_tx_ring * ring ;
610
+ unsigned int i ;
581
611
u32 reg ;
582
612
583
613
reg = tdma_readl (priv , TDMA_DESC_RING_INTR_CONTROL (0 ));
584
614
585
615
ec -> tx_coalesce_usecs = (reg >> RING_TIMEOUT_SHIFT ) * 8192 / 1000 ;
586
616
ec -> tx_max_coalesced_frames = reg & RING_INTR_THRESH_MASK ;
617
+ for (i = 0 ; i < dev -> num_tx_queues ; i ++ ) {
618
+ ring = & priv -> tx_rings [i ];
619
+ ec -> use_adaptive_tx_coalesce |= ring -> dim .use_dim ;
620
+ }
587
621
588
622
reg = rdma_readl (priv , RDMA_MBDONE_INTR );
589
623
590
624
ec -> rx_coalesce_usecs = (reg >> RDMA_TIMEOUT_SHIFT ) * 8192 / 1000 ;
591
625
ec -> rx_max_coalesced_frames = reg & RDMA_INTR_THRESH_MASK ;
626
+ ec -> use_adaptive_rx_coalesce = priv -> dim .use_dim ;
592
627
593
628
return 0 ;
594
629
}
@@ -597,8 +632,8 @@ static int bcm_sysport_set_coalesce(struct net_device *dev,
597
632
struct ethtool_coalesce * ec )
598
633
{
599
634
struct bcm_sysport_priv * priv = netdev_priv (dev );
635
+ struct bcm_sysport_tx_ring * ring ;
600
636
unsigned int i ;
601
- u32 reg ;
602
637
603
638
/* Base system clock is 125Mhz, DMA timeout is this reference clock
604
639
* divided by 1024, which yield roughly 8.192 us, our maximum value has
@@ -615,22 +650,26 @@ static int bcm_sysport_set_coalesce(struct net_device *dev,
615
650
return - EINVAL ;
616
651
617
652
for (i = 0 ; i < dev -> num_tx_queues ; i ++ ) {
618
- reg = tdma_readl (priv , TDMA_DESC_RING_INTR_CONTROL (i ));
619
- reg &= ~(RING_INTR_THRESH_MASK |
620
- RING_TIMEOUT_MASK << RING_TIMEOUT_SHIFT );
621
- reg |= ec -> tx_max_coalesced_frames ;
622
- reg |= DIV_ROUND_UP (ec -> tx_coalesce_usecs * 1000 , 8192 ) <<
623
- RING_TIMEOUT_SHIFT ;
624
- tdma_writel (priv , reg , TDMA_DESC_RING_INTR_CONTROL (i ));
653
+ ring = & priv -> tx_rings [i ];
654
+ ring -> dim .coal_pkts = ec -> tx_max_coalesced_frames ;
655
+ ring -> dim .coal_usecs = ec -> tx_coalesce_usecs ;
656
+ if (!ec -> use_adaptive_tx_coalesce && ring -> dim .use_dim ) {
657
+ ring -> dim .coal_pkts = 1 ;
658
+ ring -> dim .coal_usecs = 0 ;
659
+ }
660
+ ring -> dim .use_dim = ec -> use_adaptive_tx_coalesce ;
661
+ bcm_sysport_set_tx_coalesce (ring );
625
662
}
626
663
627
- reg = rdma_readl (priv , RDMA_MBDONE_INTR );
628
- reg &= ~(RDMA_INTR_THRESH_MASK |
629
- RDMA_TIMEOUT_MASK << RDMA_TIMEOUT_SHIFT );
630
- reg |= ec -> rx_max_coalesced_frames ;
631
- reg |= DIV_ROUND_UP (ec -> rx_coalesce_usecs * 1000 , 8192 ) <<
632
- RDMA_TIMEOUT_SHIFT ;
633
- rdma_writel (priv , reg , RDMA_MBDONE_INTR );
664
+ priv -> dim .coal_usecs = ec -> rx_coalesce_usecs ;
665
+ priv -> dim .coal_pkts = ec -> rx_max_coalesced_frames ;
666
+
667
+ if (!ec -> use_adaptive_rx_coalesce && priv -> dim .use_dim ) {
668
+ priv -> dim .coal_pkts = 1 ;
669
+ priv -> dim .coal_usecs = 0 ;
670
+ }
671
+ priv -> dim .use_dim = ec -> use_adaptive_rx_coalesce ;
672
+ bcm_sysport_set_rx_coalesce (priv );
634
673
635
674
return 0 ;
636
675
}
@@ -709,6 +748,7 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
709
748
struct bcm_sysport_stats64 * stats64 = & priv -> stats64 ;
710
749
struct net_device * ndev = priv -> netdev ;
711
750
unsigned int processed = 0 , to_process ;
751
+ unsigned int processed_bytes = 0 ;
712
752
struct bcm_sysport_cb * cb ;
713
753
struct sk_buff * skb ;
714
754
unsigned int p_index ;
@@ -800,6 +840,7 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
800
840
*/
801
841
skb_pull (skb , sizeof (* rsb ) + 2 );
802
842
len -= (sizeof (* rsb ) + 2 );
843
+ processed_bytes += len ;
803
844
804
845
/* UniMAC may forward CRC */
805
846
if (priv -> crc_fwd ) {
@@ -824,6 +865,9 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
824
865
priv -> rx_read_ptr = 0 ;
825
866
}
826
867
868
+ priv -> dim .packets = processed ;
869
+ priv -> dim .bytes = processed_bytes ;
870
+
827
871
return processed ;
828
872
}
829
873
@@ -896,6 +940,8 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
896
940
ring -> packets += pkts_compl ;
897
941
ring -> bytes += bytes_compl ;
898
942
u64_stats_update_end (& priv -> syncp );
943
+ ring -> dim .packets = pkts_compl ;
944
+ ring -> dim .bytes = bytes_compl ;
899
945
900
946
ring -> c_index = c_index ;
901
947
@@ -941,6 +987,7 @@ static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget)
941
987
{
942
988
struct bcm_sysport_tx_ring * ring =
943
989
container_of (napi , struct bcm_sysport_tx_ring , napi );
990
+ struct net_dim_sample dim_sample ;
944
991
unsigned int work_done = 0 ;
945
992
946
993
work_done = bcm_sysport_tx_reclaim (ring -> priv , ring );
@@ -957,6 +1004,12 @@ static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget)
957
1004
return 0 ;
958
1005
}
959
1006
1007
+ if (ring -> dim .use_dim ) {
1008
+ net_dim_sample (ring -> dim .event_ctr , ring -> dim .packets ,
1009
+ ring -> dim .bytes , & dim_sample );
1010
+ net_dim (& ring -> dim .dim , dim_sample );
1011
+ }
1012
+
960
1013
return budget ;
961
1014
}
962
1015
@@ -972,6 +1025,7 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget)
972
1025
{
973
1026
struct bcm_sysport_priv * priv =
974
1027
container_of (napi , struct bcm_sysport_priv , napi );
1028
+ struct net_dim_sample dim_sample ;
975
1029
unsigned int work_done = 0 ;
976
1030
977
1031
work_done = bcm_sysport_desc_rx (priv , budget );
@@ -994,6 +1048,12 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget)
994
1048
intrl2_0_mask_clear (priv , INTRL2_0_RDMA_MBDONE );
995
1049
}
996
1050
1051
+ if (priv -> dim .use_dim ) {
1052
+ net_dim_sample (priv -> dim .event_ctr , priv -> dim .packets ,
1053
+ priv -> dim .bytes , & dim_sample );
1054
+ net_dim (& priv -> dim .dim , dim_sample );
1055
+ }
1056
+
997
1057
return work_done ;
998
1058
}
999
1059
@@ -1012,6 +1072,40 @@ static void bcm_sysport_resume_from_wol(struct bcm_sysport_priv *priv)
1012
1072
netif_dbg (priv , wol , priv -> netdev , "resumed from WOL\n" );
1013
1073
}
1014
1074
1075
+ static void bcm_sysport_dim_work (struct work_struct * work )
1076
+ {
1077
+ struct net_dim * dim = container_of (work , struct net_dim , work );
1078
+ struct bcm_sysport_net_dim * ndim =
1079
+ container_of (dim , struct bcm_sysport_net_dim , dim );
1080
+ struct bcm_sysport_priv * priv =
1081
+ container_of (ndim , struct bcm_sysport_priv , dim );
1082
+ struct net_dim_cq_moder cur_profile =
1083
+ net_dim_get_profile (dim -> mode , dim -> profile_ix );
1084
+
1085
+ priv -> dim .coal_usecs = cur_profile .usec ;
1086
+ priv -> dim .coal_pkts = cur_profile .pkts ;
1087
+
1088
+ bcm_sysport_set_rx_coalesce (priv );
1089
+ dim -> state = NET_DIM_START_MEASURE ;
1090
+ }
1091
+
1092
+ static void bcm_sysport_dim_tx_work (struct work_struct * work )
1093
+ {
1094
+ struct net_dim * dim = container_of (work , struct net_dim , work );
1095
+ struct bcm_sysport_net_dim * ndim =
1096
+ container_of (dim , struct bcm_sysport_net_dim , dim );
1097
+ struct bcm_sysport_tx_ring * ring =
1098
+ container_of (ndim , struct bcm_sysport_tx_ring , dim );
1099
+ struct net_dim_cq_moder cur_profile =
1100
+ net_dim_get_profile (dim -> mode , dim -> profile_ix );
1101
+
1102
+ ring -> dim .coal_usecs = cur_profile .usec ;
1103
+ ring -> dim .coal_pkts = cur_profile .pkts ;
1104
+
1105
+ bcm_sysport_set_tx_coalesce (ring );
1106
+ dim -> state = NET_DIM_START_MEASURE ;
1107
+ }
1108
+
1015
1109
/* RX and misc interrupt routine */
1016
1110
static irqreturn_t bcm_sysport_rx_isr (int irq , void * dev_id )
1017
1111
{
@@ -1030,6 +1124,7 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
1030
1124
}
1031
1125
1032
1126
if (priv -> irq0_stat & INTRL2_0_RDMA_MBDONE ) {
1127
+ priv -> dim .event_ctr ++ ;
1033
1128
if (likely (napi_schedule_prep (& priv -> napi ))) {
1034
1129
/* disable RX interrupts */
1035
1130
intrl2_0_mask_set (priv , INTRL2_0_RDMA_MBDONE );
@@ -1057,6 +1152,7 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
1057
1152
continue ;
1058
1153
1059
1154
txr = & priv -> tx_rings [ring ];
1155
+ txr -> dim .event_ctr ++ ;
1060
1156
1061
1157
if (likely (napi_schedule_prep (& txr -> napi ))) {
1062
1158
intrl2_0_mask_set (priv , ring_bit );
@@ -1089,6 +1185,7 @@ static irqreturn_t bcm_sysport_tx_isr(int irq, void *dev_id)
1089
1185
continue ;
1090
1186
1091
1187
txr = & priv -> tx_rings [ring ];
1188
+ txr -> dim .event_ctr ++ ;
1092
1189
1093
1190
if (likely (napi_schedule_prep (& txr -> napi ))) {
1094
1191
intrl2_1_mask_set (priv , BIT (ring ));
@@ -1354,6 +1451,16 @@ static void bcm_sysport_adj_link(struct net_device *dev)
1354
1451
phy_print_status (phydev );
1355
1452
}
1356
1453
1454
+ static void bcm_sysport_init_dim (struct bcm_sysport_net_dim * dim ,
1455
+ void (* cb )(struct work_struct * work ))
1456
+ {
1457
+ INIT_WORK (& dim -> dim .work , cb );
1458
+ dim -> dim .mode = NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE ;
1459
+ dim -> event_ctr = 0 ;
1460
+ dim -> packets = 0 ;
1461
+ dim -> bytes = 0 ;
1462
+ }
1463
+
1357
1464
static int bcm_sysport_init_tx_ring (struct bcm_sysport_priv * priv ,
1358
1465
unsigned int index )
1359
1466
{
@@ -1444,6 +1551,7 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
1444
1551
reg |= (1 << index );
1445
1552
tdma_writel (priv , reg , TDMA_TIER1_ARB_0_QUEUE_EN );
1446
1553
1554
+ bcm_sysport_init_dim (& ring -> dim , bcm_sysport_dim_tx_work );
1447
1555
napi_enable (& ring -> napi );
1448
1556
1449
1557
netif_dbg (priv , hw , priv -> netdev ,
@@ -1474,6 +1582,7 @@ static void bcm_sysport_fini_tx_ring(struct bcm_sysport_priv *priv,
1474
1582
return ;
1475
1583
1476
1584
napi_disable (& ring -> napi );
1585
+ cancel_work_sync (& ring -> dim .dim .work );
1477
1586
netif_napi_del (& ring -> napi );
1478
1587
1479
1588
bcm_sysport_tx_clean (priv , ring );
@@ -1763,6 +1872,7 @@ static void bcm_sysport_netif_start(struct net_device *dev)
1763
1872
struct bcm_sysport_priv * priv = netdev_priv (dev );
1764
1873
1765
1874
/* Enable NAPI */
1875
+ bcm_sysport_init_dim (& priv -> dim , bcm_sysport_dim_work );
1766
1876
napi_enable (& priv -> napi );
1767
1877
1768
1878
/* Enable RX interrupt and TX ring full interrupt */
@@ -1948,6 +2058,7 @@ static void bcm_sysport_netif_stop(struct net_device *dev)
1948
2058
/* stop all software from updating hardware */
1949
2059
netif_tx_stop_all_queues (dev );
1950
2060
napi_disable (& priv -> napi );
2061
+ cancel_work_sync (& priv -> dim .dim .work );
1951
2062
phy_stop (dev -> phydev );
1952
2063
1953
2064
/* mask all interrupts */
0 commit comments