diff mbox series

[net-next,v3,2/7] bnxt_en: add support for tcp-data-split ethtool command

Message ID 20241003160620.1521626-3-ap420073@gmail.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series bnxt_en: implement device memory TCP for bnxt | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next, async
netdev/ynl success Generated files up to date; no warnings/errors; GEN HAS DIFF 2 files changed, 38 insertions(+);
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 9 this patch: 9
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 5 of 5 maintainers
netdev/build_clang success Errors and warnings before: 9 this patch: 9
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 9 this patch: 9
netdev/checkpatch warning WARNING: line length of 89 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 2 this patch: 2
netdev/source_inline success Was 0 now: 0

Commit Message

Taehee Yoo Oct. 3, 2024, 4:06 p.m. UTC
NICs that uses bnxt_en driver supports tcp-data-split feature by the
name of HDS(header-data-split).
But there is no implementation for the HDS to enable or disable by
ethtool.
Only getting the current HDS status is implemented and The HDS is just
automatically enabled only when either LRO, HW-GRO, or JUMBO is enabled.
The hds_threshold follows rx-copybreak value. and it was unchangeable.

This implements `ethtool -G <interface name> tcp-data-split <value>`
command option.
The value can be <on>, <off>, and <auto> but the <auto> will be
automatically changed to <on>.

HDS feature relies on the aggregation ring.
So, if HDS is enabled, the bnxt_en driver initializes the aggregation
ring.
This is the reason why BNXT_FLAG_AGG_RINGS contains HDS condition.

Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---

v3:
 - No changes.

v2:
 - Do not set hds_threshold to 0.

 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  9 +++----
 drivers/net/ethernet/broadcom/bnxt/bnxt.h     |  5 ++--
 .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 25 +++++++++++++++++--
 3 files changed, 30 insertions(+), 9 deletions(-)

Comments

