Skip to content

Commit 3254ce8

Browse files
committed
Merge branch 'introduce-hsr-offload-support-for-icssg'
MD Danish Anwar says: ==================== Introduce HSR offload support for ICSSG This series introduces HSR offload support for ICSSG driver. To support HSR offload to hardware, ICSSG HSR firmware is used. This series introduces, 1. HSR frame offload support for ICSSG driver. 2. HSR Tx Packet duplication offload 3. HSR Tx Tag and Rx Tag offload 4. Multicast filtering support in HSR offload mode. 5. Dependencies related to IEP. HSR Test Setup: -------------- ___________ ___________ ___________ | | Link AB | | Link BC | | __| AM64* |_________| AM64 |_________| AM64* |___ | | Station A | | Station B | | Station C | | | |___________| |___________| |___________| | | | |______________________________________________________________| Link CA *Could be any device that supports two ethernet interfaces. Steps to switch to HSR frame forward offload mode: ------------------------------------------------- Example assuming eth1, eth2 ports of ICSSG1 on AM64-EVM 1) Enable HSR offload for both interfaces ethtool -K eth1 hsr-fwd-offload on ethtool -K eth1 hsr-dup-offload on ethtool -K eth1 hsr-tag-ins-offload on ethtool -K eth1 hsr-tag-rm-offload on ethtool -K eth2 hsr-fwd-offload on ethtool -K eth2 hsr-dup-offload on ethtool -K eth2 hsr-tag-ins-offload on ethtool -K eth2 hsr-tag-rm-offload on 2) Create HSR interface and add slave interfaces to it ip link add name hsr0 type hsr slave1 eth1 slave2 eth2 \ supervision 45 version 1 3) Add IP address to the HSR interface ip addr add <IP_ADDR>/24 dev hsr0 4) Bring up the HSR interface ip link set hsr0 up Switching back to previous mode: -------------------------------- 1) Delete HSR interface ip link delete hsr0 2) Disable HSR port-to-port offloading mode, packet duplication ethtool -K eth1 hsr-fwd-offload off ethtool -K eth1 hsr-dup-offload off ethtool -K eth1 hsr-tag-ins-offload off ethtool -K eth1 hsr-tag-rm-offload off ethtool -K eth2 hsr-fwd-offload off ethtool -K eth2 hsr-dup-offload off ethtool -K eth2 hsr-tag-ins-offload off ethtool -K eth2 hsr-tag-rm-offload off Testing the port-to-port frame forward offload feature: ----------------------------------------------------- 1) Connect the LAN cables as shown in the test setup. 2) Configure Station A and Station C in HSR non-offload mode. 3) Configure Station B is HSR offload mode. 4) Since HSR is a redundancy protocol, disconnect cable "Link CA", to ensure frames from Station A reach Station C only through Station B. 5) Run iperf3 Server on Station C and client on station A. 7) Check the CPU usage on Station B. CPU usage report on Station B using mpstat when running UDP iperf3: ------------------------------------------------------------------- 1) Non-Offload case ------------------- CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle all 0.00 0.00 0.50 0.00 3.52 29.15 0.00 0.00 66.83 0 0.00 0.00 0.00 0.00 7.00 58.00 0.00 0.00 35.00 1 0.00 0.00 0.99 0.00 0.99 0.00 0.00 0.00 98.02 2) Offload case --------------- CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle all 0.00 0.00 0.00 0.00 0.50 0.00 0.00 0.00 99.50 0 0.00 0.00 0.99 0.00 0.00 0.00 0.00 0.00 99.01 1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 Note: 1) At the very least, hsr-fwd-offload must be enabled. Without offloading the port-to-port offload, other HSR offloads cannot be enabled. 2) hsr-tag-ins-offload and hsr-dup-offload are tightly coupled in the firmware implementation. They both need to be enabled / disabled together. v1: https://lore.kernel.org/[email protected]/ v2: https://lore.kernel.org/[email protected] v3: https://lore.kernel.org/[email protected]/ v4: https://lore.kernel.org/[email protected]/ v5: https://lore.kernel.org/[email protected]/ [0] https://lore.kernel.org/[email protected]/ [1] https://lore.kernel.org/[email protected]/ [2] https://lore.kernel.org/[email protected]/ [3] https://lore.kernel.org/[email protected]/ [4] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/commit/?id=e846be0fba85 ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 34c44eb + 1d6ae96 commit 3254ce8

File tree

8 files changed

+290
-92
lines changed

8 files changed

+290
-92
lines changed

