Skip to content

Commit 5d6a8ae

Browse files
author
Paolo Abeni
committed
Merge branch 'net-sparx5-prepare-for-lan969x-switch-driver'
Daniel Machon says: ==================== net: sparx5: prepare for lan969x switch driver == Description: This series is the first of a multi-part series, that prepares and adds support for the new lan969x switch driver. The upstreaming efforts is split into multiple series (might change a bit as we go along): 1) Prepare the Sparx5 driver for lan969x (this series) 2) Add support lan969x (same basic features as Sparx5 provides + RGMII, excl. FDMA and VCAP) 3) Add support for lan969x FDMA 4) Add support for lan969x VCAP == Lan969x in short: The lan969x Ethernet switch family [1] provides a rich set of switching features and port configurations (up to 30 ports) from 10Mbps to 10Gbps, with support for RGMII, SGMII, QSGMII, USGMII, and USXGMII, ideal for industrial & process automation infrastructure applications, transport, grid automation, power substation automation, and ring & intra-ring topologies. The LAN969x family is hardware and software compatible and scalable supporting 46Gbps to 102Gbps switch bandwidths. == Preparing Sparx5 for lan969x: The lan969x switch chip reuses many of the IP's of the Sparx5 switch chip, therefore it has been decided to add support through the existing Sparx5 driver, in order to avoid a bunch of duplicate code. However, in order to reuse the Sparx5 switch driver, we have to introduce some mechanisms to handle the chip differences that are there. These mechanisms are: - Platform match data to contain all the differences that needs to be handled (constants, ops etc.) - Register macro indirection layer so that we can reuse the existing register macros. - Function for branching out on platform type where required. In some places we ops out functions and in other places we branch on the chip type. Exactly when we choose one over the other, is an estimate in each case. After this series is applied, the Sparx5 driver will be prepared for lan969x and still function exactly as before. == Patch breakdown: Patch kernel-patches#1 adds private match data Patch kernel-patches#2 adds register macro indirection layer Patch kernel-patches#3-kernel-patches#4 does some preparation work Patch kernel-patches#5-kernel-patches#7 adds chip constants and updates the code to use them Patch kernel-patches#8-kernel-patches#13 adds and uses ops for handling functions differently on the two platforms. Patch kernel-patches#14 adds and uses a macro for branching out on the chip type. Patch kernel-patches#15 (NEW) redefines macros for internal ports and PGID's. [1] https://www.microchip.com/en-us/product/lan9698 To: David S. Miller <[email protected]> To: Eric Dumazet <[email protected]> To: Jakub Kicinski <[email protected]> To: Paolo Abeni <[email protected]> To: Lars Povlsen <[email protected]> To: Steen Hegelund <[email protected]> To: [email protected] To: [email protected] To: [email protected] To: Richard Cochran <[email protected]> To: [email protected] To: [email protected] To: [email protected] To: [email protected] To: [email protected] To: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Signed-off-by: Daniel Machon <[email protected]> ==================== Link: https://patch.msgid.link/20241004-b4-sparx5-lan969x-switch-driver-v2-0-d3290f581663@microchip.com Signed-off-by: Paolo Abeni <[email protected]>
2 parents e793b86 + 8cc4102 commit 5d6a8ae

26 files changed

+3531
-2226
lines changed

drivers/net/ethernet/microchip/sparx5/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ sparx5-switch-y := sparx5_main.o sparx5_packet.o \
1111
sparx5_ptp.o sparx5_pgid.o sparx5_tc.o sparx5_qos.o \
1212
sparx5_vcap_impl.o sparx5_vcap_ag_api.o sparx5_tc_flower.o \
1313
sparx5_tc_matchall.o sparx5_pool.o sparx5_sdlb.o sparx5_police.o \
14-
sparx5_psfp.o sparx5_mirror.o
14+
sparx5_psfp.o sparx5_mirror.o sparx5_regs.o
1515

1616
sparx5-switch-$(CONFIG_SPARX5_DCB) += sparx5_dcb.o
1717
sparx5-switch-$(CONFIG_DEBUG_FS) += sparx5_vcap_debugfs.o

