Both PSFP stats and the port stats read by ocelot_check_stats_work() are indirectly read through the same mechanism - write to STAT_CFG:STAT_VIEW, read from SYS:STAT:CNT[n]. It's just that for port stats, we write STAT_VIEW with the index of the port, and for PSFP stats, we write STAT_VIEW with the filter index. So if we allow them to run concurrently, ocelot_check_stats_work() may change the view from vsc9959_psfp_counters_get(), and vice versa.
Unified · Split
| @@ -1886,6 +1886,8 @@ static void vsc9959_psfp_sgi_table_del(struct ocelot *ocelot, · 1885 unmodified lines | |||
| 1886 | static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index, | 1886 | static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index, |
| 1887 | struct felix_stream_filter_counters *counters) | 1887 | struct felix_stream_filter_counters *counters) |
| 1888 | { | 1888 | { |
| 1889 | mutex_lock(&ocelot->stats_lock); | ||
| 1890 | |||
| 1889 | ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(index), | 1891 | ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(index), |
| 1890 | SYS_STAT_CFG_STAT_VIEW_M, | 1892 | SYS_STAT_CFG_STAT_VIEW_M, |
| 1891 | SYS_STAT_CFG); | 1893 | SYS_STAT_CFG); |
| @@ -1900,6 +1902,8 @@ static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index, · 8 unmodified lines | |||
| 1900 | SYS_STAT_CFG_STAT_VIEW(index) | | 1902 | SYS_STAT_CFG_STAT_VIEW(index) | |
| 1901 | SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10), | 1903 | SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10), |
| 1902 | SYS_STAT_CFG); | 1904 | SYS_STAT_CFG); |
| 1905 | |||
| 1906 | mutex_unlock(&ocelot->stats_lock); | ||
| 1903 | } | 1907 | } |
| 1904 | 1908 | ||
| 1905 | static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port, | 1909 | static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port, |