Skip to content

Commit a629ef2

Browse files
pmachatadavem330
authored andcommitted
mlxsw: spectrum: Move SPAN code to separate module
For the upcoming work on SPAN, it makes sense to move the current code to a module of its own. It already has a well-defined API boundary to the mirror management (which is used from matchall and ACL code). A couple more functions need to be exported for the functions that spectrum.c needs to use for MTU handling and subsystem init/fini. Signed-off-by: Petr Machata <petrm@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent ce470b4 commit a629ef2

File tree

6 files changed

+433
-348
lines changed

6 files changed

+433
-348
lines changed

drivers/net/ethernet/mellanox/mlxsw/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \
2020
spectrum_cnt.o spectrum_fid.o \
2121
spectrum_ipip.o spectrum_acl_flex_actions.o \
2222
spectrum_mr.o spectrum_mr_tcam.o \
23-
spectrum_qdisc.o
23+
spectrum_qdisc.o spectrum_span.o
2424
mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB) += spectrum_dcb.o
2525
mlxsw_spectrum-$(CONFIG_NET_DEVLINK) += spectrum_dpipe.o
2626
obj-$(CONFIG_MLXSW_MINIMAL) += mlxsw_minimal.o

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

Lines changed: 1 addition & 319 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
#include "spectrum_cnt.h"
7272
#include "spectrum_dpipe.h"
7373
#include "spectrum_acl_flex_actions.h"
74+
#include "spectrum_span.h"
7475
#include "../mlxfw/mlxfw.h"
7576

7677
#define MLXSW_FWREV_MAJOR 13
@@ -487,325 +488,6 @@ static int mlxsw_sp_base_mac_get(struct mlxsw_sp *mlxsw_sp)
487488
return 0;
488489
}
489490

