Skip to content

Commit b0ec003

Browse files
Jiri Pirkodavem330
authored andcommitted
mlxsw: spectrum: Introduce port mapping change event processing
Register PMLPE trap and process the port mapping changes delivered by it by creating related ports. Note that this happens after provisioning. The INI of the linecard is processed and merged by FW. PMLPE is generated for each port. Process this mapping change. Layout of PMLPE is the same as layout of PMLP. Signed-off-by: Jiri Pirko <jiri@nvidia.com> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent adc6462 commit b0ec003

3 files changed

Lines changed: 166 additions & 9 deletions

File tree

drivers/net/ethernet/mellanox/mlxsw/spectrum.c

Lines changed: 157 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -481,21 +481,16 @@ mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port)
481481
}
482482

483483
static int
484-
mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp, u16 local_port,
485-
struct mlxsw_sp_port_mapping *port_mapping)
484+
mlxsw_sp_port_module_info_parse(struct mlxsw_sp *mlxsw_sp,
485+
u16 local_port, char *pmlp_pl,
486+
struct mlxsw_sp_port_mapping *port_mapping)
486487
{
487-
char pmlp_pl[MLXSW_REG_PMLP_LEN];
488488
bool separate_rxtx;
489489
u8 first_lane;
490490
u8 module;
491491
u8 width;
492-
int err;
493492
int i;
494493

495-
mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
496-
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl);
497-
if (err)
498-
return err;
499494
module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
500495
width = mlxsw_reg_pmlp_width_get(pmlp_pl);
501496
separate_rxtx = mlxsw_reg_pmlp_rxtx_get(pmlp_pl);
@@ -534,6 +529,21 @@ mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp, u16 local_port,
534529
return 0;
535530
}
536531

532+
static int
533+
mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp, u16 local_port,
534+
struct mlxsw_sp_port_mapping *port_mapping)
535+
{
536+
char pmlp_pl[MLXSW_REG_PMLP_LEN];
537+
int err;
538+
539+
mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
540+
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl);
541+
if (err)
542+
return err;
543+
return mlxsw_sp_port_module_info_parse(mlxsw_sp, local_port,
544+
pmlp_pl, port_mapping);
545+
}
546+
537547
static int
538548
mlxsw_sp_port_module_map(struct mlxsw_sp *mlxsw_sp, u16 local_port,
539549
const struct mlxsw_sp_port_mapping *port_mapping)
@@ -1861,13 +1871,121 @@ static bool mlxsw_sp_port_created(struct mlxsw_sp *mlxsw_sp, u16 local_port)
18611871
return mlxsw_sp->ports[local_port] != NULL;
18621872
}
18631873

