Skip to content

Commit d3a6987

Browse files
committed
Merge branch 'mv88e6xxx-Add-per-port-devlink-regions'
Andrew Lunn says: ==================== mv88e6xxx: Add per port devlink regions This patchset extends devlink regions to support per port regions, and them makes use of them to support the ports of the mv88e6xxx switches. root@rap:~# devlink region show mdio_bus/gpio-0:00/global1: size 64 snapshot [] mdio_bus/gpio-0:00/global2: size 64 snapshot [] mdio_bus/gpio-0:00/atu: size 49152 snapshot [] mdio_bus/gpio-0:00/0/port: size 64 snapshot [] mdio_bus/gpio-0:00/1/port: size 64 snapshot [] mdio_bus/gpio-0:00/2/port: size 64 snapshot [] mdio_bus/gpio-0:00/3/port: size 64 snapshot [] mdio_bus/gpio-0:00/4/port: size 64 snapshot [] mdio_bus/gpio-0:00/5/port: size 64 snapshot [] mdio_bus/gpio-0:00/6/port: size 64 snapshot [] mdio_bus/gpio-0:00/7/port: size 64 snapshot [] mdio_bus/gpio-0:00/8/port: size 64 snapshot [] mdio_bus/gpio-0:00/9/port: size 64 snapshot [] mdio_bus/gpio-0:00/10/port: size 64 snapshot [] root@rap:~# devlink region new mdio_bus/gpio-0:00/1/port snapshot 42 root@rap:~# devlink region dump mdio_bus/gpio-0:00/1/port snapshot 42 0000000000000000 4f 1e 3e 20 00 01 01 39 3f 05 00 00 fd 07 00 00 0000000000000010 80 00 01 00 00 00 00 00 00 00 00 00 00 00 00 91 0000000000000020 00 00 00 00 00 00 00 00 00 00 00 00 22 00 00 00 0000000000000030 07 3e 00 00 00 00 00 80 00 00 00 00 00 00 5b 00 In order to support all ports of the switch, a new devlink flavour has been added for unused ports: mdio_bus/gpio-0:00/0: type notset flavour unused splittable false mdio_bus/gpio-0:00/1: type notset flavour cpu port 1 splittable false mdio_bus/gpio-0:00/2: type eth netdev red flavour physical port 2 splittable fae mdio_bus/gpio-0:00/3: type eth netdev blue flavour physical port 3 splittable fe mdio_bus/gpio-0:00/4: type eth netdev green flavour physical port 4 splittable e mdio_bus/gpio-0:00/5: type notset flavour unused splittable false mdio_bus/gpio-0:00/6: type notset flavour unused splittable false mdio_bus/gpio-0:00/7: type notset flavour unused splittable false mdio_bus/gpio-0:00/8: type eth netdev waic0 flavour physical port 8 splittable e mdio_bus/gpio-0:00/9: type notset flavour unused splittable false mdio_bus/gpio-0:00/10: type notset flavour unused splittable false The DSA core now creates the devlink port instances earlier, so that the driver setup function can make use of them. v3: Whitespace cleanup Added justification for devlink unused flavour Added Tested-by, Reviewed-by: ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 321e921 + b71a8d6 commit d3a6987

File tree

7 files changed

+468
-74
lines changed

7 files changed

+468
-74
lines changed

drivers/net/dsa/mv88e6xxx/devlink.c

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,36 @@ static int mv88e6xxx_region_atu_snapshot(struct devlink *dl,
415415
return err;
416416
}
417417

418+
static int mv88e6xxx_region_port_snapshot(struct devlink_port *devlink_port,
419+
const struct devlink_port_region_ops *ops,
420+
struct netlink_ext_ack *extack,
421+
u8 **data)
422+
{
423+
struct dsa_switch *ds = dsa_devlink_port_to_ds(devlink_port);
424+
int port = dsa_devlink_port_to_port(devlink_port);
425+
struct mv88e6xxx_chip *chip = ds->priv;
426+
u16 *registers;
427+
int i, err;
428+
429+
registers = kmalloc_array(32, sizeof(u16), GFP_KERNEL);
430+
if (!registers)
431+
return -ENOMEM;
432+
433+
mv88e6xxx_reg_lock(chip);
434+
for (i = 0; i < 32; i++) {
435+
err = mv88e6xxx_port_read(chip, port, i, &registers[i]);
436+
if (err) {
437+
kfree(registers);
438+
goto out;
439+
}
440+
}
441+
*data = (u8 *)registers;
442+
out:
443+
mv88e6xxx_reg_unlock(chip);
444+
445+
return err;
446+
}
447+
418448
static struct mv88e6xxx_region_priv mv88e6xxx_region_global1_priv = {
419449
.id = MV88E6XXX_REGION_GLOBAL1,
420450
};
@@ -443,6 +473,12 @@ static struct devlink_region_ops mv88e6xxx_region_atu_ops = {
443473
.destructor = kfree,
444474
};
445475