490-
static int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
491-
{
492-
int i;
493-
494-
if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_SPAN))
495-
return -EIO;
496-
497-
mlxsw_sp->span.entries_count = MLXSW_CORE_RES_GET(mlxsw_sp->core,
498-
MAX_SPAN);
499-
mlxsw_sp->span.entries = kcalloc(mlxsw_sp->span.entries_count,
500-
sizeof(struct mlxsw_sp_span_entry),
501-
GFP_KERNEL);
502-
if (!mlxsw_sp->span.entries)
503-
return -ENOMEM;
504-
505-
for (i = 0; i < mlxsw_sp->span.entries_count; i++)
506-
INIT_LIST_HEAD(&mlxsw_sp->span.entries[i].bound_ports_list);
507-
508-
return 0;
509-
}
510-
511-
static void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp)
512-
{
513-
int i;
514-
515-
for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
516-
struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
517-
518-
WARN_ON_ONCE(!list_empty(&curr->bound_ports_list));
519-
}
520-
kfree(mlxsw_sp->span.entries);
521-
}
522-
523-
static struct mlxsw_sp_span_entry *
524-
mlxsw_sp_span_entry_create(struct mlxsw_sp_port *port)
525-
{
526-
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
527-
struct mlxsw_sp_span_entry *span_entry;
528-
char mpat_pl[MLXSW_REG_MPAT_LEN];
529-
u8 local_port = port->local_port;
530-
int index;
531-
int i;
532-
int err;
533-
534-
/* find a free entry to use */
535-
index = -1;
536-
for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
537-
if (!mlxsw_sp->span.entries[i].ref_count) {
538-
index = i;
539-
span_entry = &mlxsw_sp->span.entries[i];
540-
break;
541-
}
542-
}
543-
if (index < 0)
544-
return NULL;
545-
546-
/* create a new port analayzer entry for local_port */
547-
mlxsw_reg_mpat_pack(mpat_pl, index, local_port, true);
548-
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
549-
if (err)
550-
return NULL;
551-
552-
span_entry->id = index;
553-
span_entry->ref_count = 1;
554-
span_entry->local_port = local_port;
555-
return span_entry;
556-
}
557-
558-
static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp,
559-
struct mlxsw_sp_span_entry *span_entry)
560-
{
561-
u8 local_port = span_entry->local_port;
562-
char mpat_pl[MLXSW_REG_MPAT_LEN];
563-
int pa_id = span_entry->id;
564-
565-
mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, false);
566-
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
567-
}
568-
569-
struct mlxsw_sp_span_entry *
570-
mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port)
571-
{
572-
int i;
573-
574-
for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
575-
struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
576-
577-
if (curr->ref_count && curr->local_port == local_port)
578-
return curr;
579-
}
580-
return NULL;
581-
}
582-
583-
static struct mlxsw_sp_span_entry *
584-
mlxsw_sp_span_entry_get(struct mlxsw_sp_port *port)
585-
{
586-
struct mlxsw_sp_span_entry *span_entry;
587-
588-
span_entry = mlxsw_sp_span_entry_find(port->mlxsw_sp,
589-
port->local_port);
590-
if (span_entry) {
591-
/* Already exists, just take a reference */
592-
span_entry->ref_count++;
593-
return span_entry;
594-
}
595-
596-
return mlxsw_sp_span_entry_create(port);
597-
}
598-
599-
static int mlxsw_sp_span_entry_put(struct mlxsw_sp *mlxsw_sp,
600-
struct mlxsw_sp_span_entry *span_entry)
601-
{
602-
WARN_ON(!span_entry->ref_count);
603-
if (--span_entry->ref_count == 0)
604-
mlxsw_sp_span_entry_destroy(mlxsw_sp, span_entry);
605-
return 0;
606-
}
607-
608-
static bool mlxsw_sp_span_is_egress_mirror(struct mlxsw_sp_port *port)
609-
{
610-
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
611-
struct mlxsw_sp_span_inspected_port *p;
612-
int i;
613-
614-
for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
615-
struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
616-
617-
list_for_each_entry(p, &curr->bound_ports_list, list)
618-
if (p->local_port == port->local_port &&
619-
p->type == MLXSW_SP_SPAN_EGRESS)
620-
return true;
621-
}
622-
623-
return false;
624-
}
625-
626-
static int mlxsw_sp_span_mtu_to_buffsize(const struct mlxsw_sp *mlxsw_sp,
627-
int mtu)
628-
{
629-
return mlxsw_sp_bytes_cells(mlxsw_sp, mtu * 5 / 2) + 1;
630-
}
631-
632-
static int mlxsw_sp_span_port_mtu_update(struct mlxsw_sp_port *port, u16 mtu)
633-
{
634-
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
635-
char sbib_pl[MLXSW_REG_SBIB_LEN];
636-
int err;
637-
638-
/* If port is egress mirrored, the shared buffer size should be
639-
* updated according to the mtu value
640-
*/
641-
if (mlxsw_sp_span_is_egress_mirror(port)) {
642-
u32 buffsize = mlxsw_sp_span_mtu_to_buffsize(mlxsw_sp, mtu);
643-
644-
mlxsw_reg_sbib_pack(sbib_pl, port->local_port, buffsize);
645-
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
646-
if (err) {
647-
netdev_err(port->dev, "Could not update shared buffer for mirroring\n");
648-
return err;
649-
}
650-
}
651-
652-
return 0;
653-
}
654-
655-
static struct mlxsw_sp_span_inspected_port *
656-
mlxsw_sp_span_entry_bound_port_find(struct mlxsw_sp_port *port,
657-
struct mlxsw_sp_span_entry *span_entry)
658-
{
659-
struct mlxsw_sp_span_inspected_port *p;
660-
661-
list_for_each_entry(p, &span_entry->bound_ports_list, list)
662-
if (port->local_port == p->local_port)
663-
return p;
664-
return NULL;
665-
}
666-
667-
static int
668-
mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
669-
struct mlxsw_sp_span_entry *span_entry,
670-
enum mlxsw_sp_span_type type,
671-
bool bind)
672-
{
673-
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
674-
char mpar_pl[MLXSW_REG_MPAR_LEN];
675-
int pa_id = span_entry->id;
676-
677-
/* bind the port to the SPAN entry */
678-
mlxsw_reg_mpar_pack(mpar_pl, port->local_port,
679-
(enum mlxsw_reg_mpar_i_e) type, bind, pa_id);
680-
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
681-
}
682-
683-
static int
684-
mlxsw_sp_span_inspected_port_add(struct mlxsw_sp_port *port,
685-
struct mlxsw_sp_span_entry *span_entry,
686-
enum mlxsw_sp_span_type type,
687-
bool bind)
688-
{
689-
struct mlxsw_sp_span_inspected_port *inspected_port;
690-
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
691-
char sbib_pl[MLXSW_REG_SBIB_LEN];
692-
int err;
693-
694-
/* if it is an egress SPAN, bind a shared buffer to it */
695-
if (type == MLXSW_SP_SPAN_EGRESS) {
696-
u32 buffsize = mlxsw_sp_span_mtu_to_buffsize(mlxsw_sp,
697-
port->dev->mtu);
698-
699-
mlxsw_reg_sbib_pack(sbib_pl, port->local_port, buffsize);
700-
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
701-
if (err) {
702-
netdev_err(port->dev, "Could not create shared buffer for mirroring\n");
703-
return err;
704-
}
705-
}
706-
707-
if (bind) {
708-
err = mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
709-
true);
710-
if (err)
711-
goto err_port_bind;
712-
}
713-
714-
inspected_port = kzalloc(sizeof(*inspected_port), GFP_KERNEL);
715-
if (!inspected_port) {
716-
err = -ENOMEM;
717-
goto err_inspected_port_alloc;
718-
}
719-
inspected_port->local_port = port->local_port;
720-
inspected_port->type = type;
721-
list_add_tail(&inspected_port->list, &span_entry->bound_ports_list);
722-
723-
return 0;
724-
725-
err_inspected_port_alloc:
726-
if (bind)
727-
mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
728-
false);
729-
err_port_bind:
730-
if (type == MLXSW_SP_SPAN_EGRESS) {
731-
mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0);
732-
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
733-
}
734-
return err;
735-
}
736-
737-
static void
738-
mlxsw_sp_span_inspected_port_del(struct mlxsw_sp_port *port,
739-
struct mlxsw_sp_span_entry *span_entry,
740-
enum mlxsw_sp_span_type type,
741-
bool bind)
742-
{
743-
struct mlxsw_sp_span_inspected_port *inspected_port;
744-
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
745-
char sbib_pl[MLXSW_REG_SBIB_LEN];
746-
747-
inspected_port = mlxsw_sp_span_entry_bound_port_find(port, span_entry);
748-
if (!inspected_port)
749-
return;
750-
751-
if (bind)
752-
mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
753-
false);
754-
/* remove the SBIB buffer if it was egress SPAN */
755-
if (type == MLXSW_SP_SPAN_EGRESS) {
756-
mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0);
757-
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
758-
}
759-
760-
mlxsw_sp_span_entry_put(mlxsw_sp, span_entry);
761-
762-
list_del(&inspected_port->list);
763-
kfree(inspected_port);
764-
}
765-
766-
int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
767-
struct mlxsw_sp_port *to,
768-
enum mlxsw_sp_span_type type, bool bind)
769-
{
770-
struct mlxsw_sp *mlxsw_sp = from->mlxsw_sp;
771-
struct mlxsw_sp_span_entry *span_entry;
772-
int err;
773-
774-
span_entry = mlxsw_sp_span_entry_get(to);
775-
if (!span_entry)
776-
return -ENOENT;
777-
778-
netdev_dbg(from->dev, "Adding inspected port to SPAN entry %d\n",
779-
span_entry->id);
780-
781-
err = mlxsw_sp_span_inspected_port_add(from, span_entry, type, bind);
782-
if (err)
783-
goto err_port_bind;
784-
785-
return 0;
786-
787-
err_port_bind:
788-
mlxsw_sp_span_entry_put(mlxsw_sp, span_entry);
789-
return err;
790-
}
791-
792-
void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, u8 destination_port,
793-
enum mlxsw_sp_span_type type, bool bind)
794-
{
795-
struct mlxsw_sp_span_entry *span_entry;
796-
797-
span_entry = mlxsw_sp_span_entry_find(from->mlxsw_sp,
798-
destination_port);
799-
if (!span_entry) {
800-
netdev_err(from->dev, "no span entry found\n");
801-
return;
802-
}
803-
804-
netdev_dbg(from->dev, "removing inspected port from SPAN entry %d\n",
805-
span_entry->id);
806-
mlxsw_sp_span_inspected_port_del(from, span_entry, type, bind);
807-
}
808-
809491
static int mlxsw_sp_port_sample_set(struct mlxsw_sp_port *mlxsw_sp_port,
810492
bool enable, u32 rate)
811493
{

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

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ enum mlxsw_sp_resource_id {
8080

8181
struct mlxsw_sp_port;
8282
struct mlxsw_sp_rif;
83+
struct mlxsw_sp_span_entry;
8384

8485
struct mlxsw_sp_upper {
8586
struct net_device *dev;
@@ -111,24 +112,6 @@ struct mlxsw_sp_mid {
111112
unsigned long *ports_in_mid; /* bits array */
112113
};
113114

114-
enum mlxsw_sp_span_type {
115-
MLXSW_SP_SPAN_EGRESS,
116-
MLXSW_SP_SPAN_INGRESS
117-
};
118-
119-
struct mlxsw_sp_span_inspected_port {
120-
struct list_head list;
121-
enum mlxsw_sp_span_type type;
122-
u8 local_port;
123-
};
124-
125-
struct mlxsw_sp_span_entry {
126-
u8 local_port;
127-
struct list_head bound_ports_list;
128-
int ref_count;
129-
int id;
130-
};
131-
132115
enum mlxsw_sp_port_mall_action_type {
133116
MLXSW_SP_PORT_MALL_MIRROR,
134117
MLXSW_SP_PORT_MALL_SAMPLE,
@@ -395,16 +378,6 @@ struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev);
395378
struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev);
396379
void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port);
397380
struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev);
398-
int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
399-
struct mlxsw_sp_port *to,
400-
enum mlxsw_sp_span_type type,
401-
bool bind);
402-
void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from,
403-
u8 destination_port,
404-
enum mlxsw_sp_span_type type,
405-
bool bind);
406-
struct mlxsw_sp_span_entry *
407-
mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port);
408381

409382
/* spectrum_dcb.c */
410383
#ifdef CONFIG_MLXSW_SPECTRUM_DCB

0 commit comments

Comments
 (0)