1874+
static int mlxsw_sp_port_mapping_event_set(struct mlxsw_sp *mlxsw_sp,
1875+
u16 local_port, bool enable)
1876+
{
1877+
char pmecr_pl[MLXSW_REG_PMECR_LEN];
1878+
1879+
mlxsw_reg_pmecr_pack(pmecr_pl, local_port,
1880+
enable ? MLXSW_REG_PMECR_E_GENERATE_EVENT :
1881+
MLXSW_REG_PMECR_E_DO_NOT_GENERATE_EVENT);
1882+
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmecr), pmecr_pl);
1883+
}
1884+
1885+
struct mlxsw_sp_port_mapping_event {
1886+
struct list_head list;
1887+
char pmlp_pl[MLXSW_REG_PMLP_LEN];
1888+
};
1889+
1890+
static void mlxsw_sp_port_mapping_events_work(struct work_struct *work)
1891+
{
1892+
struct mlxsw_sp_port_mapping_event *event, *next_event;
1893+
struct mlxsw_sp_port_mapping_events *events;
1894+
struct mlxsw_sp_port_mapping port_mapping;
1895+
struct mlxsw_sp *mlxsw_sp;
1896+
struct devlink *devlink;
1897+
LIST_HEAD(event_queue);
1898+
u16 local_port;
1899+
int err;
1900+
1901+
events = container_of(work, struct mlxsw_sp_port_mapping_events, work);
1902+
mlxsw_sp = container_of(events, struct mlxsw_sp, port_mapping_events);
1903+
devlink = priv_to_devlink(mlxsw_sp->core);
1904+
1905+
spin_lock_bh(&events->queue_lock);
1906+
list_splice_init(&events->queue, &event_queue);
1907+
spin_unlock_bh(&events->queue_lock);
1908+
1909+
list_for_each_entry_safe(event, next_event, &event_queue, list) {
1910+
local_port = mlxsw_reg_pmlp_local_port_get(event->pmlp_pl);
1911+
err = mlxsw_sp_port_module_info_parse(mlxsw_sp, local_port,
1912+
event->pmlp_pl, &port_mapping);
1913+
if (err)
1914+
goto out;
1915+
1916+
if (WARN_ON_ONCE(!port_mapping.width))
1917+
goto out;
1918+
1919+
devl_lock(devlink);
1920+
1921+
if (!mlxsw_sp_port_created(mlxsw_sp, local_port))
1922+
mlxsw_sp_port_create(mlxsw_sp, local_port,
1923+
false, &port_mapping);
1924+
else
1925+
WARN_ON_ONCE(1);
1926+
1927+
devl_unlock(devlink);
1928+
1929+
mlxsw_sp->port_mapping[local_port] = port_mapping;
1930+
1931+
out:
1932+
kfree(event);
1933+
}
1934+
}
1935+
1936+
static void
1937+
mlxsw_sp_port_mapping_listener_func(const struct mlxsw_reg_info *reg,
1938+
char *pmlp_pl, void *priv)
1939+
{
1940+
struct mlxsw_sp_port_mapping_events *events;
1941+
struct mlxsw_sp_port_mapping_event *event;
1942+
struct mlxsw_sp *mlxsw_sp = priv;
1943+
u16 local_port;
1944+
1945+
local_port = mlxsw_reg_pmlp_local_port_get(pmlp_pl);
1946+
if (WARN_ON_ONCE(!mlxsw_sp_local_port_is_valid(mlxsw_sp, local_port)))
1947+
return;
1948+
1949+
events = &mlxsw_sp->port_mapping_events;
1950+
event = kmalloc(sizeof(*event), GFP_ATOMIC);
1951+
if (!event)
1952+
return;
1953+
memcpy(event->pmlp_pl, pmlp_pl, sizeof(event->pmlp_pl));
1954+
spin_lock(&events->queue_lock);
1955+
list_add_tail(&event->list, &events->queue);
1956+
spin_unlock(&events->queue_lock);
1957+
mlxsw_core_schedule_work(&events->work);
1958+
}
1959+
1960+
static void
1961+
__mlxsw_sp_port_mapping_events_cancel(struct mlxsw_sp *mlxsw_sp)
1962+
{
1963+
struct mlxsw_sp_port_mapping_event *event, *next_event;
1964+
struct mlxsw_sp_port_mapping_events *events;
1965+
1966+
events = &mlxsw_sp->port_mapping_events;
1967+
1968+
/* Caller needs to make sure that no new event is going to appear. */
1969+
cancel_work_sync(&events->work);
1970+
list_for_each_entry_safe(event, next_event, &events->queue, list) {
1971+
list_del(&event->list);
1972+
kfree(event);
1973+
}
1974+
}
1975+
18641976
static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp)
18651977
{
1978+
unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
18661979
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
18671980
int i;
18681981

1982+
for (i = 1; i < max_ports; i++)
1983+
mlxsw_sp_port_mapping_event_set(mlxsw_sp, i, false);
1984+
/* Make sure all scheduled events are processed */
1985+
__mlxsw_sp_port_mapping_events_cancel(mlxsw_sp);
1986+
18691987
devl_lock(devlink);
1870-
for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++)
1988+
for (i = 1; i < max_ports; i++)
18711989
if (mlxsw_sp_port_created(mlxsw_sp, i))
18721990
mlxsw_sp_port_remove(mlxsw_sp, i);
18731991
mlxsw_sp_cpu_port_remove(mlxsw_sp);
@@ -1880,6 +1998,7 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
18801998
{
18811999
unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
18822000
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
2001+
struct mlxsw_sp_port_mapping_events *events;
18832002
struct mlxsw_sp_port_mapping *port_mapping;
18842003
size_t alloc_size;
18852004
int i;
@@ -1890,6 +2009,17 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
18902009
if (!mlxsw_sp->ports)
18912010
return -ENOMEM;
18922011

2012+
events = &mlxsw_sp->port_mapping_events;
2013+
INIT_LIST_HEAD(&events->queue);
2014+
spin_lock_init(&events->queue_lock);
2015+
INIT_WORK(&events->work, mlxsw_sp_port_mapping_events_work);
2016+
2017+
for (i = 1; i < max_ports; i++) {
2018+
err = mlxsw_sp_port_mapping_event_set(mlxsw_sp, i, true);
2019+
if (err)
2020+
goto err_event_enable;
2021+
}
2022+
18932023
devl_lock(devlink);
18942024
err = mlxsw_sp_cpu_port_create(mlxsw_sp);
18952025
if (err)
@@ -1910,9 +2040,15 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
19102040
for (i--; i >= 1; i--)
19112041
if (mlxsw_sp_port_created(mlxsw_sp, i))
19122042
mlxsw_sp_port_remove(mlxsw_sp, i);
2043+
i = max_ports;
19132044
mlxsw_sp_cpu_port_remove(mlxsw_sp);
19142045
err_cpu_port_create:
19152046
devl_unlock(devlink);
2047+
err_event_enable:
2048+
for (i--; i >= 1; i--)
2049+
mlxsw_sp_port_mapping_event_set(mlxsw_sp, i, false);
2050+
/* Make sure all scheduled events are processed */
2051+
__mlxsw_sp_port_mapping_events_cancel(mlxsw_sp);
19162052
kfree(mlxsw_sp->ports);
19172053
mlxsw_sp->ports = NULL;
19182054
return err;
@@ -2074,6 +2210,7 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u16 local_port,
20742210

20752211
err_port_split_create:
20762212
mlxsw_sp_port_unsplit_create(mlxsw_sp, count, pmtdb_pl);
2213+
20772214
return err;
20782215
}
20792216