drivers/net/ethernet/microchip/sparx5/sparx5_calendar.c

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515
#define SPX5_CALBITS_PER_PORT 3 /* Bit per port in calendar register */
1616

1717
/* DSM calendar information */
18-
#define SPX5_DSM_CAL_LEN 64
1918
#define SPX5_DSM_CAL_EMPTY 0xFFFF
20-
#define SPX5_DSM_CAL_MAX_DEVS_PER_TAXI 13
2119
#define SPX5_DSM_CAL_TAXIS 8
2220
#define SPX5_DSM_CAL_BW_LOSS 553
2321

@@ -37,19 +35,6 @@ static u32 sparx5_taxi_ports[SPX5_DSM_CAL_TAXIS][SPX5_DSM_CAL_MAX_DEVS_PER_TAXI]
3735
{64, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99},
3836
};
3937

40-
struct sparx5_calendar_data {
41-
u32 schedule[SPX5_DSM_CAL_LEN];
42-
u32 avg_dist[SPX5_DSM_CAL_MAX_DEVS_PER_TAXI];
43-
u32 taxi_ports[SPX5_DSM_CAL_MAX_DEVS_PER_TAXI];
44-
u32 taxi_speeds[SPX5_DSM_CAL_MAX_DEVS_PER_TAXI];
45-
u32 dev_slots[SPX5_DSM_CAL_MAX_DEVS_PER_TAXI];
46-
u32 new_slots[SPX5_DSM_CAL_LEN];
47-
u32 temp_sched[SPX5_DSM_CAL_LEN];
48-
u32 indices[SPX5_DSM_CAL_LEN];
49-
u32 short_list[SPX5_DSM_CAL_LEN];
50-
u32 long_list[SPX5_DSM_CAL_LEN];
51-
};
52-
5338
static u32 sparx5_target_bandwidth(struct sparx5 *sparx5)
5439
{
5540
switch (sparx5->target_ct) {
@@ -131,18 +116,24 @@ static enum sparx5_cal_bw sparx5_get_port_cal_speed(struct sparx5 *sparx5,
131116
{
132117
struct sparx5_port *port;
133118

134-
if (portno >= SPX5_PORTS) {
119+
if (portno >= sparx5->data->consts->n_ports) {
135120
/* Internal ports */
136-
if (portno == SPX5_PORT_CPU_0 || portno == SPX5_PORT_CPU_1) {
121+
if (portno ==
122+
sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_0) ||
123+
portno ==
124+
sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_1)) {
137125
/* Equals 1.25G */
138126
return SPX5_CAL_SPEED_2G5;
139-
} else if (portno == SPX5_PORT_VD0) {
127+
} else if (portno ==
128+
sparx5_get_internal_port(sparx5, SPX5_PORT_VD0)) {
140129
/* IPMC only idle BW */
141130
return SPX5_CAL_SPEED_NONE;
142-
} else if (portno == SPX5_PORT_VD1) {
131+
} else if (portno ==
132+
sparx5_get_internal_port(sparx5, SPX5_PORT_VD1)) {
143133
/* OAM only idle BW */
144134
return SPX5_CAL_SPEED_NONE;
145-
} else if (portno == SPX5_PORT_VD2) {
135+
} else if (portno ==
136+
sparx5_get_internal_port(sparx5, SPX5_PORT_VD2)) {
146137
/* IPinIP gets only idle BW */
147138
return SPX5_CAL_SPEED_NONE;
148139
}
@@ -159,6 +150,7 @@ static enum sparx5_cal_bw sparx5_get_port_cal_speed(struct sparx5 *sparx5,
159150
/* Auto configure the QSYS calendar based on port configuration */
160151
int sparx5_config_auto_calendar(struct sparx5 *sparx5)
161152
{
153+
const struct sparx5_consts *consts = sparx5->data->consts;
162154
u32 cal[7], value, idx, portno;
163155
u32 max_core_bw;
164156
u32 total_bw = 0, used_port_bw = 0;
@@ -174,15 +166,15 @@ int sparx5_config_auto_calendar(struct sparx5 *sparx5)
174166
}
175167

176168
/* Setup the calendar with the bandwidth to each port */
177-
for (portno = 0; portno < SPX5_PORTS_ALL; portno++) {
169+
for (portno = 0; portno < consts->n_ports_all; portno++) {
178170
u64 reg, offset, this_bw;
179171

180172
spd = sparx5_get_port_cal_speed(sparx5, portno);
181173
if (spd == SPX5_CAL_SPEED_NONE)
182174
continue;
183175

184176
this_bw = sparx5_cal_speed_to_value(spd);
185-
if (portno < SPX5_PORTS)
177+
if (portno < consts->n_ports)
186178
used_port_bw += this_bw;
187179
else
188180
/* Internal ports are granted half the value */
@@ -208,12 +200,13 @@ int sparx5_config_auto_calendar(struct sparx5 *sparx5)
208200
}
209201

210202
/* Halt the calendar while changing it */
211-
spx5_rmw(QSYS_CAL_CTRL_CAL_MODE_SET(10),
212-
QSYS_CAL_CTRL_CAL_MODE,
213-
sparx5, QSYS_CAL_CTRL);
203+
if (is_sparx5(sparx5))
204+
spx5_rmw(QSYS_CAL_CTRL_CAL_MODE_SET(10),
205+
QSYS_CAL_CTRL_CAL_MODE,
206+
sparx5, QSYS_CAL_CTRL);
214207

215208
/* Assign port bandwidth to auto calendar */
216-
for (idx = 0; idx < ARRAY_SIZE(cal); idx++)
209+
for (idx = 0; idx < consts->n_auto_cals; idx++)
217210
spx5_wr(cal[idx], sparx5, QSYS_CAL_AUTO(idx));
218211

219212
/* Increase grant rate of all ports to account for
@@ -278,8 +271,8 @@ static u32 sparx5_dsm_cp_cal(u32 *sched)
278271
return SPX5_DSM_CAL_EMPTY;
279272
}
280273

281-
static int sparx5_dsm_calendar_calc(struct sparx5 *sparx5, u32 taxi,
282-
struct sparx5_calendar_data *data)
274+
int sparx5_dsm_calendar_calc(struct sparx5 *sparx5, u32 taxi,
275+
struct sparx5_calendar_data *data)
283276
{
284277
bool slow_mode;
285278
u32 gcd, idx, sum, min, factor;
@@ -304,7 +297,7 @@ static int sparx5_dsm_calendar_calc(struct sparx5 *sparx5, u32 taxi,
304297
for (idx = 0; idx < SPX5_DSM_CAL_MAX_DEVS_PER_TAXI; idx++) {
305298
u32 portno = data->taxi_ports[idx];
306299

307-
if (portno < SPX5_TAXI_PORT_MAX) {
300+
if (portno < sparx5->data->consts->n_ports_all) {
308301
data->taxi_speeds[idx] = sparx5_cal_speed_to_value
309302
(sparx5_get_port_cal_speed(sparx5, portno));
310303
} else {
@@ -565,6 +558,7 @@ static int sparx5_dsm_calendar_update(struct sparx5 *sparx5, u32 taxi,
565558
/* Configure the DSM calendar based on port configuration */
566559
int sparx5_config_dsm_calendar(struct sparx5 *sparx5)
567560
{
561+
const struct sparx5_ops *ops = sparx5->data->ops;
568562
int taxi;
569563
struct sparx5_calendar_data *data;
570564
int err = 0;
@@ -573,8 +567,8 @@ int sparx5_config_dsm_calendar(struct sparx5 *sparx5)
573567
if (!data)
574568
return -ENOMEM;
575569

576-
for (taxi = 0; taxi < SPX5_DSM_CAL_TAXIS; ++taxi) {
577-
err = sparx5_dsm_calendar_calc(sparx5, taxi, data);
570+
for (taxi = 0; taxi < sparx5->data->consts->n_dsm_cal_taxis; ++taxi) {
571+
err = ops->dsm_calendar_calc(sparx5, taxi, data);
578572
if (err) {
579573
dev_err(sparx5->dev, "DSM calendar calculation failed\n");
580574
goto cal_out;

drivers/net/ethernet/microchip/sparx5/sparx5_dcb.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,11 @@ static int sparx5_dcb_ieee_dscp_setdel(struct net_device *dev,
234234
struct dcb_app *))
235235
{
236236
struct sparx5_port *port = netdev_priv(dev);
237+
struct sparx5 *sparx5 = port->sparx5;
237238
struct sparx5_port *port_itr;
238239
int err, i;
239240

240-
for (i = 0; i < SPX5_PORTS; i++) {
241+
for (i = 0; i < sparx5->data->consts->n_ports; i++) {
241242
port_itr = port->sparx5->ports[i];
242243
if (!port_itr)
243244
continue;
@@ -386,7 +387,7 @@ int sparx5_dcb_init(struct sparx5 *sparx5)
386387
struct sparx5_port *port;
387388
int i;
388389

389-
for (i = 0; i < SPX5_PORTS; i++) {
390+
for (i = 0; i < sparx5->data->consts->n_ports; i++) {
390391
port = sparx5->ports[i];
391392
if (!port)
392393
continue;

drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -505,8 +505,8 @@ static void sparx5_get_dev_misc_stats(u64 *portstats, void __iomem *inst, u32
505505
static void sparx5_get_device_stats(struct sparx5 *sparx5, int portno)
506506
{
507507
u64 *portstats = &sparx5->stats[portno * sparx5->num_stats];
508-
u32 tinst = sparx5_port_dev_index(portno);
509-
u32 dev = sparx5_to_high_dev(portno);
508+
u32 tinst = sparx5_port_dev_index(sparx5, portno);
509+
u32 dev = sparx5_to_high_dev(sparx5, portno);
510510
void __iomem *inst;
511511

512512
inst = spx5_inst_get(sparx5, dev, tinst);
@@ -819,8 +819,8 @@ static void sparx5_get_eth_phy_stats(struct net_device *ndev,
819819

820820
portstats = &sparx5->stats[portno * sparx5->num_stats];
821821
if (sparx5_is_baser(port->conf.portmode)) {
822-
u32 tinst = sparx5_port_dev_index(portno);
823-
u32 dev = sparx5_to_high_dev(portno);
822+
u32 tinst = sparx5_port_dev_index(sparx5, portno);
823+
u32 dev = sparx5_to_high_dev(sparx5, portno);
824824

825825
inst = spx5_inst_get(sparx5, dev, tinst);
826826
sparx5_get_dev_phy_stats(portstats, inst, tinst);
@@ -844,8 +844,8 @@ static void sparx5_get_eth_mac_stats(struct net_device *ndev,
844844

845845
portstats = &sparx5->stats[portno * sparx5->num_stats];
846846
if (sparx5_is_baser(port->conf.portmode)) {
847-
u32 tinst = sparx5_port_dev_index(portno);
848-
u32 dev = sparx5_to_high_dev(portno);
847+
u32 tinst = sparx5_port_dev_index(sparx5, portno);
848+
u32 dev = sparx5_to_high_dev(sparx5, portno);
849849

850850
inst = spx5_inst_get(sparx5, dev, tinst);
851851
sparx5_get_dev_mac_stats(portstats, inst, tinst);
@@ -912,8 +912,8 @@ static void sparx5_get_eth_mac_ctrl_stats(struct net_device *ndev,
912912

913913
portstats = &sparx5->stats[portno * sparx5->num_stats];
914914
if (sparx5_is_baser(port->conf.portmode)) {
915-
u32 tinst = sparx5_port_dev_index(portno);
916-
u32 dev = sparx5_to_high_dev(portno);
915+
u32 tinst = sparx5_port_dev_index(sparx5, portno);
916+
u32 dev = sparx5_to_high_dev(sparx5, portno);
917917

918918
inst = spx5_inst_get(sparx5, dev, tinst);
919919
sparx5_get_dev_mac_ctrl_stats(portstats, inst, tinst);
@@ -944,8 +944,8 @@ static void sparx5_get_eth_rmon_stats(struct net_device *ndev,
944944

945945
portstats = &sparx5->stats[portno * sparx5->num_stats];
946946
if (sparx5_is_baser(port->conf.portmode)) {
947-
u32 tinst = sparx5_port_dev_index(portno);
948-
u32 dev = sparx5_to_high_dev(portno);
947+
u32 tinst = sparx5_port_dev_index(sparx5, portno);
948+
u32 dev = sparx5_to_high_dev(sparx5, portno);
949949

950950
inst = spx5_inst_get(sparx5, dev, tinst);
951951
sparx5_get_dev_rmon_stats(portstats, inst, tinst);
@@ -1027,8 +1027,8 @@ static void sparx5_get_sset_data(struct net_device *ndev,
10271027

10281028
portstats = &sparx5->stats[portno * sparx5->num_stats];
10291029
if (sparx5_is_baser(port->conf.portmode)) {
1030-
u32 tinst = sparx5_port_dev_index(portno);
1031-
u32 dev = sparx5_to_high_dev(portno);
1030+
u32 tinst = sparx5_port_dev_index(sparx5, portno);
1031+
u32 dev = sparx5_to_high_dev(sparx5, portno);
10321032

10331033
inst = spx5_inst_get(sparx5, dev, tinst);
10341034
sparx5_get_dev_misc_stats(portstats, inst, tinst);
@@ -1122,7 +1122,7 @@ static void sparx5_update_stats(struct sparx5 *sparx5)
11221122
{
11231123
int idx;
11241124

1125-
for (idx = 0; idx < SPX5_PORTS; idx++)
1125+
for (idx = 0; idx < sparx5->data->consts->n_ports; idx++)
11261126
if (sparx5->ports[idx])
11271127
sparx5_update_port_stats(sparx5, idx);
11281128
}
@@ -1189,7 +1189,7 @@ static int sparx5_get_ts_info(struct net_device *dev,
11891189
struct sparx5 *sparx5 = port->sparx5;
11901190
struct sparx5_phc *phc;
11911191

1192-
if (!sparx5->ptp)
1192+
if (!sparx5->ptp && is_sparx5(sparx5))
11931193
return ethtool_op_get_ts_info(dev, info);
11941194

11951195
phc = &sparx5->phc[SPARX5_PHC_PORT];
@@ -1228,21 +1228,23 @@ const struct ethtool_ops sparx5_ethtool_ops = {
12281228

12291229
int sparx_stats_init(struct sparx5 *sparx5)
12301230
{
1231+
const struct sparx5_consts *consts = sparx5->data->consts;
12311232
char queue_name[32];
12321233
int portno;
12331234

12341235
sparx5->stats_layout = sparx5_stats_layout;
12351236
sparx5->num_stats = spx5_stats_count;
12361237
sparx5->num_ethtool_stats = ARRAY_SIZE(sparx5_stats_layout);
12371238
sparx5->stats = devm_kcalloc(sparx5->dev,
1238-
SPX5_PORTS_ALL * sparx5->num_stats,
1239+
consts->n_ports_all *
1240+
sparx5->num_stats,
12391241
sizeof(u64), GFP_KERNEL);
12401242
if (!sparx5->stats)
12411243
return -ENOMEM;
12421244

12431245
mutex_init(&sparx5->queue_stats_lock);
12441246
sparx5_config_stats(sparx5);
1245-
for (portno = 0; portno < SPX5_PORTS; portno++)
1247+
for (portno = 0; portno < consts->n_ports; portno++)
12461248
if (sparx5->ports[portno])
12471249
sparx5_config_port_stats(sparx5, portno);
12481250

drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,9 @@ static bool sparx5_fdma_rx_get_frame(struct sparx5 *sparx5, struct sparx5_rx *rx
156156
/* Now do the normal processing of the skb */
157157
sparx5_ifh_parse((u32 *)skb->data, &fi);
158158
/* Map to port netdev */
159-
port = fi.src_port < SPX5_PORTS ? sparx5->ports[fi.src_port] : NULL;
159+
port = fi.src_port < sparx5->data->consts->n_ports ?
160+
sparx5->ports[fi.src_port] :
161+
NULL;
160162
if (!port || !port->ndev) {
161163
dev_err(sparx5->dev, "Data on inactive port %d\n", fi.src_port);
162164
sparx5_xtr_flush(sparx5, XTR_QUEUE);
@@ -296,7 +298,7 @@ static void sparx5_fdma_rx_init(struct sparx5 *sparx5,
296298
fdma->ops.dataptr_cb = &sparx5_fdma_rx_dataptr_cb;
297299
fdma->ops.nextptr_cb = &fdma_nextptr_cb;
298300
/* Fetch a netdev for SKB and NAPI use, any will do */
299-
for (idx = 0; idx < SPX5_PORTS; ++idx) {
301+
for (idx = 0; idx < sparx5->data->consts->n_ports; ++idx) {
300302
struct sparx5_port *port = sparx5->ports[idx];
301303

302304
if (port && port->ndev) {
@@ -362,7 +364,9 @@ static void sparx5_fdma_injection_mode(struct sparx5 *sparx5)
362364
sparx5, QS_INJ_GRP_CFG(INJ_QUEUE));
363365

364366
/* CPU ports capture setup */
365-
for (portno = SPX5_PORT_CPU_0; portno <= SPX5_PORT_CPU_1; portno++) {
367+
for (portno = sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_0);
368+
portno <= sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_1);
369+
portno++) {
366370
/* ASM CPU port: No preamble, IFH, enable padding */
367371
spx5_wr(ASM_PORT_CFG_PAD_ENA_SET(1) |
368372
ASM_PORT_CFG_NO_PREAMBLE_ENA_SET(1) |

drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,16 @@ static void sparx5_mact_select(struct sparx5 *sparx5,
8080
int sparx5_mact_learn(struct sparx5 *sparx5, int pgid,
8181
const unsigned char mac[ETH_ALEN], u16 vid)
8282
{
83+
const struct sparx5_consts *consts = sparx5->data->consts;
8384
int addr, type, ret;
8485

85-
if (pgid < SPX5_PORTS) {
86+
if (pgid < consts->n_ports) {
8687
type = MAC_ENTRY_ADDR_TYPE_UPSID_PN;
8788
addr = pgid % 32;
8889
addr += (pgid / 32) << 5; /* Add upsid */
8990
} else {
9091
type = MAC_ENTRY_ADDR_TYPE_MC_IDX;
91-
addr = pgid - SPX5_PORTS;
92+
addr = pgid - consts->n_ports;
9293
}
9394

9495
mutex_lock(&sparx5->lock);
@@ -128,7 +129,8 @@ int sparx5_mc_sync(struct net_device *dev, const unsigned char *addr)
128129
struct sparx5_port *port = netdev_priv(dev);
129130
struct sparx5 *sparx5 = port->sparx5;
130131

131-
return sparx5_mact_learn(sparx5, PGID_CPU, addr, port->pvid);
132+
return sparx5_mact_learn(sparx5, sparx5_get_pgid(sparx5, PGID_CPU),
133+
addr, port->pvid);
132134
}
133135

134136
static int sparx5_mact_get(struct sparx5 *sparx5,
@@ -371,7 +373,7 @@ static void sparx5_mact_handle_entry(struct sparx5 *sparx5,
371373
return;
372374

373375
port = LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_ADDR_GET(cfg2);
374-
if (port >= SPX5_PORTS)
376+
if (port >= sparx5->data->consts->n_ports)
375377
return;
376378

377379
if (!test_bit(port, sparx5->bridge_mask))

0 commit comments

Comments
 (0)