476+
static const struct devlink_port_region_ops mv88e6xxx_region_port_ops = {
477+
.name = "port",
478+
.snapshot = mv88e6xxx_region_port_snapshot,
479+
.destructor = kfree,
480+
};
481+
446482
struct mv88e6xxx_region {
447483
struct devlink_region_ops *ops;
448484
u64 size;
@@ -471,11 +507,59 @@ mv88e6xxx_teardown_devlink_regions_global(struct mv88e6xxx_chip *chip)
471507
dsa_devlink_region_destroy(chip->regions[i]);
472508
}
473509

474-
void mv88e6xxx_teardown_devlink_regions(struct dsa_switch *ds)
510+
static void
511+
mv88e6xxx_teardown_devlink_regions_port(struct mv88e6xxx_chip *chip,
512+
int port)
475513
{
476-
struct mv88e6xxx_chip *chip = ds->priv;
514+
dsa_devlink_region_destroy(chip->ports[port].region);
515+
}
477516

478-
mv88e6xxx_teardown_devlink_regions_global(chip);
517+
static int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds,
518+
struct mv88e6xxx_chip *chip,
519+
int port)
520+
{
521+
struct devlink_region *region;
522+
523+
region = dsa_devlink_port_region_create(ds,
524+
port,
525+
&mv88e6xxx_region_port_ops, 1,
526+
32 * sizeof(u16));
527+
if (IS_ERR(region))
528+
return PTR_ERR(region);
529+
530+
chip->ports[port].region = region;
531+
532+
return 0;
533+
}
534+
535+
static void
536+
mv88e6xxx_teardown_devlink_regions_ports(struct mv88e6xxx_chip *chip)
537+
{
538+
int port;
539+
540+
for (port = 0; port < mv88e6xxx_num_ports(chip); port++)
541+
mv88e6xxx_teardown_devlink_regions_port(chip, port);
542+
}
543+
544+
static int mv88e6xxx_setup_devlink_regions_ports(struct dsa_switch *ds,
545+
struct mv88e6xxx_chip *chip)
546+
{
547+
int port;
548+
int err;
549+
550+
for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
551+
err = mv88e6xxx_setup_devlink_regions_port(ds, chip, port);
552+
if (err)
553+
goto out;
554+
}
555+
556+
return 0;
557+
558+
out:
559+
while (port-- > 0)
560+
mv88e6xxx_teardown_devlink_regions_port(chip, port);
561+
562+
return err;
479563
}
480564

481565
static int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds,
@@ -511,8 +595,25 @@ static int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds,
511595
int mv88e6xxx_setup_devlink_regions(struct dsa_switch *ds)
512596
{
513597
struct mv88e6xxx_chip *chip = ds->priv;
598+
int err;
599+
600+
err = mv88e6xxx_setup_devlink_regions_global(ds, chip);
601+
if (err)
602+
return err;
603+
604+
err = mv88e6xxx_setup_devlink_regions_ports(ds, chip);
605+
if (err)
606+
mv88e6xxx_teardown_devlink_regions_global(chip);
514607

515-
return mv88e6xxx_setup_devlink_regions_global(ds, chip);
608+
return err;
609+
}
610+
611+
void mv88e6xxx_teardown_devlink_regions(struct dsa_switch *ds)
612+
{
613+
struct mv88e6xxx_chip *chip = ds->priv;
614+
615+
mv88e6xxx_teardown_devlink_regions_ports(chip);
616+
mv88e6xxx_teardown_devlink_regions_global(chip);
516617
}
517618