@@ -2294,6 +2431,11 @@ static const struct mlxsw_listener mlxsw_sp1_listener[] = {
22942431
MLXSW_EVENTL(mlxsw_sp1_ptp_ing_fifo_event_func, PTP_ING_FIFO, SP_PTP0),
22952432
};
22962433

2434+
static const struct mlxsw_listener mlxsw_sp2_listener[] = {
2435+
/* Events */
2436+
MLXSW_SP_EVENTL(mlxsw_sp_port_mapping_listener_func, PMLPE),
2437+
};
2438+
22972439
static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
22982440
{
22992441
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
@@ -3085,6 +3227,8 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
30853227
mlxsw_sp->trap_ops = &mlxsw_sp2_trap_ops;
30863228
mlxsw_sp->mall_ops = &mlxsw_sp2_mall_ops;
30873229
mlxsw_sp->router_ops = &mlxsw_sp2_router_ops;
3230+
mlxsw_sp->listeners = mlxsw_sp2_listener;
3231+
mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp2_listener);
30883232
mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP2;
30893233

30903234
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
@@ -3115,6 +3259,8 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
31153259
mlxsw_sp->trap_ops = &mlxsw_sp2_trap_ops;
31163260
mlxsw_sp->mall_ops = &mlxsw_sp2_mall_ops;
31173261
mlxsw_sp->router_ops = &mlxsw_sp2_router_ops;
3262+
mlxsw_sp->listeners = mlxsw_sp2_listener;
3263+
mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp2_listener);
31183264
mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3;
31193265

31203266
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
@@ -3145,6 +3291,8 @@ static int mlxsw_sp4_init(struct mlxsw_core *mlxsw_core,
31453291
mlxsw_sp->trap_ops = &mlxsw_sp2_trap_ops;
31463292
mlxsw_sp->mall_ops = &mlxsw_sp2_mall_ops;
31473293
mlxsw_sp->router_ops = &mlxsw_sp2_router_ops;
3294+
mlxsw_sp->listeners = mlxsw_sp2_listener;
3295+
mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp2_listener);
31483296
mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP4;
31493297

31503298
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@ struct mlxsw_sp_port_mapping {
150150
u8 lane;
151151
};
152152

153+
struct mlxsw_sp_port_mapping_events {
154+
struct list_head queue;
155+
spinlock_t queue_lock; /* protects queue */
156+
struct work_struct work;
157+
};
158+
153159
struct mlxsw_sp_parsing {
154160
refcount_t parsing_depth_ref;
155161
u16 parsing_depth;
@@ -165,6 +171,7 @@ struct mlxsw_sp {
165171
const unsigned char *mac_mask;
166172
struct mlxsw_sp_upper *lags;
167173
struct mlxsw_sp_port_mapping *port_mapping;
174+
struct mlxsw_sp_port_mapping_events port_mapping_events;
168175
struct rhashtable sample_trigger_ht;
169176
struct mlxsw_sp_sb *sb;
170177
struct mlxsw_sp_bridge *bridge;

drivers/net/ethernet/mellanox/mlxsw/trap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ enum mlxsw_event_trap_id {
133133
MLXSW_TRAP_ID_PTP_ING_FIFO = 0x2D,
134134
/* PTP Egress FIFO has a new entry */
135135
MLXSW_TRAP_ID_PTP_EGR_FIFO = 0x2E,
136+
/* Port mapping change */
137+
MLXSW_TRAP_ID_PMLPE = 0x32E,
136138
};
137139

138140
#endif /* _MLXSW_TRAP_H */

0 commit comments

Comments
 (0)