aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReece R. Pollack2014-08-28 14:38:09 -0500
committerMurali Karicheri2014-12-03 10:30:14 -0600
commit35cb68ef2ee637096bc3ed341049302ff9088445 (patch)
tree1ad7bde53c0777cfb82b942633f6eacb19118af9 /drivers/net/ethernet/ti/keystone_ethss2.c
parent7fac8a8b76657debc3a0d6c10383e9817e2cbd7b (diff)
downloadlinux-35cb68ef2ee637096bc3ed341049302ff9088445.tar.gz
linux-35cb68ef2ee637096bc3ed341049302ff9088445.tar.xz
linux-35cb68ef2ee637096bc3ed341049302ff9088445.zip
net: keystone: Fixes to CPSW statistics collection
In certain applications it's beneficial to allow the CPSW h/w stats counters to continue to increment even while the kernel polls them. This patch implements this behavior for both the ethss and ethss2 modules. Along the way, some bugs were discovered and fixed: In both modules, the timer routine synchronized against the ethtool- triggered updates with spin_lock_bh(). A timer function is itself a bottom-half, so this should be spin_lock(). Both modules accessed device statistics registers by dereferencing a pointer rather than using the more appropriate macro readl_relaxed(). In ethss2, the hw_stats array was undersized: 72 vs 378. This caused data following the hw_stats array to be overwritten. Also, the macro ETHTOOL_STATS_NUM calculated (42 * 8 + 1) rather than (42 * (8 + 1)) due to missing parens. Signed-off-by: Reece R. Pollack <x0183204@ti.com>
Diffstat (limited to 'drivers/net/ethernet/ti/keystone_ethss2.c')
-rw-r--r--drivers/net/ethernet/ti/keystone_ethss2.c188
1 files changed, 102 insertions, 86 deletions
diff --git a/drivers/net/ethernet/ti/keystone_ethss2.c b/drivers/net/ethernet/ti/keystone_ethss2.c
index df4e21568ad..0e93f526ba3 100644
--- a/drivers/net/ethernet/ti/keystone_ethss2.c
+++ b/drivers/net/ethernet/ti/keystone_ethss2.c
@@ -394,83 +394,6 @@ struct cpsw2_ale_regs {
394 u32 thread_map; 394 u32 thread_map;
395}; 395};
396 396
397struct cpsw2_priv {
398 struct device *dev;
399 struct clk *cpgmac;
400 struct netcp_device *netcp_device;
401 u32 num_slaves;
402 u32 ale_ageout;
403 u32 ale_entries;
404 u32 ale_ports;
405 u32 sgmii_module_ofs;
406 u32 switch_module_ofs;
407 u32 host_port_reg_ofs;
408 u32 slave_reg_ofs;
409 u32 hw_stats_reg_ofs;
410 u32 ale_reg_ofs;
411 u32 cpts_reg_ofs;
412
413 int host_port;
414 u32 rx_packet_max;
415
416 struct cpsw2_regs __iomem *regs;
417 struct cpsw2_ss_regs __iomem *ss_regs;
418 struct cpsw2_hw_stats __iomem *hw_stats_regs[CPSW2_NUM_PORTS];
419 struct cpsw2_host_regs __iomem *host_port_regs;
420 struct cpsw2_ale_regs __iomem *ale_reg;
421
422 void __iomem *sgmii_port_regs;
423
424 struct cpsw_ale *ale;
425 u32 ale_refcnt;
426
427 u32 link[MAX_SLAVES];
428 struct device_node *phy_node[MAX_SLAVES];
429
430 u32 intf_tx_queues;
431
432 u32 multi_if;
433 u32 slaves_per_interface;
434 u32 num_interfaces;
435 struct device_node *interfaces;
436 struct list_head cpsw_intf_head;
437
438 u64 hw_stats[72];
439 int init_serdes_at_probe;
440 struct kobject kobj;
441 struct kobject tx_pri_kobj;
442 struct kobject pvlan_kobj;
443 struct kobject port_ts_kobj[MAX_SLAVES];
444 struct kobject stats_kobj;
445 spinlock_t hw_stats_lock;
446 struct cpts cpts;
447 int cpts_registered;
448 int force_no_hwtstamp;
449 void __iomem *serdes_regs[CPSW2_SERDES_MAX_NUM];
450 u32 num_serdes;
451 u32 serdes_lanes;
452 struct serdes serdes;
453};
454
455struct cpsw2_intf {
456 struct net_device *ndev;
457 struct device *dev;
458 struct cpsw2_priv *cpsw_priv;
459 struct device_node *phy_node;
460 u32 num_slaves;
461 u32 slave_port;
462 struct cpsw2_slave *slaves;
463 u32 intf_tx_queues;
464 const char *tx_chan_name;
465 u32 tx_queue_depth;
466 struct netcp_tx_pipe tx_pipe;
467 u32 multi_if;
468 struct list_head cpsw_intf_list;
469 struct timer_list timer;
470 u32 sgmii_link;
471 unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
472};
473
474/* 397/*
475 * Statistic management 398 * Statistic management
476 */ 399 */
@@ -913,7 +836,85 @@ static const struct netcp2_ethtool_stat et_stats[] = {
913}; 836};
914 837
915#define ETHTOOL_PORT_STATS_NUM (ARRAY_SIZE(et_stats)/CPSW2_NUM_PORTS) 838#define ETHTOOL_PORT_STATS_NUM (ARRAY_SIZE(et_stats)/CPSW2_NUM_PORTS)
916#define ETHTOOL_STATS_NUM(num_ports) (ETHTOOL_PORT_STATS_NUM * num_ports) 839#define ETHTOOL_STATS_NUM(num_ports) (ETHTOOL_PORT_STATS_NUM * (num_ports))
840
841struct cpsw2_priv {
842 struct device *dev;
843 struct clk *cpgmac;
844 struct netcp_device *netcp_device;
845 u32 num_slaves;
846 u32 ale_ageout;
847 u32 ale_entries;
848 u32 ale_ports;
849 u32 sgmii_module_ofs;
850 u32 switch_module_ofs;
851 u32 host_port_reg_ofs;
852 u32 slave_reg_ofs;
853 u32 hw_stats_reg_ofs;
854 u32 ale_reg_ofs;
855 u32 cpts_reg_ofs;
856
857 int host_port;
858 u32 rx_packet_max;
859
860 struct cpsw2_regs __iomem *regs;
861 struct cpsw2_ss_regs __iomem *ss_regs;
862 struct cpsw2_hw_stats __iomem *hw_stats_regs[CPSW2_NUM_PORTS];
863 struct cpsw2_host_regs __iomem *host_port_regs;
864 struct cpsw2_ale_regs __iomem *ale_reg;
865
866 void __iomem *sgmii_port_regs;
867
868 struct cpsw_ale *ale;
869 u32 ale_refcnt;
870
871 u32 link[MAX_SLAVES];
872 struct device_node *phy_node[MAX_SLAVES];
873
874 u32 intf_tx_queues;
875
876 u32 multi_if;
877 u32 slaves_per_interface;
878 u32 num_interfaces;
879 struct device_node *interfaces;
880 struct list_head cpsw_intf_head;
881
882 u64 hw_stats[ARRAY_SIZE(et_stats)];
883 u32 hw_stats_prev[ARRAY_SIZE(et_stats)];
884 int init_serdes_at_probe;
885 struct kobject kobj;
886 struct kobject tx_pri_kobj;
887 struct kobject pvlan_kobj;
888 struct kobject port_ts_kobj[MAX_SLAVES];
889 struct kobject stats_kobj;
890 spinlock_t hw_stats_lock;
891 struct cpts cpts;
892 int cpts_registered;
893 int force_no_hwtstamp;
894 void __iomem *serdes_regs[CPSW2_SERDES_MAX_NUM];
895 u32 num_serdes;
896 u32 serdes_lanes;
897 struct serdes serdes;
898};
899
900struct cpsw2_intf {
901 struct net_device *ndev;
902 struct device *dev;
903 struct cpsw2_priv *cpsw_priv;
904 struct device_node *phy_node;
905 u32 num_slaves;
906 u32 slave_port;
907 struct cpsw2_slave *slaves;
908 u32 intf_tx_queues;
909 const char *tx_chan_name;
910 u32 tx_queue_depth;
911 struct netcp_tx_pipe tx_pipe;
912 u32 multi_if;
913 struct list_head cpsw_intf_list;
914 struct timer_list timer;
915 u32 sgmii_link;
916 unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
917};
917 918
918struct cpsw2_attribute { 919struct cpsw2_attribute {
919 struct attribute attr; 920 struct attribute attr;
@@ -2097,7 +2098,7 @@ static void cpsw2_reset_mod_stats(struct cpsw2_priv *cpsw_dev, int stat_mod)
2097 if (et_stats[i].type == stat_mod) { 2098 if (et_stats[i].type == stat_mod) {
2098 cpsw_dev->hw_stats[i] = 0; 2099 cpsw_dev->hw_stats[i] = 0;
2099 p = base + et_stats[i].offset; 2100 p = base + et_stats[i].offset;
2100 *p = 0xffffffff; 2101 cpsw_dev->hw_stats_prev[i] = readl_relaxed(p);
2101 } 2102 }
2102 } 2103 }
2103 return; 2104 return;
@@ -2297,17 +2298,19 @@ static void cpsw2_update_stats(struct cpsw2_priv *cpsw_dev, uint64_t *data)
2297{ 2298{
2298 void __iomem *base = NULL; 2299 void __iomem *base = NULL;
2299 u32 __iomem *p; 2300 u32 __iomem *p;
2300 u32 tmp = 0; 2301 u32 curr, delta;
2301 int i; 2302 int i;
2302 2303
2303 for (i = 0; i < ETHTOOL_STATS_NUM(cpsw_dev->num_slaves + 1); i++) { 2304 for (i = 0; i < ETHTOOL_STATS_NUM(cpsw_dev->num_slaves + 1); i++) {
2304 base = cpsw_dev->hw_stats_regs[et_stats[i].type]; 2305 base = cpsw_dev->hw_stats_regs[et_stats[i].type];
2305 p = base + et_stats[i].offset; 2306 p = base + et_stats[i].offset;
2306 tmp = *p; 2307 curr = readl_relaxed(p);
2307 cpsw_dev->hw_stats[i] = cpsw_dev->hw_stats[i] + tmp; 2308 delta = curr - cpsw_dev->hw_stats_prev[i];
2309 cpsw_dev->hw_stats_prev[i] = curr;
2310 cpsw_dev->hw_stats[i] += delta;
2311
2308 if (data) 2312 if (data)
2309 data[i] = cpsw_dev->hw_stats[i]; 2313 data[i] = cpsw_dev->hw_stats[i];
2310 *p = tmp;
2311 } 2314 }
2312 2315
2313 return; 2316 return;
@@ -3053,9 +3056,10 @@ static void cpsw2_timer(unsigned long arg)
3053 netif_carrier_off(cpsw_intf->ndev); 3056 netif_carrier_off(cpsw_intf->ndev);
3054 } 3057 }
3055 3058
3056 spin_lock_bh(&cpsw_dev->hw_stats_lock); 3059 /* A timer runs as a BH, no need to block them */
3060 spin_lock(&cpsw_dev->hw_stats_lock);
3057 cpsw2_update_stats(cpsw_dev, NULL); 3061 cpsw2_update_stats(cpsw_dev, NULL);
3058 spin_unlock_bh(&cpsw_dev->hw_stats_lock); 3062 spin_unlock(&cpsw_dev->hw_stats_lock);
3059 3063
3060 cpsw_intf->timer.expires = jiffies + (HZ/10); 3064 cpsw_intf->timer.expires = jiffies + (HZ/10);
3061 add_timer(&cpsw_intf->timer); 3065 add_timer(&cpsw_intf->timer);
@@ -3913,8 +3917,20 @@ static int cpsw2_probe(struct netcp_device *netcp_device,
3913 netcp_create_interface(netcp_device, &ndev, 3917 netcp_create_interface(netcp_device, &ndev,
3914 NULL, cpsw_dev->intf_tx_queues, 3918 NULL, cpsw_dev->intf_tx_queues,
3915 1, 0); 3919 1, 0);
3916 /* init the hw stats lock */ 3920
3921 /* init the hw stats */
3917 spin_lock_init(&cpsw_dev->hw_stats_lock); 3922 spin_lock_init(&cpsw_dev->hw_stats_lock);
3923 spin_lock_bh(&cpsw_dev->hw_stats_lock);
3924 cpsw2_reset_mod_stats(cpsw_dev, CPSW2_STATS0_MODULE);
3925 cpsw2_reset_mod_stats(cpsw_dev, CPSW2_STATS1_MODULE);
3926 cpsw2_reset_mod_stats(cpsw_dev, CPSW2_STATS2_MODULE);
3927 cpsw2_reset_mod_stats(cpsw_dev, CPSW2_STATS3_MODULE);
3928 cpsw2_reset_mod_stats(cpsw_dev, CPSW2_STATS4_MODULE);
3929 cpsw2_reset_mod_stats(cpsw_dev, CPSW2_STATS5_MODULE);
3930 cpsw2_reset_mod_stats(cpsw_dev, CPSW2_STATS6_MODULE);
3931 cpsw2_reset_mod_stats(cpsw_dev, CPSW2_STATS7_MODULE);
3932 cpsw2_reset_mod_stats(cpsw_dev, CPSW2_STATS8_MODULE);
3933 spin_unlock_bh(&cpsw_dev->hw_stats_lock);
3918 3934
3919 ret = cpsw2_create_sysfs_entries(cpsw_dev); 3935 ret = cpsw2_create_sysfs_entries(cpsw_dev);
3920 if (ret) 3936 if (ret)