armada: initial DSA support
Type: feature Change-Id: Ic6578e0ded33ca3c6590c8e6127ec11a0f5b3057 Signed-off-by: Damjan Marion <damarion@cisco.com>
This commit is contained in:
@ -152,9 +152,24 @@ format_mvpp2_rx_desc (u8 *s, va_list *args)
|
||||
s = format (s, " ");
|
||||
|
||||
foreach_pp2_rx_desc_field;
|
||||
#undef _
|
||||
return s;
|
||||
}
|
||||
|
||||
u8 *
|
||||
format_mv_dsa_tag (u8 *s, va_list *args)
|
||||
{
|
||||
mv_dsa_tag_t *tag = va_arg (*args, mv_dsa_tag_t *);
|
||||
u32 cnt = 0;
|
||||
|
||||
#define _(b, n) \
|
||||
if (#n[0] != '_') \
|
||||
s = format (s, "%s" #n " %u", cnt++ ? " " : "", tag->n);
|
||||
foreach_mv_dsa_tag_field
|
||||
#undef _
|
||||
return s;
|
||||
}
|
||||
|
||||
u8 *
|
||||
format_mvpp2_rx_trace (u8 *s, va_list *args)
|
||||
{
|
||||
@ -162,15 +177,22 @@ format_mvpp2_rx_trace (u8 *s, va_list *args)
|
||||
vlib_node_t *node = va_arg (*args, vlib_node_t *);
|
||||
mvpp2_rx_trace_t *t = va_arg (*args, mvpp2_rx_trace_t *);
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
u32 hw_if_index = t->rxq->port->intf.hw_if_index;
|
||||
vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
|
||||
u32 indent = format_get_indent (s);
|
||||
struct pp2_ppio_desc *d = &t->desc;
|
||||
|
||||
s = format (s, "pp2: %v (%d) next-node %U", hi->name, hw_if_index,
|
||||
format_vlib_next_node_name, vm, node->index, t->rxq->next_index);
|
||||
if (t->sw_if_index != CLIB_U32_MAX)
|
||||
s = format (s, "pp2: %U (%d) next-node %U", format_vnet_sw_if_index_name,
|
||||
vnm, t->sw_if_index, t->sw_if_index,
|
||||
format_vlib_next_node_name, vm, node->index, t->next_index);
|
||||
else
|
||||
s = format (s, "pp2: next-node %U", format_vlib_next_node_name, vm,
|
||||
node->index, t->next_index);
|
||||
|
||||
s = format (s, "\n%U%U", format_white_space, indent + 2,
|
||||
format_mvpp2_rx_desc, d);
|
||||
if (t->dsa_tag.as_u32)
|
||||
s = format (s, "\n%Udsa tag: %U", format_white_space, indent + 2,
|
||||
format_mv_dsa_tag, &t->dsa_tag);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -201,6 +201,7 @@ mvpp2_init (vlib_main_t *vm, vnet_dev_t *dev)
|
||||
vnet_dev_rv_t rv = VNET_DEV_OK;
|
||||
vnet_dev_bus_platform_device_data_t *dd = vnet_dev_get_bus_data (dev);
|
||||
clib_dt_node_t *sc;
|
||||
clib_dt_node_t *sw = 0;
|
||||
int pp_id = -1;
|
||||
|
||||
if (!clib_dt_node_is_compatible (dd->node, "marvell,armada-7k-pp22"))
|
||||
@ -219,12 +220,55 @@ mvpp2_init (vlib_main_t *vm, vnet_dev_t *dev)
|
||||
if (pp_id < 0)
|
||||
return VNET_DEV_ERR_UNKNOWN_DEVICE;
|
||||
|
||||
foreach_clib_dt_tree_node (n, clib_dt_get_root_node (sc))
|
||||
if (clib_dt_node_is_compatible (n, "marvell,mv88e6190") ||
|
||||
clib_dt_node_is_compatible (n, "marvell,mv88e6393x"))
|
||||
{
|
||||
clib_dt_node_t *ports;
|
||||
sw = n;
|
||||
log_debug (dev, "found mv88e6190 compatible switch at %v", n->path);
|
||||
ports = clib_dt_get_child_node (sw, "ports");
|
||||
foreach_clib_dt_child_node (pn, ports)
|
||||
{
|
||||
u32 reg = CLIB_U32_MAX;
|
||||
char *label = "(no label)";
|
||||
clib_dt_property_t *p;
|
||||
clib_dt_node_t *n;
|
||||
|
||||
p = clib_dt_get_node_property_by_name (pn, "reg");
|
||||
if (p)
|
||||
reg = clib_dt_property_get_u32 (p);
|
||||
p = clib_dt_get_node_property_by_name (pn, "label");
|
||||
if (p)
|
||||
label = clib_dt_property_get_string (p);
|
||||
|
||||
log_debug (dev, "port %u label %s", reg, label);
|
||||
|
||||
n = clib_dt_dereference_node (pn, "phy-handle");
|
||||
if (n)
|
||||
log_debug (dev, " phy is %v", n->path);
|
||||
|
||||
n = clib_dt_dereference_node (pn, "sfp");
|
||||
if (n)
|
||||
log_debug (dev, " sfp is %v", n->path);
|
||||
|
||||
n = clib_dt_dereference_node (pn, "ethernet");
|
||||
if (n)
|
||||
log_debug (dev, " connected to %v", n->path);
|
||||
|
||||
p = clib_dt_get_node_property_by_name (pn, "phy-mode");
|
||||
if (p)
|
||||
log_debug (dev, " phy mode is %s",
|
||||
clib_dt_property_get_string (p));
|
||||
}
|
||||
}
|
||||
|
||||
if ((mvpp2_global_init (vm, dev)) != VNET_DEV_OK)
|
||||
return rv;
|
||||
|
||||
md->pp_id = pp_id;
|
||||
|
||||
vec_foreach_pointer (cn, dd->node->child_nodes)
|
||||
foreach_clib_dt_child_node (cn, dd->node)
|
||||
{
|
||||
clib_dt_property_t *p;
|
||||
char netdev_name[IFNAMSIZ];
|
||||
@ -271,6 +315,28 @@ mvpp2_init (vlib_main_t *vm, vnet_dev_t *dev)
|
||||
.ppio_id = ppio_id,
|
||||
};
|
||||
|
||||
if (sw)
|
||||
{
|
||||
clib_dt_node_t *ports = clib_dt_get_child_node (sw, "ports");
|
||||
if (ports)
|
||||
foreach_clib_dt_child_node (sp, ports)
|
||||
{
|
||||
clib_dt_node_t *eth;
|
||||
|
||||
eth = clib_dt_dereference_node (sp, "ethernet");
|
||||
|
||||
if (cn != eth)
|
||||
continue;
|
||||
|
||||
mvpp2_port.is_dsa = 1;
|
||||
mvpp2_port.switch_node = sw;
|
||||
mvpp2_port.switch_port_node = sp;
|
||||
log_debug (dev, "port is connected to switch port %v",
|
||||
sp->path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vnet_dev_port_add_args_t port_add_args = {
|
||||
.port = {
|
||||
.attr = {
|
||||
@ -278,12 +344,15 @@ mvpp2_init (vlib_main_t *vm, vnet_dev_t *dev)
|
||||
.max_rx_queues = PP2_PPIO_MAX_NUM_INQS,
|
||||
.max_tx_queues = PP2_PPIO_MAX_NUM_OUTQS,
|
||||
.max_supported_rx_frame_size = 9216,
|
||||
.caps.secondary_interfaces = mvpp2_port.is_dsa != 0,
|
||||
},
|
||||
.ops = {
|
||||
.init = mvpp2_port_init,
|
||||
.deinit = mvpp2_port_deinit,
|
||||
.start = mvpp2_port_start,
|
||||
.stop = mvpp2_port_stop,
|
||||
.add_sec_if = mvpp2_port_add_sec_if,
|
||||
.del_sec_if = mvpp2_port_del_sec_if,
|
||||
.config_change = mvpp2_port_cfg_change,
|
||||
.config_change_validate = mvpp2_port_cfg_change_validate,
|
||||
.format_status = format_mvpp2_port_status,
|
||||
@ -291,6 +360,10 @@ mvpp2_init (vlib_main_t *vm, vnet_dev_t *dev)
|
||||
},
|
||||
.data_size = sizeof (mvpp2_port_t),
|
||||
.initial_data = &mvpp2_port,
|
||||
.sec_if_args = VNET_DEV_ARGS (
|
||||
VNET_DEV_ARG_UINT32 (MVPP2_SEC_IF_ARG_DSA_SWITCH, "dsa_switch", "DSA source switch ID", .max= 31),
|
||||
VNET_DEV_ARG_UINT32 (MVPP2_SEC_IF_ARG_DSA_PORT, "dsa_port", "DSA source switch port ID", .max = 31)
|
||||
),
|
||||
},
|
||||
.rx_node = &mvpp2_rx_node,
|
||||
.tx_node = &mvpp2_tx_node,
|
||||
|
@ -76,6 +76,9 @@ mvpp2_port_init (vlib_main_t *vm, vnet_dev_port_t *port)
|
||||
|
||||
log_debug (dev, "port %u %U", port->port_id, format_pp2_ppio_link_info, &li);
|
||||
|
||||
for (u32 i = 0; i < VLIB_FRAME_SIZE; i++)
|
||||
mp->desc_ptrs[i] = mp->descs + i;
|
||||
|
||||
mvpp2_port_add_counters (vm, port);
|
||||
|
||||
done:
|
||||
@ -206,6 +209,68 @@ mvpp2_port_stop (vlib_main_t *vm, vnet_dev_port_t *port)
|
||||
}
|
||||
}
|
||||
|
||||
vnet_dev_rv_t
|
||||
mvpp2_port_add_sec_if (vlib_main_t *vm, vnet_dev_port_t *port, void *p)
|
||||
{
|
||||
vnet_dev_port_interface_t *sif = p;
|
||||
mvpp2_port_t *mp = vnet_dev_get_port_data (port);
|
||||
u32 port_id = CLIB_U32_MAX, switch_id = 0, index;
|
||||
|
||||
if (mp->is_dsa == 0)
|
||||
return VNET_DEV_ERR_NOT_SUPPORTED;
|
||||
|
||||
foreach_vnet_dev_args (a, sif)
|
||||
{
|
||||
switch (a->id)
|
||||
{
|
||||
case MVPP2_SEC_IF_ARG_DSA_PORT:
|
||||
if (a->val_set)
|
||||
port_id = vnet_dev_arg_get_uint32 (a);
|
||||
break;
|
||||
case MVPP2_SEC_IF_ARG_DSA_SWITCH:
|
||||
switch_id = vnet_dev_arg_get_uint32 (a);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (port_id == CLIB_U32_MAX)
|
||||
{
|
||||
log_err (port->dev, "missing dsa_port argument");
|
||||
return VNET_DEV_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
log_debug (port->dev, "switch %u port %u", switch_id, port_id);
|
||||
|
||||
mv_dsa_tag_t tag = {
|
||||
.tag_type = MV_DSA_TAG_TYPE_FROM_CPU,
|
||||
.src_port_or_lag = port_id,
|
||||
.src_dev = switch_id,
|
||||
};
|
||||
|
||||
index = switch_id << 5 | port_id;
|
||||
|
||||
sif->user_data = tag.as_u32;
|
||||
uword_bitmap_set_bits_at_index (mp->valid_dsa_src_bitmap, index, 1);
|
||||
mp->dsa_to_sec_if[index] = sif->index;
|
||||
return VNET_DEV_OK;
|
||||
}
|
||||
|
||||
vnet_dev_rv_t
|
||||
mvpp2_port_del_sec_if (vlib_main_t *vm, vnet_dev_port_t *port, void *p)
|
||||
{
|
||||
vnet_dev_port_interface_t *sif = p;
|
||||
mvpp2_port_t *mp = vnet_dev_get_port_data (port);
|
||||
mv_dsa_tag_t tag = { .as_u32 = sif->user_data };
|
||||
u32 index = tag.src_dev << 5 | tag.src_port_or_lag;
|
||||
|
||||
log_debug (port->dev, "switch %u port %u", tag.src_dev, tag.src_port_or_lag);
|
||||
|
||||
uword_bitmap_clear_bits_at_index (mp->valid_dsa_src_bitmap, index, 1);
|
||||
return VNET_DEV_OK;
|
||||
}
|
||||
|
||||
vnet_dev_rv_t
|
||||
mvpp2_port_cfg_change_validate (vlib_main_t *vm, vnet_dev_port_t *port,
|
||||
vnet_dev_port_cfg_change_req_t *req)
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <vppinfra/clib.h>
|
||||
#include <vppinfra/error_bootstrap.h>
|
||||
#include <vppinfra/format.h>
|
||||
#include <vppinfra/devicetree.h>
|
||||
#include <vnet/vnet.h>
|
||||
#include <vnet/dev/dev.h>
|
||||
|
||||
@ -29,6 +30,58 @@
|
||||
#define MVPP2_NUM_BPOOLS 16
|
||||
#define MVPP2_MAX_THREADS 4
|
||||
#define MRVL_PP2_BUFF_BATCH_SZ 32
|
||||
#define MV_DSA_N_SRC 32
|
||||
|
||||
#define foreach_mv_dsa_tag_field \
|
||||
_ (12, vid) \
|
||||
_ (1, _zero13) \
|
||||
_ (3, pri) \
|
||||
_ (1, cfi_dei) \
|
||||
_ (1, _unused17) \
|
||||
_ (1, src_is_lag) \
|
||||
_ (5, src_port_or_lag) \
|
||||
_ (5, src_dev) \
|
||||
_ (1, src_tagged) \
|
||||
_ (2, tag_type)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MV_DSA_TAG_TYPE_TO_CPU = 0,
|
||||
MV_DSA_TAG_TYPE_FROM_CPU = 1,
|
||||
MV_DSA_TAG_TYPE_TO_SNIFFER = 2,
|
||||
MV_DSA_TAG_TYPE_FORWARD = 3
|
||||
} mv_dsa_tag_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MVPP2_SEC_IF_ARG_DSA_SWITCH,
|
||||
MVPP2_SEC_IF_ARG_DSA_PORT
|
||||
} mvpp2_sec_if_args_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
#define _(b, n) u32 (n) : (b);
|
||||
foreach_mv_dsa_tag_field
|
||||
#undef _
|
||||
};
|
||||
u32 as_u32;
|
||||
} mv_dsa_tag_t;
|
||||
|
||||
STATIC_ASSERT_SIZEOF (mv_dsa_tag_t, 4);
|
||||
|
||||
static_always_inline mv_dsa_tag_t
|
||||
mv_dsa_tag_read (void *p)
|
||||
{
|
||||
return (mv_dsa_tag_t){ .as_u32 = clib_net_to_host_u32 (*(u32u *) p) };
|
||||
}
|
||||
|
||||
static_always_inline void
|
||||
mv_dsa_tag_write (void *p, mv_dsa_tag_t tag)
|
||||
{
|
||||
((mv_dsa_tag_t *) p)->as_u32 = clib_host_to_net_u32 (tag.as_u32);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -49,6 +102,13 @@ typedef struct
|
||||
struct pp2_ppio *ppio;
|
||||
u8 ppio_id;
|
||||
struct pp2_ppio_link_info last_link_info;
|
||||
clib_dt_node_t *switch_node;
|
||||
clib_dt_node_t *switch_port_node;
|
||||
|
||||
struct pp2_ppio_desc descs[VLIB_FRAME_SIZE];
|
||||
struct pp2_ppio_desc *desc_ptrs[VLIB_FRAME_SIZE];
|
||||
uword valid_dsa_src_bitmap[1024 / uword_bits];
|
||||
u16 dsa_to_sec_if[1024];
|
||||
} mvpp2_port_t;
|
||||
|
||||
typedef struct
|
||||
@ -65,7 +125,9 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
struct pp2_ppio_desc desc;
|
||||
vnet_dev_rx_queue_t *rxq;
|
||||
u32 sw_if_index;
|
||||
u16 next_index;
|
||||
mv_dsa_tag_t dsa_tag;
|
||||
} mvpp2_rx_trace_t;
|
||||
|
||||
/* counters.c */
|
||||
@ -81,12 +143,15 @@ format_function_t format_mvpp2_port_status;
|
||||
format_function_t format_mvpp2_dev_info;
|
||||
format_function_t format_mvpp2_rx_trace;
|
||||
format_function_t format_mvpp2_rx_desc;
|
||||
format_function_t format_mv_dsa_tag;
|
||||
|
||||
/* port.c */
|
||||
vnet_dev_port_op_t mvpp2_port_init;
|
||||
vnet_dev_port_op_no_rv_t mvpp2_port_deinit;
|
||||
vnet_dev_port_op_t mvpp2_port_start;
|
||||
vnet_dev_port_op_no_rv_t mvpp2_port_stop;
|
||||
vnet_dev_port_op_with_ptr_t mvpp2_port_add_sec_if;
|
||||
vnet_dev_port_op_with_ptr_t mvpp2_port_del_sec_if;
|
||||
vnet_dev_rv_t mvpp2_port_cfg_change (vlib_main_t *, vnet_dev_port_t *,
|
||||
vnet_dev_port_cfg_change_req_t *);
|
||||
vnet_dev_rv_t
|
||||
@ -135,6 +200,7 @@ typedef enum
|
||||
"pp2_bpool_get_num_buffs error") \
|
||||
_ (BPOOL_PUT_BUFFS, bpool_put_buffs, ERROR, "pp2_bpool_put_buffs error") \
|
||||
_ (BUFFER_ALLOC, buffer_alloc, ERROR, "buffer alloc error") \
|
||||
_ (UNKNOWN_DSA_SRC, unknown_dsa_src, ERROR, "unknown DSA source") \
|
||||
_ (MAC_CE, mac_ce, ERROR, "MAC error (CRC error)") \
|
||||
_ (MAC_OR, mac_or, ERROR, "overrun error") \
|
||||
_ (MAC_RSVD, mac_rsvd, ERROR, "unknown MAC error") \
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,6 +12,7 @@ VNET_DEV_NODE_FN (mvpp2_tx_node)
|
||||
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
|
||||
{
|
||||
vnet_dev_tx_node_runtime_t *rt = vnet_dev_get_tx_node_runtime (node);
|
||||
vnet_dev_instance_t *ins = vnet_dev_get_dev_instance (rt->dev_instance);
|
||||
vnet_dev_tx_queue_t *txq = rt->tx_queue;
|
||||
vnet_dev_port_t *port = txq->port;
|
||||
vnet_dev_t *dev = port->dev;
|
||||
@ -27,6 +28,24 @@ VNET_DEV_NODE_FN (mvpp2_tx_node)
|
||||
struct pp2_ppio_desc descs[VLIB_FRAME_SIZE], *d = descs;
|
||||
u16 sz = txq->size;
|
||||
u16 mask = sz - 1;
|
||||
i16 len_adj = 0;
|
||||
|
||||
if (ins->is_primary_if == 0)
|
||||
{
|
||||
vnet_dev_port_interface_t *sif =
|
||||
vnet_dev_port_get_sec_if_by_index (port, ins->sec_if_index);
|
||||
|
||||
mv_dsa_tag_t tag = { .as_u32 = sif->user_data };
|
||||
|
||||
for (u32 i = 0; i < n_vectors; i++)
|
||||
{
|
||||
vlib_buffer_t *b = vlib_get_buffer (vm, buffers[i]);
|
||||
u8 *start = vlib_buffer_get_current (b);
|
||||
clib_memmove (start - 4, start, 12);
|
||||
mv_dsa_tag_write (start + 8, tag);
|
||||
}
|
||||
len_adj = 4;
|
||||
}
|
||||
|
||||
if (mtq->n_enq)
|
||||
{
|
||||
@ -51,9 +70,9 @@ VNET_DEV_NODE_FN (mvpp2_tx_node)
|
||||
u64 paddr = vlib_buffer_get_pa (vm, b0);
|
||||
|
||||
pp2_ppio_outq_desc_reset (d);
|
||||
pp2_ppio_outq_desc_set_phys_addr (d, paddr + b0->current_data);
|
||||
pp2_ppio_outq_desc_set_phys_addr (d, paddr + b0->current_data - len_adj);
|
||||
pp2_ppio_outq_desc_set_pkt_offset (d, 0);
|
||||
pp2_ppio_outq_desc_set_pkt_len (d, b0->current_length);
|
||||
pp2_ppio_outq_desc_set_pkt_len (d, b0->current_length + len_adj);
|
||||
}
|
||||
|
||||
buffers = vlib_frame_vector_args (frame);
|
||||
|
Reference in New Issue
Block a user