drivers/net/ethernet/ti/icssg/icss_iep.c

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -53,78 +53,6 @@
5353
#define IEP_CAP_CFG_CAPNR_1ST_EVENT_EN(n) BIT(LATCH_INDEX(n))
5454
#define IEP_CAP_CFG_CAP_ASYNC_EN(n) BIT(LATCH_INDEX(n) + 10)
5555

56-
enum {
57-
ICSS_IEP_GLOBAL_CFG_REG,
58-
ICSS_IEP_GLOBAL_STATUS_REG,
59-
ICSS_IEP_COMPEN_REG,
60-
ICSS_IEP_SLOW_COMPEN_REG,
61-
ICSS_IEP_COUNT_REG0,
62-
ICSS_IEP_COUNT_REG1,
63-
ICSS_IEP_CAPTURE_CFG_REG,
64-
ICSS_IEP_CAPTURE_STAT_REG,
65-
66-
ICSS_IEP_CAP6_RISE_REG0,
67-
ICSS_IEP_CAP6_RISE_REG1,
68-
69-
ICSS_IEP_CAP7_RISE_REG0,
70-
ICSS_IEP_CAP7_RISE_REG1,
71-
72-
ICSS_IEP_CMP_CFG_REG,
73-
ICSS_IEP_CMP_STAT_REG,
74-
ICSS_IEP_CMP0_REG0,
75-
ICSS_IEP_CMP0_REG1,
76-
ICSS_IEP_CMP1_REG0,
77-
ICSS_IEP_CMP1_REG1,
78-
79-
ICSS_IEP_CMP8_REG0,
80-
ICSS_IEP_CMP8_REG1,
81-
ICSS_IEP_SYNC_CTRL_REG,
82-
ICSS_IEP_SYNC0_STAT_REG,
83-
ICSS_IEP_SYNC1_STAT_REG,
84-
ICSS_IEP_SYNC_PWIDTH_REG,
85-
ICSS_IEP_SYNC0_PERIOD_REG,
86-
ICSS_IEP_SYNC1_DELAY_REG,
87-
ICSS_IEP_SYNC_START_REG,
88-
ICSS_IEP_MAX_REGS,
89-
};
90-
91-
/**
92-
* struct icss_iep_plat_data - Plat data to handle SoC variants
93-
* @config: Regmap configuration data
94-
* @reg_offs: register offsets to capture offset differences across SoCs
95-
* @flags: Flags to represent IEP properties
96-
*/
97-
struct icss_iep_plat_data {
98-
const struct regmap_config *config;
99-
u32 reg_offs[ICSS_IEP_MAX_REGS];
100-
u32 flags;
101-
};
102-
103-
struct icss_iep {
104-
struct device *dev;
105-
void __iomem *base;
106-
const struct icss_iep_plat_data *plat_data;
107-
struct regmap *map;
108-
struct device_node *client_np;
109-
unsigned long refclk_freq;
110-
int clk_tick_time; /* one refclk tick time in ns */
111-
struct ptp_clock_info ptp_info;
112-
struct ptp_clock *ptp_clock;
113-
struct mutex ptp_clk_mutex; /* PHC access serializer */
114-
u32 def_inc;
115-
s16 slow_cmp_inc;
116-
u32 slow_cmp_count;
117-
const struct icss_iep_clockops *ops;
118-
void *clockops_data;
119-
u32 cycle_time_ns;
120-
u32 perout_enabled;
121-
bool pps_enabled;
122-
int cap_cmp_irq;
123-
u64 period;
124-
u32 latch_enable;
125-
struct work_struct work;
126-
};
127-
12856
/**
12957
* icss_iep_get_count_hi() - Get the upper 32 bit IEP counter
13058
* @iep: Pointer to structure representing IEP.

drivers/net/ethernet/ti/icssg/icss_iep.h

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,78 @@
1212
#include <linux/ptp_clock_kernel.h>
1313
#include <linux/regmap.h>
1414

15-
struct icss_iep;
15+
enum {
16+
ICSS_IEP_GLOBAL_CFG_REG,
17+
ICSS_IEP_GLOBAL_STATUS_REG,
18+
ICSS_IEP_COMPEN_REG,
19+
ICSS_IEP_SLOW_COMPEN_REG,
20+
ICSS_IEP_COUNT_REG0,
21+
ICSS_IEP_COUNT_REG1,
22+
ICSS_IEP_CAPTURE_CFG_REG,
23+
ICSS_IEP_CAPTURE_STAT_REG,
24+
25+
ICSS_IEP_CAP6_RISE_REG0,
26+
ICSS_IEP_CAP6_RISE_REG1,
27+
28+
ICSS_IEP_CAP7_RISE_REG0,
29+
ICSS_IEP_CAP7_RISE_REG1,
30+
31+
ICSS_IEP_CMP_CFG_REG,
32+
ICSS_IEP_CMP_STAT_REG,
33+
ICSS_IEP_CMP0_REG0,
34+
ICSS_IEP_CMP0_REG1,
35+
ICSS_IEP_CMP1_REG0,
36+
ICSS_IEP_CMP1_REG1,
37+
38+
ICSS_IEP_CMP8_REG0,
39+
ICSS_IEP_CMP8_REG1,
40+
ICSS_IEP_SYNC_CTRL_REG,
41+
ICSS_IEP_SYNC0_STAT_REG,
42+
ICSS_IEP_SYNC1_STAT_REG,
43+
ICSS_IEP_SYNC_PWIDTH_REG,
44+
ICSS_IEP_SYNC0_PERIOD_REG,
45+
ICSS_IEP_SYNC1_DELAY_REG,
46+
ICSS_IEP_SYNC_START_REG,
47+
ICSS_IEP_MAX_REGS,
48+
};
49+
50+
/**
51+
* struct icss_iep_plat_data - Plat data to handle SoC variants
52+
* @config: Regmap configuration data
53+
* @reg_offs: register offsets to capture offset differences across SoCs
54+
* @flags: Flags to represent IEP properties
55+
*/
56+
struct icss_iep_plat_data {
57+
const struct regmap_config *config;
58+
u32 reg_offs[ICSS_IEP_MAX_REGS];
59+
u32 flags;
60+
};
61+
62+
struct icss_iep {
63+
struct device *dev;
64+
void __iomem *base;
65+
const struct icss_iep_plat_data *plat_data;
66+
struct regmap *map;
67+
struct device_node *client_np;
68+
unsigned long refclk_freq;
69+
int clk_tick_time; /* one refclk tick time in ns */
70+
struct ptp_clock_info ptp_info;
71+
struct ptp_clock *ptp_clock;
72+
struct mutex ptp_clk_mutex; /* PHC access serializer */
73+
u32 def_inc;
74+
s16 slow_cmp_inc;
75+
u32 slow_cmp_count;
76+
const struct icss_iep_clockops *ops;
77+
void *clockops_data;
78+
u32 cycle_time_ns;
79+
u32 perout_enabled;
80+
bool pps_enabled;
81+
int cap_cmp_irq;
82+
u64 period;
83+
u32 latch_enable;
84+
struct work_struct work;
85+
};
86+
1687
extern const struct icss_iep_clockops prueth_iep_clockops;
1788