518619
int mv88e6xxx_devlink_info_get(struct dsa_switch *ds,

include/net/devlink.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ struct devlink_port_attrs {
110110
struct devlink_port {
111111
struct list_head list;
112112
struct list_head param_list;
113+
struct list_head region_list;
113114
struct devlink *devlink;
114115
unsigned int index;
115116
bool registered;
@@ -591,6 +592,26 @@ struct devlink_region_ops {
591592
void *priv;
592593
};
593594

595+
/**
596+
* struct devlink_port_region_ops - Region operations for a port
597+
* @name: region name
598+
* @destructor: callback used to free snapshot memory when deleting
599+
* @snapshot: callback to request an immediate snapshot. On success,
600+
* the data variable must be updated to point to the snapshot data.
601+
* The function will be called while the devlink instance lock is
602+
* held.
603+
* @priv: Pointer to driver private data for the region operation
604+
*/
605+
struct devlink_port_region_ops {
606+
const char *name;
607+
void (*destructor)(const void *data);
608+
int (*snapshot)(struct devlink_port *port,
609+
const struct devlink_port_region_ops *ops,
610+
struct netlink_ext_ack *extack,
611+
u8 **data);
612+
void *priv;
613+
};
614+
594615
struct devlink_fmsg;
595616
struct devlink_health_reporter;
596617

@@ -1445,7 +1466,13 @@ struct devlink_region *
14451466
devlink_region_create(struct devlink *devlink,
14461467
const struct devlink_region_ops *ops,
14471468
u32 region_max_snapshots, u64 region_size);
1469+
struct devlink_region *
1470+
devlink_port_region_create(struct devlink_port *port,
1471+
const struct devlink_port_region_ops *ops,
1472+
u32 region_max_snapshots, u64 region_size);
14481473
void devlink_region_destroy(struct devlink_region *region);
1474+
void devlink_port_region_destroy(struct devlink_region *region);
1475+
14491476
int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id);
14501477
void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id);
14511478
int devlink_region_snapshot_create(struct devlink_region *region,

include/net/dsa.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ struct dsa_port {
215215
u8 stp_state;
216216
struct net_device *bridge_dev;
217217
struct devlink_port devlink_port;
218+
bool devlink_port_setup;
218219
struct phylink *pl;
219220
struct phylink_config pl_config;
220221

@@ -680,6 +681,11 @@ struct devlink_region *
680681
dsa_devlink_region_create(struct dsa_switch *ds,
681682
const struct devlink_region_ops *ops,
682683
u32 region_max_snapshots, u64 region_size);
684+
struct devlink_region *
685+
dsa_devlink_port_region_create(struct dsa_switch *ds,
686+
int port,
687+
const struct devlink_port_region_ops *ops,
688+
u32 region_max_snapshots, u64 region_size);
683689
void dsa_devlink_region_destroy(struct devlink_region *region);
684690

685691
struct dsa_port *dsa_port_from_netdev(struct net_device *netdev);
@@ -695,6 +701,20 @@ static inline struct dsa_switch *dsa_devlink_to_ds(struct devlink *dl)
695701
return dl_priv->ds;
696702
}
697703

704+
static inline
705+
struct dsa_switch *dsa_devlink_port_to_ds(struct devlink_port *port)
706+
{
707+
struct devlink *dl = port->devlink;
708+
struct dsa_devlink_priv *dl_priv = devlink_priv(dl);
709+
710+
return dl_priv->ds;
711+
}
712+
713+
static inline int dsa_devlink_port_to_port(struct devlink_port *port)
714+
{
715+
return port->index;
716+
}
717+
698718
struct dsa_switch_driver {
699719
struct list_head list;
700720
const struct dsa_switch_ops *ops;

include/uapi/linux/devlink.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ enum devlink_port_flavour {
197197
* port that faces the PCI VF.
198198
*/
199199
DEVLINK_PORT_FLAVOUR_VIRTUAL, /* Any virtual port facing the user. */
200+
DEVLINK_PORT_FLAVOUR_UNUSED, /* Port which exists in the switch, but
201+
* is not used in any way.
202+
*/
200203
};
201204

202205
enum devlink_param_cmode {

0 commit comments

Comments
 (0)