ocelot.c (25027c8409b4541611d0060077607d8ca70740df) | ocelot.c (fe90104cd6048364db821c06bcb2246074919c04) |
---|---|
1// SPDX-License-Identifier: (GPL-2.0 OR MIT) 2/* 3 * Microsemi Ocelot Switch driver 4 * 5 * Copyright (c) 2017 Microsemi Corporation 6 */ 7#include <linux/dsa/ocelot.h> 8#include <linux/if_bridge.h> --- 1839 unchanged lines hidden (view full) --- 1848 /* Commit back the result & save it */ 1849 memcpy(&ocelot->hwtstamp_config, &cfg, sizeof(cfg)); 1850 mutex_unlock(&ocelot->ptp_lock); 1851 1852 return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; 1853} 1854EXPORT_SYMBOL(ocelot_hwstamp_set); 1855 | 1// SPDX-License-Identifier: (GPL-2.0 OR MIT) 2/* 3 * Microsemi Ocelot Switch driver 4 * 5 * Copyright (c) 2017 Microsemi Corporation 6 */ 7#include <linux/dsa/ocelot.h> 8#include <linux/if_bridge.h> --- 1839 unchanged lines hidden (view full) --- 1848 /* Commit back the result & save it */ 1849 memcpy(&ocelot->hwtstamp_config, &cfg, sizeof(cfg)); 1850 mutex_unlock(&ocelot->ptp_lock); 1851 1852 return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; 1853} 1854EXPORT_SYMBOL(ocelot_hwstamp_set); 1855 |
1856void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data) 1857{ 1858 int i; 1859 1860 if (sset != ETH_SS_STATS) 1861 return; 1862 1863 for (i = 0; i < OCELOT_NUM_STATS; i++) { 1864 if (ocelot->stats_layout[i].name[0] == '\0') 1865 continue; 1866 1867 memcpy(data + i * ETH_GSTRING_LEN, ocelot->stats_layout[i].name, 1868 ETH_GSTRING_LEN); 1869 } 1870} 1871EXPORT_SYMBOL(ocelot_get_strings); 1872 1873/* Read the counters from hardware and keep them in region->buf. 1874 * Caller must hold &ocelot->stat_view_lock. 1875 */ 1876static int ocelot_port_update_stats(struct ocelot *ocelot, int port) 1877{ 1878 struct ocelot_stats_region *region; 1879 int err; 1880 1881 /* Configure the port to read the stats from */ 1882 ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port), SYS_STAT_CFG); 1883 1884 list_for_each_entry(region, &ocelot->stats_regions, node) { 1885 err = ocelot_bulk_read(ocelot, region->base, region->buf, 1886 region->count); 1887 if (err) 1888 return err; 1889 } 1890 1891 return 0; 1892} 1893 1894/* Transfer the counters from region->buf to ocelot->stats. 1895 * Caller must hold &ocelot->stat_view_lock and &ocelot->stats_lock. 1896 */ 1897static void ocelot_port_transfer_stats(struct ocelot *ocelot, int port) 1898{ 1899 unsigned int idx = port * OCELOT_NUM_STATS; 1900 struct ocelot_stats_region *region; 1901 int j; 1902 1903 list_for_each_entry(region, &ocelot->stats_regions, node) { 1904 for (j = 0; j < region->count; j++) { 1905 u64 *stat = &ocelot->stats[idx + j]; 1906 u64 val = region->buf[j]; 1907 1908 if (val < (*stat & U32_MAX)) 1909 *stat += (u64)1 << 32; 1910 1911 *stat = (*stat & ~(u64)U32_MAX) + val; 1912 } 1913 1914 idx += region->count; 1915 } 1916} 1917 1918static void ocelot_check_stats_work(struct work_struct *work) 1919{ 1920 struct delayed_work *del_work = to_delayed_work(work); 1921 struct ocelot *ocelot = container_of(del_work, struct ocelot, 1922 stats_work); 1923 int port, err; 1924 1925 mutex_lock(&ocelot->stat_view_lock); 1926 1927 for (port = 0; port < ocelot->num_phys_ports; port++) { 1928 err = ocelot_port_update_stats(ocelot, port); 1929 if (err) 1930 break; 1931 1932 spin_lock(&ocelot->stats_lock); 1933 ocelot_port_transfer_stats(ocelot, port); 1934 spin_unlock(&ocelot->stats_lock); 1935 } 1936 1937 if (!err && ocelot->ops->update_stats) 1938 ocelot->ops->update_stats(ocelot); 1939 1940 mutex_unlock(&ocelot->stat_view_lock); 1941 1942 if (err) 1943 dev_err(ocelot->dev, "Error %d updating ethtool stats\n", err); 1944 1945 queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work, 1946 OCELOT_STATS_CHECK_DELAY); 1947} 1948 1949void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data) 1950{ 1951 int i, err; 1952 1953 mutex_lock(&ocelot->stat_view_lock); 1954 1955 /* check and update now */ 1956 err = ocelot_port_update_stats(ocelot, port); 1957 1958 spin_lock(&ocelot->stats_lock); 1959 1960 ocelot_port_transfer_stats(ocelot, port); 1961 1962 /* Copy all supported counters */ 1963 for (i = 0; i < OCELOT_NUM_STATS; i++) { 1964 int index = port * OCELOT_NUM_STATS + i; 1965 1966 if (ocelot->stats_layout[i].name[0] == '\0') 1967 continue; 1968 1969 *data++ = ocelot->stats[index]; 1970 } 1971 1972 spin_unlock(&ocelot->stats_lock); 1973 1974 mutex_unlock(&ocelot->stat_view_lock); 1975 1976 if (err) 1977 dev_err(ocelot->dev, "Error %d updating ethtool stats\n", err); 1978} 1979EXPORT_SYMBOL(ocelot_get_ethtool_stats); 1980 1981int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset) 1982{ 1983 int i, num_stats = 0; 1984 1985 if (sset != ETH_SS_STATS) 1986 return -EOPNOTSUPP; 1987 1988 for (i = 0; i < OCELOT_NUM_STATS; i++) 1989 if (ocelot->stats_layout[i].name[0] != '\0') 1990 num_stats++; 1991 1992 return num_stats; 1993} 1994EXPORT_SYMBOL(ocelot_get_sset_count); 1995 1996static int ocelot_prepare_stats_regions(struct ocelot *ocelot) 1997{ 1998 struct ocelot_stats_region *region = NULL; 1999 unsigned int last; 2000 int i; 2001 2002 INIT_LIST_HEAD(&ocelot->stats_regions); 2003 2004 for (i = 0; i < OCELOT_NUM_STATS; i++) { 2005 if (ocelot->stats_layout[i].name[0] == '\0') 2006 continue; 2007 2008 if (region && ocelot->stats_layout[i].reg == last + 4) { 2009 region->count++; 2010 } else { 2011 region = devm_kzalloc(ocelot->dev, sizeof(*region), 2012 GFP_KERNEL); 2013 if (!region) 2014 return -ENOMEM; 2015 2016 region->base = ocelot->stats_layout[i].reg; 2017 region->count = 1; 2018 list_add_tail(®ion->node, &ocelot->stats_regions); 2019 } 2020 2021 last = ocelot->stats_layout[i].reg; 2022 } 2023 2024 list_for_each_entry(region, &ocelot->stats_regions, node) { 2025 region->buf = devm_kcalloc(ocelot->dev, region->count, 2026 sizeof(*region->buf), GFP_KERNEL); 2027 if (!region->buf) 2028 return -ENOMEM; 2029 } 2030 2031 return 0; 2032} 2033 | |
2034int ocelot_get_ts_info(struct ocelot *ocelot, int port, 2035 struct ethtool_ts_info *info) 2036{ 2037 info->phc_index = ocelot->ptp_clock ? 2038 ptp_clock_index(ocelot->ptp_clock) : -1; 2039 if (info->phc_index == -1) { 2040 info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE | 2041 SOF_TIMESTAMPING_RX_SOFTWARE | --- 1358 unchanged lines hidden (view full) --- 3400 ocelot->packet_buffer_size = 240 * SYS_MMGT_FREECNT(mmgt); 3401 3402 eq_ctrl = ocelot_read(ocelot, QSYS_EQ_CTRL); 3403 ocelot->num_frame_refs = QSYS_MMGT_EQ_CTRL_FP_FREE_CNT(eq_ctrl); 3404} 3405 3406int ocelot_init(struct ocelot *ocelot) 3407{ | 1856int ocelot_get_ts_info(struct ocelot *ocelot, int port, 1857 struct ethtool_ts_info *info) 1858{ 1859 info->phc_index = ocelot->ptp_clock ? 1860 ptp_clock_index(ocelot->ptp_clock) : -1; 1861 if (info->phc_index == -1) { 1862 info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE | 1863 SOF_TIMESTAMPING_RX_SOFTWARE | --- 1358 unchanged lines hidden (view full) --- 3222 ocelot->packet_buffer_size = 240 * SYS_MMGT_FREECNT(mmgt); 3223 3224 eq_ctrl = ocelot_read(ocelot, QSYS_EQ_CTRL); 3225 ocelot->num_frame_refs = QSYS_MMGT_EQ_CTRL_FP_FREE_CNT(eq_ctrl); 3226} 3227 3228int ocelot_init(struct ocelot *ocelot) 3229{ |
3408 char queue_name[32]; | |
3409 int i, ret; 3410 u32 port; 3411 3412 if (ocelot->ops->reset) { 3413 ret = ocelot->ops->reset(ocelot); 3414 if (ret) { 3415 dev_err(ocelot->dev, "Switch reset failed\n"); 3416 return ret; 3417 } 3418 } 3419 | 3230 int i, ret; 3231 u32 port; 3232 3233 if (ocelot->ops->reset) { 3234 ret = ocelot->ops->reset(ocelot); 3235 if (ret) { 3236 dev_err(ocelot->dev, "Switch reset failed\n"); 3237 return ret; 3238 } 3239 } 3240 |
3420 ocelot->stats = devm_kcalloc(ocelot->dev, 3421 ocelot->num_phys_ports * OCELOT_NUM_STATS, 3422 sizeof(u64), GFP_KERNEL); 3423 if (!ocelot->stats) 3424 return -ENOMEM; 3425 3426 spin_lock_init(&ocelot->stats_lock); 3427 mutex_init(&ocelot->stat_view_lock); | |
3428 mutex_init(&ocelot->ptp_lock); 3429 mutex_init(&ocelot->mact_lock); 3430 mutex_init(&ocelot->fwd_domain_lock); 3431 mutex_init(&ocelot->tas_lock); 3432 spin_lock_init(&ocelot->ptp_clock_lock); 3433 spin_lock_init(&ocelot->ts_id_lock); | 3241 mutex_init(&ocelot->ptp_lock); 3242 mutex_init(&ocelot->mact_lock); 3243 mutex_init(&ocelot->fwd_domain_lock); 3244 mutex_init(&ocelot->tas_lock); 3245 spin_lock_init(&ocelot->ptp_clock_lock); 3246 spin_lock_init(&ocelot->ts_id_lock); |
3434 snprintf(queue_name, sizeof(queue_name), "%s-stats", 3435 dev_name(ocelot->dev)); 3436 ocelot->stats_queue = create_singlethread_workqueue(queue_name); 3437 if (!ocelot->stats_queue) 3438 return -ENOMEM; | |
3439 3440 ocelot->owq = alloc_ordered_workqueue("ocelot-owq", 0); | 3247 3248 ocelot->owq = alloc_ordered_workqueue("ocelot-owq", 0); |
3441 if (!ocelot->owq) { 3442 destroy_workqueue(ocelot->stats_queue); | 3249 if (!ocelot->owq) |
3443 return -ENOMEM; | 3250 return -ENOMEM; |
3251 3252 ret = ocelot_stats_init(ocelot); 3253 if (ret) { 3254 destroy_workqueue(ocelot->owq); 3255 return ret; |
|
3444 } 3445 3446 INIT_LIST_HEAD(&ocelot->multicast); 3447 INIT_LIST_HEAD(&ocelot->pgids); 3448 INIT_LIST_HEAD(&ocelot->vlans); 3449 INIT_LIST_HEAD(&ocelot->lag_fdbs); 3450 ocelot_detect_features(ocelot); 3451 ocelot_mact_init(ocelot); --- 95 unchanged lines hidden (view full) --- 3547 ANA_CPUQ_CFG_CPUQ_IPMC_CTRL(6) | 3548 ANA_CPUQ_CFG_CPUQ_IGMP(6) | 3549 ANA_CPUQ_CFG_CPUQ_MLD(6), ANA_CPUQ_CFG); 3550 for (i = 0; i < 16; i++) 3551 ocelot_write_rix(ocelot, ANA_CPUQ_8021_CFG_CPUQ_GARP_VAL(6) | 3552 ANA_CPUQ_8021_CFG_CPUQ_BPDU_VAL(6), 3553 ANA_CPUQ_8021_CFG, i); 3554 | 3256 } 3257 3258 INIT_LIST_HEAD(&ocelot->multicast); 3259 INIT_LIST_HEAD(&ocelot->pgids); 3260 INIT_LIST_HEAD(&ocelot->vlans); 3261 INIT_LIST_HEAD(&ocelot->lag_fdbs); 3262 ocelot_detect_features(ocelot); 3263 ocelot_mact_init(ocelot); --- 95 unchanged lines hidden (view full) --- 3359 ANA_CPUQ_CFG_CPUQ_IPMC_CTRL(6) | 3360 ANA_CPUQ_CFG_CPUQ_IGMP(6) | 3361 ANA_CPUQ_CFG_CPUQ_MLD(6), ANA_CPUQ_CFG); 3362 for (i = 0; i < 16; i++) 3363 ocelot_write_rix(ocelot, ANA_CPUQ_8021_CFG_CPUQ_GARP_VAL(6) | 3364 ANA_CPUQ_8021_CFG_CPUQ_BPDU_VAL(6), 3365 ANA_CPUQ_8021_CFG, i); 3366 |
3555 ret = ocelot_prepare_stats_regions(ocelot); 3556 if (ret) { 3557 destroy_workqueue(ocelot->stats_queue); 3558 destroy_workqueue(ocelot->owq); 3559 return ret; 3560 } 3561 3562 INIT_DELAYED_WORK(&ocelot->stats_work, ocelot_check_stats_work); 3563 queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work, 3564 OCELOT_STATS_CHECK_DELAY); 3565 | |
3566 return 0; 3567} 3568EXPORT_SYMBOL(ocelot_init); 3569 3570void ocelot_deinit(struct ocelot *ocelot) 3571{ | 3367 return 0; 3368} 3369EXPORT_SYMBOL(ocelot_init); 3370 3371void ocelot_deinit(struct ocelot *ocelot) 3372{ |
3572 cancel_delayed_work(&ocelot->stats_work); 3573 destroy_workqueue(ocelot->stats_queue); | 3373 ocelot_stats_deinit(ocelot); |
3574 destroy_workqueue(ocelot->owq); 3575} 3576EXPORT_SYMBOL(ocelot_deinit); 3577 3578void ocelot_deinit_port(struct ocelot *ocelot, int port) 3579{ 3580 struct ocelot_port *ocelot_port = ocelot->ports[port]; 3581 3582 skb_queue_purge(&ocelot_port->tx_skbs); 3583} 3584EXPORT_SYMBOL(ocelot_deinit_port); 3585 3586MODULE_LICENSE("Dual MIT/GPL"); | 3374 destroy_workqueue(ocelot->owq); 3375} 3376EXPORT_SYMBOL(ocelot_deinit); 3377 3378void ocelot_deinit_port(struct ocelot *ocelot, int port) 3379{ 3380 struct ocelot_port *ocelot_port = ocelot->ports[port]; 3381 3382 skb_queue_purge(&ocelot_port->tx_skbs); 3383} 3384EXPORT_SYMBOL(ocelot_deinit_port); 3385 3386MODULE_LICENSE("Dual MIT/GPL"); |