1889
/* Firmware specific clock operations */

drivers/net/ethernet/ti/icssg/icssg_classifier.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac)
290290
mac[2] << 16 | mac[3] << 24));
291291
regmap_write(miig_rt, MAC_INTERFACE_1, (u32)(mac[4] | mac[5] << 8));
292292
}
293+
EXPORT_SYMBOL_GPL(icssg_class_set_host_mac_addr);
293294

294295
void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac)
295296
{

drivers/net/ethernet/ti/icssg/icssg_common.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -660,14 +660,15 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev
660660
{
661661
struct cppi5_host_desc_t *first_desc, *next_desc, *cur_desc;
662662
struct prueth_emac *emac = netdev_priv(ndev);
663+
struct prueth *prueth = emac->prueth;
663664
struct netdev_queue *netif_txq;
664665
struct prueth_tx_chn *tx_chn;
665666
dma_addr_t desc_dma, buf_dma;
667+
u32 pkt_len, dst_tag_id;
666668
int i, ret = 0, q_idx;
667669
bool in_tx_ts = 0;
668670
int tx_ts_cookie;
669671
void **swdata;
670-
u32 pkt_len;
671672
u32 *epib;
672673

673674
pkt_len = skb_headlen(skb);
@@ -712,9 +713,20 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev
712713

713714
/* set dst tag to indicate internal qid at the firmware which is at
714715
* bit8..bit15. bit0..bit7 indicates port num for directed
715-
* packets in case of switch mode operation
716+
* packets in case of switch mode operation and port num 0
717+
* for undirected packets in case of HSR offload mode
716718
*/
717-
cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8)));
719+
dst_tag_id = emac->port_id | (q_idx << 8);
720+
721+
if (prueth->is_hsr_offload_mode &&
722+
(ndev->features & NETIF_F_HW_HSR_DUP))
723+
dst_tag_id = PRUETH_UNDIRECTED_PKT_DST_TAG;
724+
725+
if (prueth->is_hsr_offload_mode &&
726+
(ndev->features & NETIF_F_HW_HSR_TAG_INS))
727+
epib[1] |= PRUETH_UNDIRECTED_PKT_TAG_INS;
728+
729+
cppi5_desc_set_tags_ids(&first_desc->hdr, 0, dst_tag_id);
718730
k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma);
719731
cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len);
720732
swdata = cppi5_hdesc_get_swdata(first_desc);

