Message ID | 20240906111538.1259418-5-danishanwar@ti.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Introduce HSR offload support for ICSSG | expand |
On 06/09/2024 14:15, MD Danish Anwar wrote: > From: Ravi Gunasekaran <r-gunasekaran@ti.com> > > The HSR stack allows to offload its Tx packet duplication functionality to > the hardware. Enable this offloading feature for ICSSG driver. Add support > to offload HSR Tx Tag Insertion and Rx Tag Removal and duplicate discard. > > Inorder to enable hsr-tag-ins-offload, hsr-dup-offload must also be enabled "In order" > as these are tightly coupled in the firmware implementation. > > Duplicate discard is done as part of RX tag removal and it is > done by the firmware. When driver sends the r30 command > ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE, firmware does RX tag removal as well as > duplicate discard. > > Signed-off-by: Ravi Gunasekaran <r-gunasekaran@ti.com> > Signed-off-by: MD Danish Anwar <danishanwar@ti.com> > --- > drivers/net/ethernet/ti/icssg/icssg_common.c | 18 ++++++++++--- > drivers/net/ethernet/ti/icssg/icssg_config.c | 4 ++- > drivers/net/ethernet/ti/icssg/icssg_config.h | 2 ++ > drivers/net/ethernet/ti/icssg/icssg_prueth.c | 28 +++++++++++++++++++- > drivers/net/ethernet/ti/icssg/icssg_prueth.h | 3 +++ > 5 files changed, 50 insertions(+), 5 deletions(-) > > diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c > index b9d8a93d1680..fdebeb2f84e0 100644 > --- a/drivers/net/ethernet/ti/icssg/icssg_common.c > +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c > @@ -660,14 +660,15 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev > { > struct cppi5_host_desc_t *first_desc, *next_desc, *cur_desc; > struct prueth_emac *emac = netdev_priv(ndev); > + struct prueth *prueth = emac->prueth; > struct netdev_queue *netif_txq; > struct prueth_tx_chn *tx_chn; > dma_addr_t desc_dma, buf_dma; > + u32 pkt_len, dst_tag_id; > int i, ret = 0, q_idx; > bool in_tx_ts = 0; > int tx_ts_cookie; > void **swdata; > - u32 pkt_len; > u32 *epib; > > pkt_len = skb_headlen(skb); > @@ -712,9 +713,20 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev > > /* set dst tag to indicate internal qid at the firmware which is at > * bit8..bit15. bit0..bit7 indicates port num for directed > - * packets in case of switch mode operation > + * packets in case of switch mode operation and port num 0 > + * for undirected packets in case of HSR offload mode > */ > - cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8))); > + dst_tag_id = emac->port_id | (q_idx << 8); > + > + if (prueth->is_hsr_offload_mode && > + (ndev->features & NETIF_F_HW_HSR_DUP)) > + dst_tag_id = PRUETH_UNDIRECTED_PKT_DST_TAG; > + > + if (prueth->is_hsr_offload_mode && > + (ndev->features & NETIF_F_HW_HSR_TAG_INS)) > + epib[1] |= PRUETH_UNDIRECTED_PKT_TAG_INS; > + > + cppi5_desc_set_tags_ids(&first_desc->hdr, 0, dst_tag_id); > k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma); > cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len); > swdata = cppi5_hdesc_get_swdata(first_desc); > diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c > index 7b2e6c192ff3..72ace151d8e9 100644 > --- a/drivers/net/ethernet/ti/icssg/icssg_config.c > +++ b/drivers/net/ethernet/ti/icssg/icssg_config.c > @@ -531,7 +531,9 @@ static const struct icssg_r30_cmd emac_r32_bitmask[] = { > {{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/ > {{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx DISABLE*/ > {{0xffff0010, EMAC_NONE, 0xffff0010, EMAC_NONE}}, /* VLAN AWARE*/ > - {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}} /* VLAN UNWARE*/ > + {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}}, /* VLAN UNWARE*/ > + {{0xffff2000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* HSR_RX_OFFLOAD_ENABLE */ > + {{0xdfff0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}} /* HSR_RX_OFFLOAD_DISABLE */ > }; > > int icssg_set_port_state(struct prueth_emac *emac, > diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.h b/drivers/net/ethernet/ti/icssg/icssg_config.h > index 1ac60283923b..92c2deaa3068 100644 > --- a/drivers/net/ethernet/ti/icssg/icssg_config.h > +++ b/drivers/net/ethernet/ti/icssg/icssg_config.h > @@ -80,6 +80,8 @@ enum icssg_port_state_cmd { > ICSSG_EMAC_PORT_PREMPT_TX_DISABLE, > ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE, > ICSSG_EMAC_PORT_VLAN_AWARE_DISABLE, > + ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE, > + ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE, > ICSSG_EMAC_PORT_MAX_COMMANDS > }; > > diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c > index 676168d6fded..9af06454ba64 100644 > --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c > +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c > @@ -41,7 +41,10 @@ > #define DEFAULT_PORT_MASK 1 > #define DEFAULT_UNTAG_MASK 1 > > -#define NETIF_PRUETH_HSR_OFFLOAD_FEATURES NETIF_F_HW_HSR_FWD > +#define NETIF_PRUETH_HSR_OFFLOAD_FEATURES (NETIF_F_HW_HSR_FWD | \ > + NETIF_F_HW_HSR_DUP | \ > + NETIF_F_HW_HSR_TAG_INS | \ > + NETIF_F_HW_HSR_TAG_RM) > > /* CTRLMMR_ICSSG_RGMII_CTRL register bits */ > #define ICSSG_CTRL_RGMII_ID_MODE BIT(24) > @@ -758,6 +761,21 @@ static void emac_change_hsr_feature(struct net_device *ndev, > } > } > > +static netdev_features_t emac_ndo_fix_features(struct net_device *ndev, > + netdev_features_t features) > +{ > + /* In order to enable hsr tag insertion offload, hsr dup offload must > + * also be enabled as these two are tightly coupled in firmware > + * implementation. > + */ > + if (features & NETIF_F_HW_HSR_TAG_INS) > + features |= NETIF_F_HW_HSR_DUP; What if only NETIF_F_HW_HSR_DUP was set? Don't you have to set NETIF_F_HW_HSR_TAG_INS as well? > + else > + features &= ~NETIF_F_HW_HSR_DUP; what if NETIF_F_HW_HSR_DUP was still set? I think you need to write a logic like follows. if both are already cleared in ndev->features and any one is set in features you set both in features. if both are already set in ndev->features and any one is cleared in features you clear both in features. is this reasonable? > + > + return features; > +} > + > static int emac_ndo_set_features(struct net_device *ndev, > netdev_features_t features) > { > @@ -780,6 +798,7 @@ static const struct net_device_ops emac_netdev_ops = { > .ndo_eth_ioctl = icssg_ndo_ioctl, > .ndo_get_stats64 = icssg_ndo_get_stats64, > .ndo_get_phys_port_name = icssg_ndo_get_phys_port_name, > + .ndo_fix_features = emac_ndo_fix_features, > .ndo_set_features = emac_ndo_set_features, > }; > > @@ -1007,6 +1026,13 @@ static void icssg_change_mode(struct prueth *prueth) > > for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) { > emac = prueth->emac[mac]; > + if (prueth->is_hsr_offload_mode) { > + if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM) > + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE); > + else > + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE); > + } > + > if (netif_running(emac->ndev)) { > icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan, > ICSSG_FDB_ENTRY_P0_MEMBERSHIP | > diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h > index a4b025fae797..bba6da2e6bd8 100644 > --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h > +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h > @@ -59,6 +59,9 @@ > > #define IEP_DEFAULT_CYCLE_TIME_NS 1000000 /* 1 ms */ > > +#define PRUETH_UNDIRECTED_PKT_DST_TAG 0 > +#define PRUETH_UNDIRECTED_PKT_TAG_INS BIT(30) > + > /* Firmware status codes */ > #define ICSS_HS_FW_READY 0x55555555 > #define ICSS_HS_FW_DEAD 0xDEAD0000 /* lower 16 bits contain error code */
Hi Roger, On 9/10/2024 11:08 PM, Roger Quadros wrote: > > > On 06/09/2024 14:15, MD Danish Anwar wrote: >> From: Ravi Gunasekaran <r-gunasekaran@ti.com> >> >> The HSR stack allows to offload its Tx packet duplication functionality to >> the hardware. Enable this offloading feature for ICSSG driver. Add support >> to offload HSR Tx Tag Insertion and Rx Tag Removal and duplicate discard. >> >> Inorder to enable hsr-tag-ins-offload, hsr-dup-offload must also be enabled > > "In order" > >> as these are tightly coupled in the firmware implementation. >> >> Duplicate discard is done as part of RX tag removal and it is >> done by the firmware. When driver sends the r30 command >> ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE, firmware does RX tag removal as well as >> duplicate discard. >> >> Signed-off-by: Ravi Gunasekaran <r-gunasekaran@ti.com> >> Signed-off-by: MD Danish Anwar <danishanwar@ti.com> >> --- >> drivers/net/ethernet/ti/icssg/icssg_common.c | 18 ++++++++++--- >> drivers/net/ethernet/ti/icssg/icssg_config.c | 4 ++- >> drivers/net/ethernet/ti/icssg/icssg_config.h | 2 ++ >> drivers/net/ethernet/ti/icssg/icssg_prueth.c | 28 +++++++++++++++++++- >> drivers/net/ethernet/ti/icssg/icssg_prueth.h | 3 +++ >> 5 files changed, 50 insertions(+), 5 deletions(-) >> >> diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c >> index b9d8a93d1680..fdebeb2f84e0 100644 >> --- a/drivers/net/ethernet/ti/icssg/icssg_common.c >> +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c >> @@ -660,14 +660,15 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev >> { >> struct cppi5_host_desc_t *first_desc, *next_desc, *cur_desc; >> struct prueth_emac *emac = netdev_priv(ndev); >> + struct prueth *prueth = emac->prueth; >> struct netdev_queue *netif_txq; >> struct prueth_tx_chn *tx_chn; >> dma_addr_t desc_dma, buf_dma; >> + u32 pkt_len, dst_tag_id; >> int i, ret = 0, q_idx; >> bool in_tx_ts = 0; >> int tx_ts_cookie; >> void **swdata; >> - u32 pkt_len; >> u32 *epib; >> >> pkt_len = skb_headlen(skb); >> @@ -712,9 +713,20 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev >> >> /* set dst tag to indicate internal qid at the firmware which is at >> * bit8..bit15. bit0..bit7 indicates port num for directed >> - * packets in case of switch mode operation >> + * packets in case of switch mode operation and port num 0 >> + * for undirected packets in case of HSR offload mode >> */ >> - cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8))); >> + dst_tag_id = emac->port_id | (q_idx << 8); >> + >> + if (prueth->is_hsr_offload_mode && >> + (ndev->features & NETIF_F_HW_HSR_DUP)) >> + dst_tag_id = PRUETH_UNDIRECTED_PKT_DST_TAG; >> + >> + if (prueth->is_hsr_offload_mode && >> + (ndev->features & NETIF_F_HW_HSR_TAG_INS)) >> + epib[1] |= PRUETH_UNDIRECTED_PKT_TAG_INS; >> + >> + cppi5_desc_set_tags_ids(&first_desc->hdr, 0, dst_tag_id); >> k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma); >> cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len); >> swdata = cppi5_hdesc_get_swdata(first_desc); >> diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c >> index 7b2e6c192ff3..72ace151d8e9 100644 >> --- a/drivers/net/ethernet/ti/icssg/icssg_config.c >> +++ b/drivers/net/ethernet/ti/icssg/icssg_config.c >> @@ -531,7 +531,9 @@ static const struct icssg_r30_cmd emac_r32_bitmask[] = { >> {{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/ >> {{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx DISABLE*/ >> {{0xffff0010, EMAC_NONE, 0xffff0010, EMAC_NONE}}, /* VLAN AWARE*/ >> - {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}} /* VLAN UNWARE*/ >> + {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}}, /* VLAN UNWARE*/ >> + {{0xffff2000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* HSR_RX_OFFLOAD_ENABLE */ >> + {{0xdfff0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}} /* HSR_RX_OFFLOAD_DISABLE */ >> }; >> >> int icssg_set_port_state(struct prueth_emac *emac, >> diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.h b/drivers/net/ethernet/ti/icssg/icssg_config.h >> index 1ac60283923b..92c2deaa3068 100644 >> --- a/drivers/net/ethernet/ti/icssg/icssg_config.h >> +++ b/drivers/net/ethernet/ti/icssg/icssg_config.h >> @@ -80,6 +80,8 @@ enum icssg_port_state_cmd { >> ICSSG_EMAC_PORT_PREMPT_TX_DISABLE, >> ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE, >> ICSSG_EMAC_PORT_VLAN_AWARE_DISABLE, >> + ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE, >> + ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE, >> ICSSG_EMAC_PORT_MAX_COMMANDS >> }; >> >> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c >> index 676168d6fded..9af06454ba64 100644 >> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c >> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c >> @@ -41,7 +41,10 @@ >> #define DEFAULT_PORT_MASK 1 >> #define DEFAULT_UNTAG_MASK 1 >> >> -#define NETIF_PRUETH_HSR_OFFLOAD_FEATURES NETIF_F_HW_HSR_FWD >> +#define NETIF_PRUETH_HSR_OFFLOAD_FEATURES (NETIF_F_HW_HSR_FWD | \ >> + NETIF_F_HW_HSR_DUP | \ >> + NETIF_F_HW_HSR_TAG_INS | \ >> + NETIF_F_HW_HSR_TAG_RM) >> >> /* CTRLMMR_ICSSG_RGMII_CTRL register bits */ >> #define ICSSG_CTRL_RGMII_ID_MODE BIT(24) >> @@ -758,6 +761,21 @@ static void emac_change_hsr_feature(struct net_device *ndev, >> } >> } >> >> +static netdev_features_t emac_ndo_fix_features(struct net_device *ndev, >> + netdev_features_t features) >> +{ >> + /* In order to enable hsr tag insertion offload, hsr dup offload must >> + * also be enabled as these two are tightly coupled in firmware >> + * implementation. >> + */ >> + if (features & NETIF_F_HW_HSR_TAG_INS) >> + features |= NETIF_F_HW_HSR_DUP; > > What if only NETIF_F_HW_HSR_DUP was set? Don't you have to set NETIF_F_HW_HSR_TAG_INS as well? > >> + else >> + features &= ~NETIF_F_HW_HSR_DUP; > > what if NETIF_F_HW_HSR_DUP was still set? > > I think you need to write a logic like follows. > if both are already cleared in ndev->features and any one is set in features you set both in features. > if both are already set in ndev->features and any one is cleared in features you clear both in features. > > is this reasonable? > Yes that does sound reasonable, How does below code look to you. if (!(ndev->features & NETIF_F_HW_HSR_DUP) && !(ndev->features & NETIF_F_HW_HSR_TAG_INS)) if ((features & NETIF_F_HW_HSR_DUP) || (features & NETIF_F_HW_HSR_TAG_INS)) { features |= NETIF_F_HW_HSR_DUP; features |= NETIF_F_HW_HSR_TAG_INS; } if ((ndev->features & NETIF_F_HW_HSR_DUP) && (ndev->features & NETIF_F_HW_HSR_TAG_INS)) if (!(features & NETIF_F_HW_HSR_DUP) || !(features & NETIF_F_HW_HSR_TAG_INS)) { features &= ~NETIF_F_HW_HSR_DUP; features &= ~NETIF_F_HW_HSR_TAG_INS; } >> + >> + return features; >> +} >> + >> static int emac_ndo_set_features(struct net_device *ndev, >> netdev_features_t features) >> { >> @@ -780,6 +798,7 @@ static const struct net_device_ops emac_netdev_ops = { >> .ndo_eth_ioctl = icssg_ndo_ioctl, >> .ndo_get_stats64 = icssg_ndo_get_stats64, >> .ndo_get_phys_port_name = icssg_ndo_get_phys_port_name, >> + .ndo_fix_features = emac_ndo_fix_features, >> .ndo_set_features = emac_ndo_set_features, >> }; >> >> @@ -1007,6 +1026,13 @@ static void icssg_change_mode(struct prueth *prueth) >> >> for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) { >> emac = prueth->emac[mac]; >> + if (prueth->is_hsr_offload_mode) { >> + if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM) >> + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE); >> + else >> + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE); >> + } >> + >> if (netif_running(emac->ndev)) { >> icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan, >> ICSSG_FDB_ENTRY_P0_MEMBERSHIP | >> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h >> index a4b025fae797..bba6da2e6bd8 100644 >> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h >> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h >> @@ -59,6 +59,9 @@ >> >> #define IEP_DEFAULT_CYCLE_TIME_NS 1000000 /* 1 ms */ >> >> +#define PRUETH_UNDIRECTED_PKT_DST_TAG 0 >> +#define PRUETH_UNDIRECTED_PKT_TAG_INS BIT(30) >> + >> /* Firmware status codes */ >> #define ICSS_HS_FW_READY 0x55555555 >> #define ICSS_HS_FW_DEAD 0xDEAD0000 /* lower 16 bits contain error code */ >
On 10/09/2024 20:52, Anwar, Md Danish wrote: > Hi Roger, > > On 9/10/2024 11:08 PM, Roger Quadros wrote: >> >> >> On 06/09/2024 14:15, MD Danish Anwar wrote: >>> From: Ravi Gunasekaran <r-gunasekaran@ti.com> >>> >>> The HSR stack allows to offload its Tx packet duplication functionality to >>> the hardware. Enable this offloading feature for ICSSG driver. Add support >>> to offload HSR Tx Tag Insertion and Rx Tag Removal and duplicate discard. >>> >>> Inorder to enable hsr-tag-ins-offload, hsr-dup-offload must also be enabled >> >> "In order" >> >>> as these are tightly coupled in the firmware implementation. >>> >>> Duplicate discard is done as part of RX tag removal and it is >>> done by the firmware. When driver sends the r30 command >>> ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE, firmware does RX tag removal as well as >>> duplicate discard. >>> >>> Signed-off-by: Ravi Gunasekaran <r-gunasekaran@ti.com> >>> Signed-off-by: MD Danish Anwar <danishanwar@ti.com> >>> --- >>> drivers/net/ethernet/ti/icssg/icssg_common.c | 18 ++++++++++--- >>> drivers/net/ethernet/ti/icssg/icssg_config.c | 4 ++- >>> drivers/net/ethernet/ti/icssg/icssg_config.h | 2 ++ >>> drivers/net/ethernet/ti/icssg/icssg_prueth.c | 28 +++++++++++++++++++- >>> drivers/net/ethernet/ti/icssg/icssg_prueth.h | 3 +++ >>> 5 files changed, 50 insertions(+), 5 deletions(-) >>> >>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c >>> index b9d8a93d1680..fdebeb2f84e0 100644 >>> --- a/drivers/net/ethernet/ti/icssg/icssg_common.c >>> +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c >>> @@ -660,14 +660,15 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev >>> { >>> struct cppi5_host_desc_t *first_desc, *next_desc, *cur_desc; >>> struct prueth_emac *emac = netdev_priv(ndev); >>> + struct prueth *prueth = emac->prueth; >>> struct netdev_queue *netif_txq; >>> struct prueth_tx_chn *tx_chn; >>> dma_addr_t desc_dma, buf_dma; >>> + u32 pkt_len, dst_tag_id; >>> int i, ret = 0, q_idx; >>> bool in_tx_ts = 0; >>> int tx_ts_cookie; >>> void **swdata; >>> - u32 pkt_len; >>> u32 *epib; >>> >>> pkt_len = skb_headlen(skb); >>> @@ -712,9 +713,20 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev >>> >>> /* set dst tag to indicate internal qid at the firmware which is at >>> * bit8..bit15. bit0..bit7 indicates port num for directed >>> - * packets in case of switch mode operation >>> + * packets in case of switch mode operation and port num 0 >>> + * for undirected packets in case of HSR offload mode >>> */ >>> - cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8))); >>> + dst_tag_id = emac->port_id | (q_idx << 8); >>> + >>> + if (prueth->is_hsr_offload_mode && >>> + (ndev->features & NETIF_F_HW_HSR_DUP)) >>> + dst_tag_id = PRUETH_UNDIRECTED_PKT_DST_TAG; >>> + >>> + if (prueth->is_hsr_offload_mode && >>> + (ndev->features & NETIF_F_HW_HSR_TAG_INS)) >>> + epib[1] |= PRUETH_UNDIRECTED_PKT_TAG_INS; >>> + >>> + cppi5_desc_set_tags_ids(&first_desc->hdr, 0, dst_tag_id); >>> k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma); >>> cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len); >>> swdata = cppi5_hdesc_get_swdata(first_desc); >>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c >>> index 7b2e6c192ff3..72ace151d8e9 100644 >>> --- a/drivers/net/ethernet/ti/icssg/icssg_config.c >>> +++ b/drivers/net/ethernet/ti/icssg/icssg_config.c >>> @@ -531,7 +531,9 @@ static const struct icssg_r30_cmd emac_r32_bitmask[] = { >>> {{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/ >>> {{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx DISABLE*/ >>> {{0xffff0010, EMAC_NONE, 0xffff0010, EMAC_NONE}}, /* VLAN AWARE*/ >>> - {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}} /* VLAN UNWARE*/ >>> + {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}}, /* VLAN UNWARE*/ >>> + {{0xffff2000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* HSR_RX_OFFLOAD_ENABLE */ >>> + {{0xdfff0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}} /* HSR_RX_OFFLOAD_DISABLE */ >>> }; >>> >>> int icssg_set_port_state(struct prueth_emac *emac, >>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.h b/drivers/net/ethernet/ti/icssg/icssg_config.h >>> index 1ac60283923b..92c2deaa3068 100644 >>> --- a/drivers/net/ethernet/ti/icssg/icssg_config.h >>> +++ b/drivers/net/ethernet/ti/icssg/icssg_config.h >>> @@ -80,6 +80,8 @@ enum icssg_port_state_cmd { >>> ICSSG_EMAC_PORT_PREMPT_TX_DISABLE, >>> ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE, >>> ICSSG_EMAC_PORT_VLAN_AWARE_DISABLE, >>> + ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE, >>> + ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE, >>> ICSSG_EMAC_PORT_MAX_COMMANDS >>> }; >>> >>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c >>> index 676168d6fded..9af06454ba64 100644 >>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c >>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c >>> @@ -41,7 +41,10 @@ >>> #define DEFAULT_PORT_MASK 1 >>> #define DEFAULT_UNTAG_MASK 1 >>> >>> -#define NETIF_PRUETH_HSR_OFFLOAD_FEATURES NETIF_F_HW_HSR_FWD >>> +#define NETIF_PRUETH_HSR_OFFLOAD_FEATURES (NETIF_F_HW_HSR_FWD | \ >>> + NETIF_F_HW_HSR_DUP | \ >>> + NETIF_F_HW_HSR_TAG_INS | \ >>> + NETIF_F_HW_HSR_TAG_RM) >>> >>> /* CTRLMMR_ICSSG_RGMII_CTRL register bits */ >>> #define ICSSG_CTRL_RGMII_ID_MODE BIT(24) >>> @@ -758,6 +761,21 @@ static void emac_change_hsr_feature(struct net_device *ndev, >>> } >>> } >>> >>> +static netdev_features_t emac_ndo_fix_features(struct net_device *ndev, >>> + netdev_features_t features) >>> +{ >>> + /* In order to enable hsr tag insertion offload, hsr dup offload must >>> + * also be enabled as these two are tightly coupled in firmware >>> + * implementation. >>> + */ >>> + if (features & NETIF_F_HW_HSR_TAG_INS) >>> + features |= NETIF_F_HW_HSR_DUP; >> >> What if only NETIF_F_HW_HSR_DUP was set? Don't you have to set NETIF_F_HW_HSR_TAG_INS as well? >> >>> + else >>> + features &= ~NETIF_F_HW_HSR_DUP; >> >> what if NETIF_F_HW_HSR_DUP was still set? >> >> I think you need to write a logic like follows. >> if both are already cleared in ndev->features and any one is set in features you set both in features. >> if both are already set in ndev->features and any one is cleared in features you clear both in features. >> >> is this reasonable? >> > > Yes that does sound reasonable, > How does below code look to you. > > if (!(ndev->features & NETIF_F_HW_HSR_DUP) && > !(ndev->features & NETIF_F_HW_HSR_TAG_INS)) While this is OK. it could also be if (!(ndev->features & (NETIF_F_HW_HSR_DUP | NETIF_F_HW_HSR_TAG_INS))) Your choice. > if ((features & NETIF_F_HW_HSR_DUP) || > (features & NETIF_F_HW_HSR_TAG_INS)) { > features |= NETIF_F_HW_HSR_DUP; > features |= NETIF_F_HW_HSR_TAG_INS; how about one line? features |= NETIF_F_HW_HSR_DUP | NETIF_F_HW_HSR_TAG_INS; > } then you can get rid of the braces. > > if ((ndev->features & NETIF_F_HW_HSR_DUP) && > (ndev->features & NETIF_F_HW_HSR_TAG_INS)) > if (!(features & NETIF_F_HW_HSR_DUP) || > !(features & NETIF_F_HW_HSR_TAG_INS)) { > features &= ~NETIF_F_HW_HSR_DUP; > features &= ~NETIF_F_HW_HSR_TAG_INS; features &= ~(NETIF_F_HW_HSR_DUP | NETIF_F_HW_HSR_TAG_INS); > } > >>> + >>> + return features; >>> +} >>> + >>> static int emac_ndo_set_features(struct net_device *ndev, >>> netdev_features_t features) >>> { >>> @@ -780,6 +798,7 @@ static const struct net_device_ops emac_netdev_ops = { >>> .ndo_eth_ioctl = icssg_ndo_ioctl, >>> .ndo_get_stats64 = icssg_ndo_get_stats64, >>> .ndo_get_phys_port_name = icssg_ndo_get_phys_port_name, >>> + .ndo_fix_features = emac_ndo_fix_features, >>> .ndo_set_features = emac_ndo_set_features, >>> }; >>> >>> @@ -1007,6 +1026,13 @@ static void icssg_change_mode(struct prueth *prueth) >>> >>> for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) { >>> emac = prueth->emac[mac]; >>> + if (prueth->is_hsr_offload_mode) { >>> + if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM) >>> + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE); >>> + else >>> + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE); >>> + } >>> + >>> if (netif_running(emac->ndev)) { >>> icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan, >>> ICSSG_FDB_ENTRY_P0_MEMBERSHIP | >>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h >>> index a4b025fae797..bba6da2e6bd8 100644 >>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h >>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h >>> @@ -59,6 +59,9 @@ >>> >>> #define IEP_DEFAULT_CYCLE_TIME_NS 1000000 /* 1 ms */ >>> >>> +#define PRUETH_UNDIRECTED_PKT_DST_TAG 0 >>> +#define PRUETH_UNDIRECTED_PKT_TAG_INS BIT(30) >>> + >>> /* Firmware status codes */ >>> #define ICSS_HS_FW_READY 0x55555555 >>> #define ICSS_HS_FW_DEAD 0xDEAD0000 /* lower 16 bits contain error code */ >> >
On 9/10/2024 11:36 PM, Roger Quadros wrote: > > > On 10/09/2024 20:52, Anwar, Md Danish wrote: >> Hi Roger, >> >> On 9/10/2024 11:08 PM, Roger Quadros wrote: >>> >>> >>> On 06/09/2024 14:15, MD Danish Anwar wrote: >>>> From: Ravi Gunasekaran <r-gunasekaran@ti.com> >>>> >>>> The HSR stack allows to offload its Tx packet duplication functionality to >>>> the hardware. Enable this offloading feature for ICSSG driver. Add support >>>> to offload HSR Tx Tag Insertion and Rx Tag Removal and duplicate discard. >>>> >>>> Inorder to enable hsr-tag-ins-offload, hsr-dup-offload must also be enabled >>> >>> "In order" >>> >>>> as these are tightly coupled in the firmware implementation. >>>> >>>> Duplicate discard is done as part of RX tag removal and it is >>>> done by the firmware. When driver sends the r30 command >>>> ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE, firmware does RX tag removal as well as >>>> duplicate discard. >>>> >>>> Signed-off-by: Ravi Gunasekaran <r-gunasekaran@ti.com> >>>> Signed-off-by: MD Danish Anwar <danishanwar@ti.com> >>>> --- >>>> drivers/net/ethernet/ti/icssg/icssg_common.c | 18 ++++++++++--- >>>> drivers/net/ethernet/ti/icssg/icssg_config.c | 4 ++- >>>> drivers/net/ethernet/ti/icssg/icssg_config.h | 2 ++ >>>> drivers/net/ethernet/ti/icssg/icssg_prueth.c | 28 +++++++++++++++++++- >>>> drivers/net/ethernet/ti/icssg/icssg_prueth.h | 3 +++ >>>> 5 files changed, 50 insertions(+), 5 deletions(-) >>>> >>>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c >>>> index b9d8a93d1680..fdebeb2f84e0 100644 >>>> --- a/drivers/net/ethernet/ti/icssg/icssg_common.c >>>> +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c >>>> @@ -660,14 +660,15 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev >>>> { >>>> struct cppi5_host_desc_t *first_desc, *next_desc, *cur_desc; >>>> struct prueth_emac *emac = netdev_priv(ndev); >>>> + struct prueth *prueth = emac->prueth; >>>> struct netdev_queue *netif_txq; >>>> struct prueth_tx_chn *tx_chn; >>>> dma_addr_t desc_dma, buf_dma; >>>> + u32 pkt_len, dst_tag_id; >>>> int i, ret = 0, q_idx; >>>> bool in_tx_ts = 0; >>>> int tx_ts_cookie; >>>> void **swdata; >>>> - u32 pkt_len; >>>> u32 *epib; >>>> >>>> pkt_len = skb_headlen(skb); >>>> @@ -712,9 +713,20 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev >>>> >>>> /* set dst tag to indicate internal qid at the firmware which is at >>>> * bit8..bit15. bit0..bit7 indicates port num for directed >>>> - * packets in case of switch mode operation >>>> + * packets in case of switch mode operation and port num 0 >>>> + * for undirected packets in case of HSR offload mode >>>> */ >>>> - cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8))); >>>> + dst_tag_id = emac->port_id | (q_idx << 8); >>>> + >>>> + if (prueth->is_hsr_offload_mode && >>>> + (ndev->features & NETIF_F_HW_HSR_DUP)) >>>> + dst_tag_id = PRUETH_UNDIRECTED_PKT_DST_TAG; >>>> + >>>> + if (prueth->is_hsr_offload_mode && >>>> + (ndev->features & NETIF_F_HW_HSR_TAG_INS)) >>>> + epib[1] |= PRUETH_UNDIRECTED_PKT_TAG_INS; >>>> + >>>> + cppi5_desc_set_tags_ids(&first_desc->hdr, 0, dst_tag_id); >>>> k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma); >>>> cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len); >>>> swdata = cppi5_hdesc_get_swdata(first_desc); >>>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c >>>> index 7b2e6c192ff3..72ace151d8e9 100644 >>>> --- a/drivers/net/ethernet/ti/icssg/icssg_config.c >>>> +++ b/drivers/net/ethernet/ti/icssg/icssg_config.c >>>> @@ -531,7 +531,9 @@ static const struct icssg_r30_cmd emac_r32_bitmask[] = { >>>> {{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/ >>>> {{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx DISABLE*/ >>>> {{0xffff0010, EMAC_NONE, 0xffff0010, EMAC_NONE}}, /* VLAN AWARE*/ >>>> - {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}} /* VLAN UNWARE*/ >>>> + {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}}, /* VLAN UNWARE*/ >>>> + {{0xffff2000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* HSR_RX_OFFLOAD_ENABLE */ >>>> + {{0xdfff0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}} /* HSR_RX_OFFLOAD_DISABLE */ >>>> }; >>>> >>>> int icssg_set_port_state(struct prueth_emac *emac, >>>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.h b/drivers/net/ethernet/ti/icssg/icssg_config.h >>>> index 1ac60283923b..92c2deaa3068 100644 >>>> --- a/drivers/net/ethernet/ti/icssg/icssg_config.h >>>> +++ b/drivers/net/ethernet/ti/icssg/icssg_config.h >>>> @@ -80,6 +80,8 @@ enum icssg_port_state_cmd { >>>> ICSSG_EMAC_PORT_PREMPT_TX_DISABLE, >>>> ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE, >>>> ICSSG_EMAC_PORT_VLAN_AWARE_DISABLE, >>>> + ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE, >>>> + ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE, >>>> ICSSG_EMAC_PORT_MAX_COMMANDS >>>> }; >>>> >>>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c >>>> index 676168d6fded..9af06454ba64 100644 >>>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c >>>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c >>>> @@ -41,7 +41,10 @@ >>>> #define DEFAULT_PORT_MASK 1 >>>> #define DEFAULT_UNTAG_MASK 1 >>>> >>>> -#define NETIF_PRUETH_HSR_OFFLOAD_FEATURES NETIF_F_HW_HSR_FWD >>>> +#define NETIF_PRUETH_HSR_OFFLOAD_FEATURES (NETIF_F_HW_HSR_FWD | \ >>>> + NETIF_F_HW_HSR_DUP | \ >>>> + NETIF_F_HW_HSR_TAG_INS | \ >>>> + NETIF_F_HW_HSR_TAG_RM) >>>> >>>> /* CTRLMMR_ICSSG_RGMII_CTRL register bits */ >>>> #define ICSSG_CTRL_RGMII_ID_MODE BIT(24) >>>> @@ -758,6 +761,21 @@ static void emac_change_hsr_feature(struct net_device *ndev, >>>> } >>>> } >>>> >>>> +static netdev_features_t emac_ndo_fix_features(struct net_device *ndev, >>>> + netdev_features_t features) >>>> +{ >>>> + /* In order to enable hsr tag insertion offload, hsr dup offload must >>>> + * also be enabled as these two are tightly coupled in firmware >>>> + * implementation. >>>> + */ >>>> + if (features & NETIF_F_HW_HSR_TAG_INS) >>>> + features |= NETIF_F_HW_HSR_DUP; >>> >>> What if only NETIF_F_HW_HSR_DUP was set? Don't you have to set NETIF_F_HW_HSR_TAG_INS as well? >>> >>>> + else >>>> + features &= ~NETIF_F_HW_HSR_DUP; >>> >>> what if NETIF_F_HW_HSR_DUP was still set? >>> >>> I think you need to write a logic like follows. >>> if both are already cleared in ndev->features and any one is set in features you set both in features. >>> if both are already set in ndev->features and any one is cleared in features you clear both in features. >>> >>> is this reasonable? >>> >> >> Yes that does sound reasonable, >> How does below code look to you. >> >> if (!(ndev->features & NETIF_F_HW_HSR_DUP) && >> !(ndev->features & NETIF_F_HW_HSR_TAG_INS)) > > While this is OK. it could also be > if (!(ndev->features & (NETIF_F_HW_HSR_DUP | NETIF_F_HW_HSR_TAG_INS))) > Your choice. > >> if ((features & NETIF_F_HW_HSR_DUP) || >> (features & NETIF_F_HW_HSR_TAG_INS)) { >> features |= NETIF_F_HW_HSR_DUP; >> features |= NETIF_F_HW_HSR_TAG_INS; > how about one line? > features |= NETIF_F_HW_HSR_DUP | NETIF_F_HW_HSR_TAG_INS; >> } > > then you can get rid of the braces. > Yes I could do this but this make the line length go beyond 80 characters. That's why I thought of putting this in two lines. >> >> if ((ndev->features & NETIF_F_HW_HSR_DUP) && >> (ndev->features & NETIF_F_HW_HSR_TAG_INS)) >> if (!(features & NETIF_F_HW_HSR_DUP) || >> !(features & NETIF_F_HW_HSR_TAG_INS)) { >> features &= ~NETIF_F_HW_HSR_DUP; >> features &= ~NETIF_F_HW_HSR_TAG_INS; > > features &= ~(NETIF_F_HW_HSR_DUP | NETIF_F_HW_HSR_TAG_INS); > >> } >> >>>> + >>>> + return features; >>>> +} >>>> + >>>> static int emac_ndo_set_features(struct net_device *ndev, >>>> netdev_features_t features) >>>> { >>>> @@ -780,6 +798,7 @@ static const struct net_device_ops emac_netdev_ops = { >>>> .ndo_eth_ioctl = icssg_ndo_ioctl, >>>> .ndo_get_stats64 = icssg_ndo_get_stats64, >>>> .ndo_get_phys_port_name = icssg_ndo_get_phys_port_name, >>>> + .ndo_fix_features = emac_ndo_fix_features, >>>> .ndo_set_features = emac_ndo_set_features, >>>> }; >>>> >>>> @@ -1007,6 +1026,13 @@ static void icssg_change_mode(struct prueth *prueth) >>>> >>>> for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) { >>>> emac = prueth->emac[mac]; >>>> + if (prueth->is_hsr_offload_mode) { >>>> + if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM) >>>> + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE); >>>> + else >>>> + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE); >>>> + } >>>> + >>>> if (netif_running(emac->ndev)) { >>>> icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan, >>>> ICSSG_FDB_ENTRY_P0_MEMBERSHIP | >>>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h >>>> index a4b025fae797..bba6da2e6bd8 100644 >>>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h >>>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h >>>> @@ -59,6 +59,9 @@ >>>> >>>> #define IEP_DEFAULT_CYCLE_TIME_NS 1000000 /* 1 ms */ >>>> >>>> +#define PRUETH_UNDIRECTED_PKT_DST_TAG 0 >>>> +#define PRUETH_UNDIRECTED_PKT_TAG_INS BIT(30) >>>> + >>>> /* Firmware status codes */ >>>> #define ICSS_HS_FW_READY 0x55555555 >>>> #define ICSS_HS_FW_DEAD 0xDEAD0000 /* lower 16 bits contain error code */ >>> >> >
On 10/09/2024 21:27, Anwar, Md Danish wrote: > > > On 9/10/2024 11:36 PM, Roger Quadros wrote: >> >> >> On 10/09/2024 20:52, Anwar, Md Danish wrote: >>> Hi Roger, >>> >>> On 9/10/2024 11:08 PM, Roger Quadros wrote: >>>> >>>> >>>> On 06/09/2024 14:15, MD Danish Anwar wrote: >>>>> From: Ravi Gunasekaran <r-gunasekaran@ti.com> >>>>> >>>>> The HSR stack allows to offload its Tx packet duplication functionality to >>>>> the hardware. Enable this offloading feature for ICSSG driver. Add support >>>>> to offload HSR Tx Tag Insertion and Rx Tag Removal and duplicate discard. >>>>> >>>>> Inorder to enable hsr-tag-ins-offload, hsr-dup-offload must also be enabled >>>> >>>> "In order" >>>> >>>>> as these are tightly coupled in the firmware implementation. >>>>> >>>>> Duplicate discard is done as part of RX tag removal and it is >>>>> done by the firmware. When driver sends the r30 command >>>>> ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE, firmware does RX tag removal as well as >>>>> duplicate discard. >>>>> >>>>> Signed-off-by: Ravi Gunasekaran <r-gunasekaran@ti.com> >>>>> Signed-off-by: MD Danish Anwar <danishanwar@ti.com> >>>>> --- >>>>> drivers/net/ethernet/ti/icssg/icssg_common.c | 18 ++++++++++--- >>>>> drivers/net/ethernet/ti/icssg/icssg_config.c | 4 ++- >>>>> drivers/net/ethernet/ti/icssg/icssg_config.h | 2 ++ >>>>> drivers/net/ethernet/ti/icssg/icssg_prueth.c | 28 +++++++++++++++++++- >>>>> drivers/net/ethernet/ti/icssg/icssg_prueth.h | 3 +++ >>>>> 5 files changed, 50 insertions(+), 5 deletions(-) >>>>> >>>>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c >>>>> index b9d8a93d1680..fdebeb2f84e0 100644 >>>>> --- a/drivers/net/ethernet/ti/icssg/icssg_common.c >>>>> +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c >>>>> @@ -660,14 +660,15 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev >>>>> { >>>>> struct cppi5_host_desc_t *first_desc, *next_desc, *cur_desc; >>>>> struct prueth_emac *emac = netdev_priv(ndev); >>>>> + struct prueth *prueth = emac->prueth; >>>>> struct netdev_queue *netif_txq; >>>>> struct prueth_tx_chn *tx_chn; >>>>> dma_addr_t desc_dma, buf_dma; >>>>> + u32 pkt_len, dst_tag_id; >>>>> int i, ret = 0, q_idx; >>>>> bool in_tx_ts = 0; >>>>> int tx_ts_cookie; >>>>> void **swdata; >>>>> - u32 pkt_len; >>>>> u32 *epib; >>>>> >>>>> pkt_len = skb_headlen(skb); >>>>> @@ -712,9 +713,20 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev >>>>> >>>>> /* set dst tag to indicate internal qid at the firmware which is at >>>>> * bit8..bit15. bit0..bit7 indicates port num for directed >>>>> - * packets in case of switch mode operation >>>>> + * packets in case of switch mode operation and port num 0 >>>>> + * for undirected packets in case of HSR offload mode >>>>> */ >>>>> - cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8))); >>>>> + dst_tag_id = emac->port_id | (q_idx << 8); >>>>> + >>>>> + if (prueth->is_hsr_offload_mode && >>>>> + (ndev->features & NETIF_F_HW_HSR_DUP)) >>>>> + dst_tag_id = PRUETH_UNDIRECTED_PKT_DST_TAG; >>>>> + >>>>> + if (prueth->is_hsr_offload_mode && >>>>> + (ndev->features & NETIF_F_HW_HSR_TAG_INS)) >>>>> + epib[1] |= PRUETH_UNDIRECTED_PKT_TAG_INS; >>>>> + >>>>> + cppi5_desc_set_tags_ids(&first_desc->hdr, 0, dst_tag_id); >>>>> k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma); >>>>> cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len); >>>>> swdata = cppi5_hdesc_get_swdata(first_desc); >>>>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c >>>>> index 7b2e6c192ff3..72ace151d8e9 100644 >>>>> --- a/drivers/net/ethernet/ti/icssg/icssg_config.c >>>>> +++ b/drivers/net/ethernet/ti/icssg/icssg_config.c >>>>> @@ -531,7 +531,9 @@ static const struct icssg_r30_cmd emac_r32_bitmask[] = { >>>>> {{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/ >>>>> {{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx DISABLE*/ >>>>> {{0xffff0010, EMAC_NONE, 0xffff0010, EMAC_NONE}}, /* VLAN AWARE*/ >>>>> - {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}} /* VLAN UNWARE*/ >>>>> + {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}}, /* VLAN UNWARE*/ >>>>> + {{0xffff2000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* HSR_RX_OFFLOAD_ENABLE */ >>>>> + {{0xdfff0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}} /* HSR_RX_OFFLOAD_DISABLE */ >>>>> }; >>>>> >>>>> int icssg_set_port_state(struct prueth_emac *emac, >>>>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.h b/drivers/net/ethernet/ti/icssg/icssg_config.h >>>>> index 1ac60283923b..92c2deaa3068 100644 >>>>> --- a/drivers/net/ethernet/ti/icssg/icssg_config.h >>>>> +++ b/drivers/net/ethernet/ti/icssg/icssg_config.h >>>>> @@ -80,6 +80,8 @@ enum icssg_port_state_cmd { >>>>> ICSSG_EMAC_PORT_PREMPT_TX_DISABLE, >>>>> ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE, >>>>> ICSSG_EMAC_PORT_VLAN_AWARE_DISABLE, >>>>> + ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE, >>>>> + ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE, >>>>> ICSSG_EMAC_PORT_MAX_COMMANDS >>>>> }; >>>>> >>>>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c >>>>> index 676168d6fded..9af06454ba64 100644 >>>>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c >>>>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c >>>>> @@ -41,7 +41,10 @@ >>>>> #define DEFAULT_PORT_MASK 1 >>>>> #define DEFAULT_UNTAG_MASK 1 >>>>> >>>>> -#define NETIF_PRUETH_HSR_OFFLOAD_FEATURES NETIF_F_HW_HSR_FWD >>>>> +#define NETIF_PRUETH_HSR_OFFLOAD_FEATURES (NETIF_F_HW_HSR_FWD | \ >>>>> + NETIF_F_HW_HSR_DUP | \ >>>>> + NETIF_F_HW_HSR_TAG_INS | \ >>>>> + NETIF_F_HW_HSR_TAG_RM) >>>>> >>>>> /* CTRLMMR_ICSSG_RGMII_CTRL register bits */ >>>>> #define ICSSG_CTRL_RGMII_ID_MODE BIT(24) >>>>> @@ -758,6 +761,21 @@ static void emac_change_hsr_feature(struct net_device *ndev, >>>>> } >>>>> } >>>>> >>>>> +static netdev_features_t emac_ndo_fix_features(struct net_device *ndev, >>>>> + netdev_features_t features) >>>>> +{ >>>>> + /* In order to enable hsr tag insertion offload, hsr dup offload must >>>>> + * also be enabled as these two are tightly coupled in firmware >>>>> + * implementation. >>>>> + */ >>>>> + if (features & NETIF_F_HW_HSR_TAG_INS) >>>>> + features |= NETIF_F_HW_HSR_DUP; >>>> >>>> What if only NETIF_F_HW_HSR_DUP was set? Don't you have to set NETIF_F_HW_HSR_TAG_INS as well? >>>> >>>>> + else >>>>> + features &= ~NETIF_F_HW_HSR_DUP; >>>> >>>> what if NETIF_F_HW_HSR_DUP was still set? >>>> >>>> I think you need to write a logic like follows. >>>> if both are already cleared in ndev->features and any one is set in features you set both in features. >>>> if both are already set in ndev->features and any one is cleared in features you clear both in features. >>>> >>>> is this reasonable? >>>> >>> >>> Yes that does sound reasonable, >>> How does below code look to you. >>> >>> if (!(ndev->features & NETIF_F_HW_HSR_DUP) && >>> !(ndev->features & NETIF_F_HW_HSR_TAG_INS)) >> >> While this is OK. it could also be >> if (!(ndev->features & (NETIF_F_HW_HSR_DUP | NETIF_F_HW_HSR_TAG_INS))) >> Your choice. >> >>> if ((features & NETIF_F_HW_HSR_DUP) || >>> (features & NETIF_F_HW_HSR_TAG_INS)) { >>> features |= NETIF_F_HW_HSR_DUP; >>> features |= NETIF_F_HW_HSR_TAG_INS; >> how about one line? >> features |= NETIF_F_HW_HSR_DUP | NETIF_F_HW_HSR_TAG_INS; >>> } >> >> then you can get rid of the braces. >> > > Yes I could do this but this make the line length go beyond 80 > characters. That's why I thought of putting this in two lines. then you can split the line e.g. features |= NETIF_F_HW_HSR_DUP | NETIF_F_HW_HSR_TAG_INS; > >>> >>> if ((ndev->features & NETIF_F_HW_HSR_DUP) && >>> (ndev->features & NETIF_F_HW_HSR_TAG_INS)) >>> if (!(features & NETIF_F_HW_HSR_DUP) || >>> !(features & NETIF_F_HW_HSR_TAG_INS)) { >>> features &= ~NETIF_F_HW_HSR_DUP; >>> features &= ~NETIF_F_HW_HSR_TAG_INS; >> >> features &= ~(NETIF_F_HW_HSR_DUP | NETIF_F_HW_HSR_TAG_INS); >> >>> } >>> >>>>> + >>>>> + return features; >>>>> +} >>>>> + >>>>> static int emac_ndo_set_features(struct net_device *ndev, >>>>> netdev_features_t features) >>>>> { >>>>> @@ -780,6 +798,7 @@ static const struct net_device_ops emac_netdev_ops = { >>>>> .ndo_eth_ioctl = icssg_ndo_ioctl, >>>>> .ndo_get_stats64 = icssg_ndo_get_stats64, >>>>> .ndo_get_phys_port_name = icssg_ndo_get_phys_port_name, >>>>> + .ndo_fix_features = emac_ndo_fix_features, >>>>> .ndo_set_features = emac_ndo_set_features, >>>>> }; >>>>> >>>>> @@ -1007,6 +1026,13 @@ static void icssg_change_mode(struct prueth *prueth) >>>>> >>>>> for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) { >>>>> emac = prueth->emac[mac]; >>>>> + if (prueth->is_hsr_offload_mode) { >>>>> + if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM) >>>>> + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE); >>>>> + else >>>>> + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE); >>>>> + } >>>>> + >>>>> if (netif_running(emac->ndev)) { >>>>> icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan, >>>>> ICSSG_FDB_ENTRY_P0_MEMBERSHIP | >>>>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h >>>>> index a4b025fae797..bba6da2e6bd8 100644 >>>>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h >>>>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h >>>>> @@ -59,6 +59,9 @@ >>>>> >>>>> #define IEP_DEFAULT_CYCLE_TIME_NS 1000000 /* 1 ms */ >>>>> >>>>> +#define PRUETH_UNDIRECTED_PKT_DST_TAG 0 >>>>> +#define PRUETH_UNDIRECTED_PKT_TAG_INS BIT(30) >>>>> + >>>>> /* Firmware status codes */ >>>>> #define ICSS_HS_FW_READY 0x55555555 >>>>> #define ICSS_HS_FW_DEAD 0xDEAD0000 /* lower 16 bits contain error code */ >>>> >>> >> >
diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c index b9d8a93d1680..fdebeb2f84e0 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_common.c +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c @@ -660,14 +660,15 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev { struct cppi5_host_desc_t *first_desc, *next_desc, *cur_desc; struct prueth_emac *emac = netdev_priv(ndev); + struct prueth *prueth = emac->prueth; struct netdev_queue *netif_txq; struct prueth_tx_chn *tx_chn; dma_addr_t desc_dma, buf_dma; + u32 pkt_len, dst_tag_id; int i, ret = 0, q_idx; bool in_tx_ts = 0; int tx_ts_cookie; void **swdata; - u32 pkt_len; u32 *epib; pkt_len = skb_headlen(skb); @@ -712,9 +713,20 @@ enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev /* set dst tag to indicate internal qid at the firmware which is at * bit8..bit15. bit0..bit7 indicates port num for directed - * packets in case of switch mode operation + * packets in case of switch mode operation and port num 0 + * for undirected packets in case of HSR offload mode */ - cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8))); + dst_tag_id = emac->port_id | (q_idx << 8); + + if (prueth->is_hsr_offload_mode && + (ndev->features & NETIF_F_HW_HSR_DUP)) + dst_tag_id = PRUETH_UNDIRECTED_PKT_DST_TAG; + + if (prueth->is_hsr_offload_mode && + (ndev->features & NETIF_F_HW_HSR_TAG_INS)) + epib[1] |= PRUETH_UNDIRECTED_PKT_TAG_INS; + + cppi5_desc_set_tags_ids(&first_desc->hdr, 0, dst_tag_id); k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma); cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len); swdata = cppi5_hdesc_get_swdata(first_desc); diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c index 7b2e6c192ff3..72ace151d8e9 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_config.c +++ b/drivers/net/ethernet/ti/icssg/icssg_config.c @@ -531,7 +531,9 @@ static const struct icssg_r30_cmd emac_r32_bitmask[] = { {{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/ {{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx DISABLE*/ {{0xffff0010, EMAC_NONE, 0xffff0010, EMAC_NONE}}, /* VLAN AWARE*/ - {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}} /* VLAN UNWARE*/ + {{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}}, /* VLAN UNWARE*/ + {{0xffff2000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* HSR_RX_OFFLOAD_ENABLE */ + {{0xdfff0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}} /* HSR_RX_OFFLOAD_DISABLE */ }; int icssg_set_port_state(struct prueth_emac *emac, diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.h b/drivers/net/ethernet/ti/icssg/icssg_config.h index 1ac60283923b..92c2deaa3068 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_config.h +++ b/drivers/net/ethernet/ti/icssg/icssg_config.h @@ -80,6 +80,8 @@ enum icssg_port_state_cmd { ICSSG_EMAC_PORT_PREMPT_TX_DISABLE, ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE, ICSSG_EMAC_PORT_VLAN_AWARE_DISABLE, + ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE, + ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE, ICSSG_EMAC_PORT_MAX_COMMANDS }; diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c index 676168d6fded..9af06454ba64 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -41,7 +41,10 @@ #define DEFAULT_PORT_MASK 1 #define DEFAULT_UNTAG_MASK 1 -#define NETIF_PRUETH_HSR_OFFLOAD_FEATURES NETIF_F_HW_HSR_FWD +#define NETIF_PRUETH_HSR_OFFLOAD_FEATURES (NETIF_F_HW_HSR_FWD | \ + NETIF_F_HW_HSR_DUP | \ + NETIF_F_HW_HSR_TAG_INS | \ + NETIF_F_HW_HSR_TAG_RM) /* CTRLMMR_ICSSG_RGMII_CTRL register bits */ #define ICSSG_CTRL_RGMII_ID_MODE BIT(24) @@ -758,6 +761,21 @@ static void emac_change_hsr_feature(struct net_device *ndev, } } +static netdev_features_t emac_ndo_fix_features(struct net_device *ndev, + netdev_features_t features) +{ + /* In order to enable hsr tag insertion offload, hsr dup offload must + * also be enabled as these two are tightly coupled in firmware + * implementation. + */ + if (features & NETIF_F_HW_HSR_TAG_INS) + features |= NETIF_F_HW_HSR_DUP; + else + features &= ~NETIF_F_HW_HSR_DUP; + + return features; +} + static int emac_ndo_set_features(struct net_device *ndev, netdev_features_t features) { @@ -780,6 +798,7 @@ static const struct net_device_ops emac_netdev_ops = { .ndo_eth_ioctl = icssg_ndo_ioctl, .ndo_get_stats64 = icssg_ndo_get_stats64, .ndo_get_phys_port_name = icssg_ndo_get_phys_port_name, + .ndo_fix_features = emac_ndo_fix_features, .ndo_set_features = emac_ndo_set_features, }; @@ -1007,6 +1026,13 @@ static void icssg_change_mode(struct prueth *prueth) for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) { emac = prueth->emac[mac]; + if (prueth->is_hsr_offload_mode) { + if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM) + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE); + else + icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE); + } + if (netif_running(emac->ndev)) { icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan, ICSSG_FDB_ENTRY_P0_MEMBERSHIP | diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h index a4b025fae797..bba6da2e6bd8 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -59,6 +59,9 @@ #define IEP_DEFAULT_CYCLE_TIME_NS 1000000 /* 1 ms */ +#define PRUETH_UNDIRECTED_PKT_DST_TAG 0 +#define PRUETH_UNDIRECTED_PKT_TAG_INS BIT(30) + /* Firmware status codes */ #define ICSS_HS_FW_READY 0x55555555 #define ICSS_HS_FW_DEAD 0xDEAD0000 /* lower 16 bits contain error code */