rtl_table_release(r);
}
+/*
+ * Reads a MAC entry for L3 termination as entry point for routing from the hardware table.
+ * idx is the index into the L3_ROUTER_MAC table
+ */
+__maybe_unused
+static void otto_l3_930x_get_router_mac(struct otto_l3_ctrl *ctrl,
+ u32 idx, struct otto_l3_router_mac *m)
+{
+ struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0);
+ u32 v, w;
+
+ rtl_table_read(r, idx);
+ /* The table has a size of 7 registers, 64 entries */
+ v = sw_r32(rtl_table_data(r, 0));
+ w = sw_r32(rtl_table_data(r, 3));
+ m->valid = !!(v & BIT(20));
+ if (!m->valid)
+ goto out;
+
+ m->p_type = !!(v & BIT(19));
+ m->p_id = (v >> 13) & 0x3f; /* trunk id of port */
+ m->vid = v & 0xfff;
+ m->vid_mask = w & 0xfff;
+ m->action = sw_r32(rtl_table_data(r, 6)) & 0x7;
+ m->mac_mask = ((((u64)sw_r32(rtl_table_data(r, 5))) << 32) & 0xffffffffffffULL) |
+ (sw_r32(rtl_table_data(r, 4)));
+ m->mac = ((((u64)sw_r32(rtl_table_data(r, 1))) << 32) & 0xffffffffffffULL) |
+ (sw_r32(rtl_table_data(r, 2)));
+ /* Bits L3_INTF and BMSK_L3_INTF are 0 */
+
+out:
+ rtl_table_release(r);
+}
+
+/*
+ * Writes a MAC entry for L3 termination as entry point for routing into the hardware table
+ * idx is the index into the L3_ROUTER_MAC table
+ */
+__maybe_unused
+static void otto_l3_930x_set_router_mac(struct otto_l3_ctrl *ctrl,
+ u32 idx, struct otto_l3_router_mac *m)
+{
+ struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0);
+ u32 v, w;
+
+ /* The table has a size of 7 registers, 64 entries */
+ v = BIT(20); /* mac entry valid, port type is 0: individual */
+ v |= (m->p_id & 0x3f) << 13;
+ v |= (m->vid & 0xfff); /* Set the interface_id to the vlan id */
+
+ w = m->vid_mask;
+ w |= (m->p_id_mask & 0x3f) << 13;
+
+ sw_w32(v, rtl_table_data(r, 0));
+ sw_w32(w, rtl_table_data(r, 3));
+
+ /* Set MAC address, L3_INTF (bit 12 in register 1) needs to be 0 */
+ sw_w32((u32)(m->mac), rtl_table_data(r, 2));
+ sw_w32(m->mac >> 32, rtl_table_data(r, 1));
+
+ /* Set MAC address mask, BMSK_L3_INTF (bit 12 in register 5) needs to be 0 */
+ sw_w32((u32)(m->mac_mask >> 32), rtl_table_data(r, 4));
+ sw_w32((u32)m->mac_mask, rtl_table_data(r, 5));
+
+ sw_w32(m->action & 0x7, rtl_table_data(r, 6));
+
+ dev_dbg(ctrl->dev, "writing index %d: %08x %08x %08x %08x %08x %08x %08x\n", idx,
+ sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)),
+ sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4)), sw_r32(rtl_table_data(r, 5)),
+ sw_r32(rtl_table_data(r, 6))
+ );
+ rtl_table_write(r, idx);
+ rtl_table_release(r);
+}
/* Destination MAC and L3 egress interface ID of a nexthop entry from the SoC's L3_NEXTHOP table */
__maybe_unused
static int otto_l3_alloc_router_mac(struct otto_l3_ctrl *ctrl, u64 mac)
{
struct rtl838x_switch_priv *priv = ctrl->priv;
- struct rtl93xx_rt_mac m;
+ struct otto_l3_router_mac m;
int free_mac = -1;
mutex_lock(&priv->reg_mutex);
for (int i = 0; i < MAX_ROUTER_MACS; i++) {
- priv->r->get_l3_router_mac(i, &m);
+ ctrl->cfg->get_router_mac(ctrl, i, &m);
if (free_mac < 0 && !m.valid) {
free_mac = i;
continue;
m.vid_mask = 0; /* ... so mask needs to be 0 */
m.mac_mask = 0xffffffffffffULL; /* We want an exact match of the interface MAC */
m.action = L3_FORWARD; /* Route the packet */
- priv->r->set_l3_router_mac(free_mac, &m);
+ ctrl->cfg->set_router_mac(ctrl, free_mac, &m);
mutex_unlock(&priv->reg_mutex);
route->prefix_len = info->dst_len;
route->nh.rvid = vlan;
- if (priv->r->set_l3_router_mac) {
+ if (ctrl->cfg->set_router_mac) {
u64 mac = ether_addr_to_u64(ndev->dev_addr);
dev_dbg(ctrl->dev, "Local route and router MAC %pM\n", ndev->dev_addr);
const struct otto_l3_config otto_l3_930x_cfg = {
#ifdef CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD
+ .get_router_mac = otto_l3_930x_get_router_mac,
+ .set_router_mac = otto_l3_930x_set_router_mac,
.get_nexthop = otto_l3_930x_get_nexthop,
.set_nexthop = otto_l3_930x_set_nexthop,
.route_lookup_hw = otto_l3_930x_route_lookup_hw,
#include "rtl-otto.h"
+/* An entry in the RTL93XX SoC's ROUTER_MAC tables setting up a termination point
+ * for the L3 routing system. Packets arriving and matching an entry in this table
+ * will be considered for routing.
+ * Mask fields state whether the corresponding data fields matter for matching
+ */
+struct otto_l3_router_mac {
+ bool valid; /* Valid or not */
+ bool p_type; /* Individual (0) or trunk (1) port */
+ bool p_mask; /* Whether the port type is used */
+ u8 p_id;
+ u8 p_id_mask; /* Mask for the port */
+ u8 action; /* Routing action performed: 0: FORWARD, 1: DROP, 2: TRAP2CPU */
+ /* 3: COPY2CPU, 4: TRAP2MASTERCPU, 5: COPY2MASTERCPU, 6: HARDDROP */
+ u16 vid;
+ u16 vid_mask;
+ u64 mac; /* MAC address used as source MAC in the routed packet */
+ u64 mac_mask;
+};
+
+
struct otto_l3_config {
+ void (*get_router_mac)(struct otto_l3_ctrl *ctrl, u32 idx, struct otto_l3_router_mac *m);
+ void (*set_router_mac)(struct otto_l3_ctrl *ctrl, u32 idx, struct otto_l3_router_mac *m);
void (*get_nexthop)(struct otto_l3_ctrl *ctrl, int idx, u16 *dmac_id, u16 *interface);
void (*set_nexthop)(struct otto_l3_ctrl *ctrl, int idx, u16 dmac_id, u16 interface);
int (*route_lookup_hw)(struct otto_l3_ctrl *ctrl, struct otto_l3_route *rt);
u8 ip6_pbr_icmp_redirect;
};
-/* An entry in the RTL93XX SoC's ROUTER_MAC tables setting up a termination point
- * for the L3 routing system. Packets arriving and matching an entry in this table
- * will be considered for routing.
- * Mask fields state whether the corresponding data fields matter for matching
- */
-struct rtl93xx_rt_mac {
- bool valid; /* Valid or not */
- bool p_type; /* Individual (0) or trunk (1) port */
- bool p_mask; /* Whether the port type is used */
- u8 p_id;
- u8 p_id_mask; /* Mask for the port */
- u8 action; /* Routing action performed: 0: FORWARD, 1: DROP, 2: TRAP2CPU */
- /* 3: COPY2CPU, 4: TRAP2MASTERCPU, 5: COPY2MASTERCPU, 6: HARDDROP */
- u16 vid;
- u16 vid_mask;
- u64 mac; /* MAC address used as source MAC in the routed packet */
- u64 mac_mask;
-};
-
struct rtl838x_switch_priv;
struct rtl83xx_flow {
u64 (*get_l3_egress_mac)(u32 idx);
void (*set_l3_egress_mac)(u32 idx, u64 mac);
int (*find_l3_slot)(struct otto_l3_route *rt, bool must_exist);
- void (*get_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m);
- void (*set_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m);
void (*set_l3_egress_intf)(int idx, struct rtl838x_l3_intf *intf);
void (*set_receive_management_action)(int port, rma_ctrl_t type, action_type_t action);
void (*led_init)(struct rtl838x_switch_priv *priv);
rtl_table_release(r);
}
-/* Reads a MAC entry for L3 termination as entry point for routing
- * from the hardware table
- * idx is the index into the L3_ROUTER_MAC table
- */
-static void rtl930x_get_l3_router_mac(u32 idx, struct rtl93xx_rt_mac *m)
-{
- u32 v, w;
- /* Read L3_ROUTER_MAC table (0) via register RTL9300_TBL_1 */
- struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0);
-
- rtl_table_read(r, idx);
- /* The table has a size of 7 registers, 64 entries */
- v = sw_r32(rtl_table_data(r, 0));
- w = sw_r32(rtl_table_data(r, 3));
- m->valid = !!(v & BIT(20));
- if (!m->valid)
- goto out;
-
- m->p_type = !!(v & BIT(19));
- m->p_id = (v >> 13) & 0x3f; /* trunk id of port */
- m->vid = v & 0xfff;
- m->vid_mask = w & 0xfff;
- m->action = sw_r32(rtl_table_data(r, 6)) & 0x7;
- m->mac_mask = ((((u64)sw_r32(rtl_table_data(r, 5))) << 32) & 0xffffffffffffULL) |
- (sw_r32(rtl_table_data(r, 4)));
- m->mac = ((((u64)sw_r32(rtl_table_data(r, 1))) << 32) & 0xffffffffffffULL) |
- (sw_r32(rtl_table_data(r, 2)));
- /* Bits L3_INTF and BMSK_L3_INTF are 0 */
-
-out:
- rtl_table_release(r);
-}
-
-/* Writes a MAC entry for L3 termination as entry point for routing
- * into the hardware table
- * idx is the index into the L3_ROUTER_MAC table
- */
-static void rtl930x_set_l3_router_mac(u32 idx, struct rtl93xx_rt_mac *m)
-{
- u32 v, w;
- /* Read L3_ROUTER_MAC table (0) via register RTL9300_TBL_1 */
- struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0);
-
- /* The table has a size of 7 registers, 64 entries */
- v = BIT(20); /* mac entry valid, port type is 0: individual */
- v |= (m->p_id & 0x3f) << 13;
- v |= (m->vid & 0xfff); /* Set the interface_id to the vlan id */
-
- w = m->vid_mask;
- w |= (m->p_id_mask & 0x3f) << 13;
-
- sw_w32(v, rtl_table_data(r, 0));
- sw_w32(w, rtl_table_data(r, 3));
-
- /* Set MAC address, L3_INTF (bit 12 in register 1) needs to be 0 */
- sw_w32((u32)(m->mac), rtl_table_data(r, 2));
- sw_w32(m->mac >> 32, rtl_table_data(r, 1));
-
- /* Set MAC address mask, BMSK_L3_INTF (bit 12 in register 5) needs to be 0 */
- sw_w32((u32)(m->mac_mask >> 32), rtl_table_data(r, 4));
- sw_w32((u32)m->mac_mask, rtl_table_data(r, 5));
-
- sw_w32(m->action & 0x7, rtl_table_data(r, 6));
-
- pr_debug("%s writing index %d: %08x %08x %08x %08x %08x %08x %08x\n", __func__, idx,
- sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)),
- sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4)), sw_r32(rtl_table_data(r, 5)),
- sw_r32(rtl_table_data(r, 6))
- );
- rtl_table_write(r, idx);
- rtl_table_release(r);
-}
-
/* Get the Destination-MAC of an L3 egress interface or the Source MAC for routed packets
* from the SoC's L3_EGR_INTF_MAC table
* Indexes 0-2047 are DMACs, 2048+ are SMACs
.get_l3_egress_mac = rtl930x_get_l3_egress_mac,
.set_l3_egress_mac = rtl930x_set_l3_egress_mac,
.find_l3_slot = rtl930x_find_l3_slot,
- .get_l3_router_mac = rtl930x_get_l3_router_mac,
- .set_l3_router_mac = rtl930x_set_l3_router_mac,
.set_l3_egress_intf = rtl930x_set_l3_egress_intf,
#endif
.led_init = rtl930x_led_init,