drivers/net/ethernet/ti/icssg/icssg_config.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ static const struct map hwq_map[2][ICSSG_NUM_OTHER_QUEUES] = {
107107
},
108108
};
109109

110-
static void icssg_config_mii_init_switch(struct prueth_emac *emac)
110+
static void icssg_config_mii_init_fw_offload(struct prueth_emac *emac)
111111
{
112112
struct prueth *prueth = emac->prueth;
113113
int mii = prueth_emac_slice(emac);
@@ -278,7 +278,7 @@ static int emac_r30_is_done(struct prueth_emac *emac)
278278
return 1;
279279
}
280280

281-
static int prueth_switch_buffer_setup(struct prueth_emac *emac)
281+
static int prueth_fw_offload_buffer_setup(struct prueth_emac *emac)
282282
{
283283
struct icssg_buffer_pool_cfg __iomem *bpool_cfg;
284284
struct icssg_rxq_ctx __iomem *rxq_ctx;
@@ -424,7 +424,7 @@ static void icssg_init_emac_mode(struct prueth *prueth)
424424
icssg_class_set_host_mac_addr(prueth->miig_rt, mac);
425425
}
426426

427-
static void icssg_init_switch_mode(struct prueth *prueth)
427+
static void icssg_init_fw_offload_mode(struct prueth *prueth)
428428
{
429429
u32 addr = prueth->shram.pa + EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET;
430430
int i;
@@ -455,8 +455,8 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
455455
struct icssg_flow_cfg __iomem *flow_cfg;
456456
int ret;
457457

458-
if (prueth->is_switch_mode)
459-
icssg_init_switch_mode(prueth);
458+
if (prueth->is_switch_mode || prueth->is_hsr_offload_mode)
459+
icssg_init_fw_offload_mode(prueth);
460460
else
461461
icssg_init_emac_mode(prueth);
462462

@@ -472,8 +472,8 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
472472
regmap_update_bits(prueth->miig_rt, ICSSG_CFG_OFFSET,
473473
ICSSG_CFG_DEFAULT, ICSSG_CFG_DEFAULT);
474474
icssg_miig_set_interface_mode(prueth->miig_rt, slice, emac->phy_if);
475-
if (prueth->is_switch_mode)
476-
icssg_config_mii_init_switch(emac);
475+
if (prueth->is_switch_mode || prueth->is_hsr_offload_mode)
476+
icssg_config_mii_init_fw_offload(emac);
477477
else
478478
icssg_config_mii_init(emac);
479479
icssg_config_ipg(emac);
@@ -498,8 +498,8 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
498498
writeb(0, config + SPL_PKT_DEFAULT_PRIORITY);
499499
writeb(0, config + QUEUE_NUM_UNTAGGED);
500500

501-
if (prueth->is_switch_mode)
502-
ret = prueth_switch_buffer_setup(emac);
501+
if (prueth->is_switch_mode || prueth->is_hsr_offload_mode)
502+
ret = prueth_fw_offload_buffer_setup(emac);
503503
else
504504
ret = prueth_emac_buffer_setup(emac);
505505
if (ret)
@@ -531,7 +531,9 @@ static const struct icssg_r30_cmd emac_r32_bitmask[] = {
531531
{{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/
532532
{{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx DISABLE*/
533533
{{0xffff0010, EMAC_NONE, 0xffff0010, EMAC_NONE}}, /* VLAN AWARE*/
534-
{{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}} /* VLAN UNWARE*/
534+
{{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}}, /* VLAN UNWARE*/
535+
{{0xffff2000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* HSR_RX_OFFLOAD_ENABLE */
536+
{{0xdfff0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}} /* HSR_RX_OFFLOAD_DISABLE */
535537
};
536538

537539
int icssg_set_port_state(struct prueth_emac *emac,

drivers/net/ethernet/ti/icssg/icssg_config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ enum icssg_port_state_cmd {
8080
ICSSG_EMAC_PORT_PREMPT_TX_DISABLE,
8181
ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE,
8282
ICSSG_EMAC_PORT_VLAN_AWARE_DISABLE,
83+
ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE,
84+
ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE,
8385
ICSSG_EMAC_PORT_MAX_COMMANDS
8486
};
8587

0 commit comments

Comments
 (0)