Jakub Kicinski Oct. 8, 2024, 6:19 p.m. UTC | #1
On Thu,  3 Oct 2024 16:06:15 +0000 Taehee Yoo wrote:
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> index fdecdf8894b3..e9ef65dd2e7b 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> @@ -829,12 +829,16 @@ static void bnxt_get_ringparam(struct net_device *dev,
>  	if (bp->flags & BNXT_FLAG_AGG_RINGS) {
>  		ering->rx_max_pending = BNXT_MAX_RX_DESC_CNT_JUM_ENA;
>  		ering->rx_jumbo_max_pending = BNXT_MAX_RX_JUM_DESC_CNT;
> -		kernel_ering->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_ENABLED;
>  	} else {
>  		ering->rx_max_pending = BNXT_MAX_RX_DESC_CNT;
>  		ering->rx_jumbo_max_pending = 0;
> -		kernel_ering->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_DISABLED;
>  	}
> +
> +	if (bp->flags & BNXT_FLAG_HDS)
> +		kernel_ering->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_ENABLED;
> +	else
> +		kernel_ering->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_DISABLED;

This breaks previous behavior. The HDS reporting from get was
introduced to signal to user space whether the page flip based
TCP zero-copy (the one added some years ago not the recent one)
will be usable with this NIC.

When HW-GRO is enabled HDS will be working.

I think that the driver should only track if the user has set the value
to ENABLED (forced HDS), or to UKNOWN (driver default). Setting the HDS
to disabled is not useful, don't support it.

>  	ering->tx_max_pending = BNXT_MAX_TX_DESC_CNT;
>  
>  	ering->rx_pending = bp->rx_ring_size;
> @@ -854,9 +858,25 @@ static int bnxt_set_ringparam(struct net_device *dev,
>  	    (ering->tx_pending < BNXT_MIN_TX_DESC_CNT))
>  		return -EINVAL;
>  
> +	if (kernel_ering->tcp_data_split != ETHTOOL_TCP_DATA_SPLIT_DISABLED &&
> +	    BNXT_RX_PAGE_MODE(bp)) {
> +		NL_SET_ERR_MSG_MOD(extack, "tcp-data-split can not be enabled with XDP");
> +		return -EINVAL;
> +	}

Technically just if the XDP does not support multi-buffer.
Any chance we could do this check in the core?
Taehee Yoo Oct. 9, 2024, 1:54 p.m. UTC | #2
On Wed, Oct 9, 2024 at 3:19 AM Jakub Kicinski <kuba@kernel.org> wrote:
>

Hi Jakub,
Thanks a lot for your reviews!

> On Thu,  3 Oct 2024 16:06:15 +0000 Taehee Yoo wrote:
> > diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> > index fdecdf8894b3..e9ef65dd2e7b 100644
> > --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> > +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> > @@ -829,12 +829,16 @@ static void bnxt_get_ringparam(struct net_device *dev,
> >       if (bp->flags & BNXT_FLAG_AGG_RINGS) {
> >               ering->rx_max_pending = BNXT_MAX_RX_DESC_CNT_JUM_ENA;
> >               ering->rx_jumbo_max_pending = BNXT_MAX_RX_JUM_DESC_CNT;
> > -             kernel_ering->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_ENABLED;
> >       } else {
> >               ering->rx_max_pending = BNXT_MAX_RX_DESC_CNT;
> >               ering->rx_jumbo_max_pending = 0;
> > -             kernel_ering->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_DISABLED;
> >       }
> > +
> > +     if (bp->flags & BNXT_FLAG_HDS)
> > +             kernel_ering->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_ENABLED;
> > +     else
> > +             kernel_ering->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_DISABLED;
>
> This breaks previous behavior. The HDS reporting from get was
> introduced to signal to user space whether the page flip based
> TCP zero-copy (the one added some years ago not the recent one)
> will be usable with this NIC.
>
> When HW-GRO is enabled HDS will be working.
>
> I think that the driver should only track if the user has set the value
> to ENABLED (forced HDS), or to UKNOWN (driver default). Setting the HDS
> to disabled is not useful, don't support it.

Okay, I will remove the disable feature in a v4 patch.
Before this patch, hds_threshold was rx-copybreak value.
How do you think hds_threshold should still follow rx-copybreak value
if it is UNKNOWN mode?
I think hds_threshold need to follow new tcp-data-split-thresh value in
ENABLE/UNKNOWN and make rx-copybreak pure software feature.
But if so, it changes the default behavior.
How do you think about it?

>
> >       ering->tx_max_pending = BNXT_MAX_TX_DESC_CNT;
> >
> >       ering->rx_pending = bp->rx_ring_size;
> > @@ -854,9 +858,25 @@ static int bnxt_set_ringparam(struct net_device *dev,
> >           (ering->tx_pending < BNXT_MIN_TX_DESC_CNT))
> >               return -EINVAL;
> >
> > +     if (kernel_ering->tcp_data_split != ETHTOOL_TCP_DATA_SPLIT_DISABLED &&
> > +         BNXT_RX_PAGE_MODE(bp)) {
> > +             NL_SET_ERR_MSG_MOD(extack, "tcp-data-split can not be enabled with XDP");
> > +             return -EINVAL;
> > +     }
>
> Technically just if the XDP does not support multi-buffer.
> Any chance we could do this check in the core?

I think we can access xdp_rxq_info with netdev_rx_queue structure.
However, xdp_rxq_info is not sufficient to distinguish mb is supported
by the driver or not. I think prog->aux->xdp_has_frags is required to
distinguish it correctly.
So, I think we need something more.
Do you have any idea?
Jakub Kicinski Oct. 9, 2024, 3:28 p.m. UTC | #3
On Wed, 9 Oct 2024 22:54:17 +0900 Taehee Yoo wrote:
> > This breaks previous behavior. The HDS reporting from get was
> > introduced to signal to user space whether the page flip based
> > TCP zero-copy (the one added some years ago not the recent one)
> > will be usable with this NIC.
> >
> > When HW-GRO is enabled HDS will be working.
> >
> > I think that the driver should only track if the user has set the value
> > to ENABLED (forced HDS), or to UKNOWN (driver default). Setting the HDS
> > to disabled is not useful, don't support it.  
> 
> Okay, I will remove the disable feature in a v4 patch.
> Before this patch, hds_threshold was rx-copybreak value.
> How do you think hds_threshold should still follow rx-copybreak value
> if it is UNKNOWN mode?

IIUC the rx_copybreak only applies to the header? Or does it apply 
to the entire frame?

If rx_copybreak applies to the entire frame and not just the first
buffer (headers or headers+payload if not split) - no preference.
If rx_copybreak only applies to the headers / first buffer then
I'd keep them separate as they operate on a different length.

> I think hds_threshold need to follow new tcp-data-split-thresh value in
> ENABLE/UNKNOWN and make rx-copybreak pure software feature.

Sounds good to me, but just to be clear:

If user sets the HDS enable to UNKNOWN (or doesn't set it):
 - GET returns (current behavior, AFAIU):
   - DISABLED (if HW-GRO is disabled and MTU is not Jumbo)
   - ENABLED (if HW-GRO is enabled of MTU is Jumbo)
If user sets the HDS enable to ENABLED (force HDS on):
 - GET returns ENABLED 

hds_threshold returns: some value, but it's only actually used if GET
returns ENABLED.

> But if so, it changes the default behavior.

How so? The configuration of neither of those two is exposed to 
the user. We can keep the same defaults, until user overrides them.

> How do you think about it?
> 
> >  
> > >       ering->tx_max_pending = BNXT_MAX_TX_DESC_CNT;
> > >
> > >       ering->rx_pending = bp->rx_ring_size;
> > > @@ -854,9 +858,25 @@ static int bnxt_set_ringparam(struct net_device *dev,
> > >           (ering->tx_pending < BNXT_MIN_TX_DESC_CNT))
> > >               return -EINVAL;
> > >
> > > +     if (kernel_ering->tcp_data_split != ETHTOOL_TCP_DATA_SPLIT_DISABLED &&
> > > +         BNXT_RX_PAGE_MODE(bp)) {
> > > +             NL_SET_ERR_MSG_MOD(extack, "tcp-data-split can not be enabled with XDP");
> > > +             return -EINVAL;
> > > +     }  
> >
> > Technically just if the XDP does not support multi-buffer.
> > Any chance we could do this check in the core?  
> 
> I think we can access xdp_rxq_info with netdev_rx_queue structure.
> However, xdp_rxq_info is not sufficient to distinguish mb is supported
> by the driver or not. I think prog->aux->xdp_has_frags is required to
> distinguish it correctly.
> So, I think we need something more.
> Do you have any idea?

Take a look at dev_xdp_prog_count(), something like that but only
counting non-mb progs?
Taehee Yoo Oct. 9, 2024, 5:47 p.m. UTC | #4
On Thu, Oct 10, 2024 at 12:28 AM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Wed, 9 Oct 2024 22:54:17 +0900 Taehee Yoo wrote:
> > > This breaks previous behavior. The HDS reporting from get was
> > > introduced to signal to user space whether the page flip based
> > > TCP zero-copy (the one added some years ago not the recent one)
> > > will be usable with this NIC.
> > >
> > > When HW-GRO is enabled HDS will be working.
> > >
> > > I think that the driver should only track if the user has set the value
> > > to ENABLED (forced HDS), or to UKNOWN (driver default). Setting the HDS
> > > to disabled is not useful, don't support it.
> >
> > Okay, I will remove the disable feature in a v4 patch.
> > Before this patch, hds_threshold was rx-copybreak value.
> > How do you think hds_threshold should still follow rx-copybreak value
> > if it is UNKNOWN mode?
>
> IIUC the rx_copybreak only applies to the header? Or does it apply
> to the entire frame?
>
> If rx_copybreak applies to the entire frame and not just the first
> buffer (headers or headers+payload if not split) - no preference.
> If rx_copybreak only applies to the headers / first buffer then
> I'd keep them separate as they operate on a different length.

It applies only the first buffer.
So, if HDS is enabled, it copies only header.
Thanks, I will separate rx-copybreak and hds_threshold.

>
> > I think hds_threshold need to follow new tcp-data-split-thresh value in
> > ENABLE/UNKNOWN and make rx-copybreak pure software feature.
>
> Sounds good to me, but just to be clear:
>
> If user sets the HDS enable to UNKNOWN (or doesn't set it):
>  - GET returns (current behavior, AFAIU):
>    - DISABLED (if HW-GRO is disabled and MTU is not Jumbo)
>    - ENABLED (if HW-GRO is enabled of MTU is Jumbo)
> If user sets the HDS enable to ENABLED (force HDS on):
>  - GET returns ENABLED
>
> hds_threshold returns: some value, but it's only actually used if GET
> returns ENABLED.
>

Thanks for the detailed explanation!

> > But if so, it changes the default behavior.
>
> How so? The configuration of neither of those two is exposed to
> the user. We can keep the same defaults, until user overrides them.
>

Ah, right.
I understood.

> > How do you think about it?
> >
> > >
> > > >       ering->tx_max_pending = BNXT_MAX_TX_DESC_CNT;
> > > >
> > > >       ering->rx_pending = bp->rx_ring_size;
> > > > @@ -854,9 +858,25 @@ static int bnxt_set_ringparam(struct net_device *dev,
> > > >           (ering->tx_pending < BNXT_MIN_TX_DESC_CNT))
> > > >               return -EINVAL;
> > > >
> > > > +     if (kernel_ering->tcp_data_split != ETHTOOL_TCP_DATA_SPLIT_DISABLED &&
> > > > +         BNXT_RX_PAGE_MODE(bp)) {
> > > > +             NL_SET_ERR_MSG_MOD(extack, "tcp-data-split can not be enabled with XDP");
> > > > +             return -EINVAL;
> > > > +     }
> > >
> > > Technically just if the XDP does not support multi-buffer.
> > > Any chance we could do this check in the core?
> >
> > I think we can access xdp_rxq_info with netdev_rx_queue structure.
> > However, xdp_rxq_info is not sufficient to distinguish mb is supported
> > by the driver or not. I think prog->aux->xdp_has_frags is required to
> > distinguish it correctly.
> > So, I think we need something more.
> > Do you have any idea?
>
> Take a look at dev_xdp_prog_count(), something like that but only
> counting non-mb progs?

Thanks for very nice example, I will try it!
Taehee Yoo Oct. 31, 2024, 5:34 p.m. UTC | #5
On Thu, Oct 10, 2024 at 12:28 AM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Wed, 9 Oct 2024 22:54:17 +0900 Taehee Yoo wrote:
> > > This breaks previous behavior. The HDS reporting from get was
> > > introduced to signal to user space whether the page flip based
> > > TCP zero-copy (the one added some years ago not the recent one)
> > > will be usable with this NIC.
> > >
> > > When HW-GRO is enabled HDS will be working.
> > >
> > > I think that the driver should only track if the user has set the value
> > > to ENABLED (forced HDS), or to UKNOWN (driver default). Setting the HDS
> > > to disabled is not useful, don't support it.
> >
> > Okay, I will remove the disable feature in a v4 patch.
> > Before this patch, hds_threshold was rx-copybreak value.
> > How do you think hds_threshold should still follow rx-copybreak value
> > if it is UNKNOWN mode?
>
> IIUC the rx_copybreak only applies to the header? Or does it apply
> to the entire frame?
>
> If rx_copybreak applies to the entire frame and not just the first
> buffer (headers or headers+payload if not split) - no preference.
> If rx_copybreak only applies to the headers / first buffer then
> I'd keep them separate as they operate on a different length.
>
> > I think hds_threshold need to follow new tcp-data-split-thresh value in
> > ENABLE/UNKNOWN and make rx-copybreak pure software feature.
>
> Sounds good to me, but just to be clear:
>
> If user sets the HDS enable to UNKNOWN (or doesn't set it):
>  - GET returns (current behavior, AFAIU):
>    - DISABLED (if HW-GRO is disabled and MTU is not Jumbo)
>    - ENABLED (if HW-GRO is enabled of MTU is Jumbo)
> If user sets the HDS enable to ENABLED (force HDS on):
>  - GET returns ENABLED

While I'm writing a patch I face an ambiguous problem here.
ethnl_set_ring() first calls .get_ringparam() to get current config.
Then it calls .set_ringparam() after it sets the current config + new
config to param structures.
The bnxt_set_ringparam() may receive ETHTOOL_TCP_DATA_SPLIT_ENABLED
because two cases.
1. from user
2. from bnxt_get_ringparam() because of UNKNWON.
The problem is that the bnxt_set_ringparam() can't distinguish them.
The problem scenario is here.
1. tcp-data-split is UNKNOWN mode.
2. HDS is automatically enabled because one of LRO or GRO is enabled.
3. user changes ring parameter with following command
`ethtool -G eth0 rx 1024`
4. ethnl_set_rings() calls .get_ringparam() to get current config.
5. bnxt_get_ringparam() returns ENABLE of HDS because of UNKNWON mode.
6. ethnl_set_rings() calls .set_ringparam() after setting param with
configs comes from .get_ringparam().
7. bnxt_set_ringparam() is passed ETHTOOL_TCP_DATA_SPLIT_ENABLED but
the user didn't set it explicitly.
8. bnxt_set_ringparam() eventually force enables tcp-data-split.

I couldn't find a way to distinguish them so far.
I'm not sure if this is acceptable or not.
Maybe we need to modify a scenario?

>
> hds_threshold returns: some value, but it's only actually used if GET
> returns ENABLED.
>
> > But if so, it changes the default behavior.
>
> How so? The configuration of neither of those two is exposed to
> the user. We can keep the same defaults, until user overrides them.
>
> > How do you think about it?
> >
> > >
> > > >       ering->tx_max_pending = BNXT_MAX_TX_DESC_CNT;
> > > >
> > > >       ering->rx_pending = bp->rx_ring_size;
> > > > @@ -854,9 +858,25 @@ static int bnxt_set_ringparam(struct net_device *dev,
> > > >           (ering->tx_pending < BNXT_MIN_TX_DESC_CNT))
> > > >               return -EINVAL;
> > > >
> > > > +     if (kernel_ering->tcp_data_split != ETHTOOL_TCP_DATA_SPLIT_DISABLED &&
> > > > +         BNXT_RX_PAGE_MODE(bp)) {
> > > > +             NL_SET_ERR_MSG_MOD(extack, "tcp-data-split can not be enabled with XDP");
> > > > +             return -EINVAL;
> > > > +     }
> > >
> > > Technically just if the XDP does not support multi-buffer.
> > > Any chance we could do this check in the core?
> >
> > I think we can access xdp_rxq_info with netdev_rx_queue structure.
> > However, xdp_rxq_info is not sufficient to distinguish mb is supported
> > by the driver or not. I think prog->aux->xdp_has_frags is required to
> > distinguish it correctly.
> > So, I think we need something more.
> > Do you have any idea?
>
> Take a look at dev_xdp_prog_count(), something like that but only
> counting non-mb progs?
Jakub Kicinski Oct. 31, 2024, 11:56 p.m. UTC | #6
On Fri, 1 Nov 2024 02:34:59 +0900 Taehee Yoo wrote:
> While I'm writing a patch I face an ambiguous problem here.
> ethnl_set_ring() first calls .get_ringparam() to get current config.
> Then it calls .set_ringparam() after it sets the current config + new
> config to param structures.
> The bnxt_set_ringparam() may receive ETHTOOL_TCP_DATA_SPLIT_ENABLED
> because two cases.
> 1. from user
> 2. from bnxt_get_ringparam() because of UNKNWON.
> The problem is that the bnxt_set_ringparam() can't distinguish them.
> The problem scenario is here.
> 1. tcp-data-split is UNKNOWN mode.
> 2. HDS is automatically enabled because one of LRO or GRO is enabled.
> 3. user changes ring parameter with following command
> `ethtool -G eth0 rx 1024`
> 4. ethnl_set_rings() calls .get_ringparam() to get current config.
> 5. bnxt_get_ringparam() returns ENABLE of HDS because of UNKNWON mode.
> 6. ethnl_set_rings() calls .set_ringparam() after setting param with
> configs comes from .get_ringparam().
> 7. bnxt_set_ringparam() is passed ETHTOOL_TCP_DATA_SPLIT_ENABLED but
> the user didn't set it explicitly.
> 8. bnxt_set_ringparam() eventually force enables tcp-data-split.
> 
> I couldn't find a way to distinguish them so far.
> I'm not sure if this is acceptable or not.
> Maybe we need to modify a scenario?

I thought we discussed this, but I may be misremembering.
You may need to record in the core whether the setting came 
from the user or not (similarly to IFF_RXFH_CONFIGURED).
User setting UNKNWON would mean "reset".
Maybe I'm misunderstanding..
Taehee Yoo Nov. 1, 2024, 5:11 p.m. UTC | #7
On Fri, Nov 1, 2024 at 8:56 AM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Fri, 1 Nov 2024 02:34:59 +0900 Taehee Yoo wrote:
> > While I'm writing a patch I face an ambiguous problem here.
> > ethnl_set_ring() first calls .get_ringparam() to get current config.
> > Then it calls .set_ringparam() after it sets the current config + new
> > config to param structures.
> > The bnxt_set_ringparam() may receive ETHTOOL_TCP_DATA_SPLIT_ENABLED
> > because two cases.
> > 1. from user
> > 2. from bnxt_get_ringparam() because of UNKNWON.
> > The problem is that the bnxt_set_ringparam() can't distinguish them.
> > The problem scenario is here.
> > 1. tcp-data-split is UNKNOWN mode.
> > 2. HDS is automatically enabled because one of LRO or GRO is enabled.
> > 3. user changes ring parameter with following command
> > `ethtool -G eth0 rx 1024`
> > 4. ethnl_set_rings() calls .get_ringparam() to get current config.
> > 5. bnxt_get_ringparam() returns ENABLE of HDS because of UNKNWON mode.
> > 6. ethnl_set_rings() calls .set_ringparam() after setting param with
> > configs comes from .get_ringparam().
> > 7. bnxt_set_ringparam() is passed ETHTOOL_TCP_DATA_SPLIT_ENABLED but
> > the user didn't set it explicitly.
> > 8. bnxt_set_ringparam() eventually force enables tcp-data-split.
> >
> > I couldn't find a way to distinguish them so far.
> > I'm not sure if this is acceptable or not.
> > Maybe we need to modify a scenario?
>
> I thought we discussed this, but I may be misremembering.
> You may need to record in the core whether the setting came
> from the user or not (similarly to IFF_RXFH_CONFIGURED).
> User setting UNKNWON would mean "reset".
> Maybe I'm misunderstanding..

Thanks a lot for that!
I will try to add a new variable, that indicates tcp-data-split is set by
user. It would be the tcp_data_split_mod in the
kernel_ethtool_ringparam structure.

Thanks a lot!
Taehee Yoo
diff mbox series

Patch

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 8da211e083a4..f046478dfd2a 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -4454,6 +4454,7 @@  void bnxt_set_tpa_flags(struct bnxt *bp)
 static void bnxt_init_ring_params(struct bnxt *bp)
 {
 	bp->rx_copybreak = BNXT_DEFAULT_RX_COPYBREAK;
+	bp->flags |= BNXT_FLAG_HDS;
 }
 
 /* bp->rx_ring_size, bp->tx_ring_size, dev->mtu, BNXT_FLAG_{G|L}RO flags must
@@ -4474,7 +4475,7 @@  void bnxt_set_ring_params(struct bnxt *bp)
 	bp->rx_agg_ring_size = 0;
 	bp->rx_agg_nr_pages = 0;
 
-	if (bp->flags & BNXT_FLAG_TPA)
+	if (bp->flags & BNXT_FLAG_TPA || bp->flags & BNXT_FLAG_HDS)
 		agg_factor = min_t(u32, 4, 65536 / BNXT_RX_PAGE_SIZE);
 
 	bp->flags &= ~BNXT_FLAG_JUMBO;
@@ -6421,15 +6422,13 @@  static int bnxt_hwrm_vnic_set_hds(struct bnxt *bp, struct bnxt_vnic_info *vnic)
 
 	req->flags = cpu_to_le32(VNIC_PLCMODES_CFG_REQ_FLAGS_JUMBO_PLACEMENT);
 	req->enables = cpu_to_le32(VNIC_PLCMODES_CFG_REQ_ENABLES_JUMBO_THRESH_VALID);
+	req->jumbo_thresh = cpu_to_le16(bp->rx_buf_use_size);
 
-	if (BNXT_RX_PAGE_MODE(bp)) {
-		req->jumbo_thresh = cpu_to_le16(bp->rx_buf_use_size);
-	} else {
+	if (bp->flags & BNXT_FLAG_HDS) {
 		req->flags |= cpu_to_le32(VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV4 |
 					  VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV6);
 		req->enables |=
 			cpu_to_le32(VNIC_PLCMODES_CFG_REQ_ENABLES_HDS_THRESHOLD_VALID);
-		req->jumbo_thresh = cpu_to_le16(bp->rx_copybreak);
 		req->hds_threshold = cpu_to_le16(bp->rx_copybreak);
 	}
 	req->vnic_id = cpu_to_le32(vnic->fw_vnic_id);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index cff031993223..35601c71dfe9 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -2202,8 +2202,6 @@  struct bnxt {
 	#define BNXT_FLAG_TPA		(BNXT_FLAG_LRO | BNXT_FLAG_GRO)
 	#define BNXT_FLAG_JUMBO		0x10
 	#define BNXT_FLAG_STRIP_VLAN	0x20
-	#define BNXT_FLAG_AGG_RINGS	(BNXT_FLAG_JUMBO | BNXT_FLAG_GRO | \
-					 BNXT_FLAG_LRO)
 	#define BNXT_FLAG_RFS		0x100
 	#define BNXT_FLAG_SHARED_RINGS	0x200
 	#define BNXT_FLAG_PORT_STATS	0x400
@@ -2224,6 +2222,9 @@  struct bnxt {
 	#define BNXT_FLAG_ROCE_MIRROR_CAP	0x4000000
 	#define BNXT_FLAG_TX_COAL_CMPL	0x8000000
 	#define BNXT_FLAG_PORT_STATS_EXT	0x10000000
+	#define BNXT_FLAG_HDS		0x20000000
+	#define BNXT_FLAG_AGG_RINGS	(BNXT_FLAG_JUMBO | BNXT_FLAG_GRO | \
+					 BNXT_FLAG_LRO | BNXT_FLAG_HDS)
 
 	#define BNXT_FLAG_ALL_CONFIG_FEATS (BNXT_FLAG_TPA |		\
 					    BNXT_FLAG_RFS |		\
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index fdecdf8894b3..e9ef65dd2e7b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -829,12 +829,16 @@  static void bnxt_get_ringparam(struct net_device *dev,
 	if (bp->flags & BNXT_FLAG_AGG_RINGS) {
 		ering->rx_max_pending = BNXT_MAX_RX_DESC_CNT_JUM_ENA;
 		ering->rx_jumbo_max_pending = BNXT_MAX_RX_JUM_DESC_CNT;
-		kernel_ering->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_ENABLED;
 	} else {
 		ering->rx_max_pending = BNXT_MAX_RX_DESC_CNT;
 		ering->rx_jumbo_max_pending = 0;
-		kernel_ering->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_DISABLED;
 	}
+
+	if (bp->flags & BNXT_FLAG_HDS)
+		kernel_ering->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_ENABLED;
+	else
+		kernel_ering->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_DISABLED;
+
 	ering->tx_max_pending = BNXT_MAX_TX_DESC_CNT;
 
 	ering->rx_pending = bp->rx_ring_size;
@@ -854,9 +858,25 @@  static int bnxt_set_ringparam(struct net_device *dev,
 	    (ering->tx_pending < BNXT_MIN_TX_DESC_CNT))
 		return -EINVAL;
 
+	if (kernel_ering->tcp_data_split != ETHTOOL_TCP_DATA_SPLIT_DISABLED &&
+	    BNXT_RX_PAGE_MODE(bp)) {
+		NL_SET_ERR_MSG_MOD(extack, "tcp-data-split can not be enabled with XDP");
+		return -EINVAL;
+	}
+
 	if (netif_running(dev))
 		bnxt_close_nic(bp, false, false);
 
+	switch (kernel_ering->tcp_data_split) {
+	case ETHTOOL_TCP_DATA_SPLIT_UNKNOWN:
+	case ETHTOOL_TCP_DATA_SPLIT_ENABLED:
+		bp->flags |= BNXT_FLAG_HDS;
+		break;
+	case ETHTOOL_TCP_DATA_SPLIT_DISABLED:
+		bp->flags &= ~BNXT_FLAG_HDS;
+		break;
+	}
+
 	bp->rx_ring_size = ering->rx_pending;
 	bp->tx_ring_size = ering->tx_pending;
 	bnxt_set_ring_params(bp);
@@ -5346,6 +5366,7 @@  const struct ethtool_ops bnxt_ethtool_ops = {
 				     ETHTOOL_COALESCE_STATS_BLOCK_USECS |
 				     ETHTOOL_COALESCE_USE_ADAPTIVE_RX |
 				     ETHTOOL_COALESCE_USE_CQE,
+	.supported_ring_params	= ETHTOOL_RING_USE_TCP_DATA_SPLIT,
 	.get_link_ksettings	= bnxt_get_link_ksettings,
 	.set_link_ksettings	= bnxt_set_link_ksettings,
 	.get_fec_stats		= bnxt_get_fec_stats,