diff mbox series

[net-next,2/2] netdev_queues: fix -Wshadow / Sparse shadow warnings throughout the file

Message ID 20240329170000.3241460-3-aleksander.lobakin@intel.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series net: fix variable shadowing spam from headers | 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; no diff in generated;
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: 947 this patch: 947
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 5 maintainers not CCed: justinstitt@google.com ndesaulniers@google.com llvm@lists.linux.dev morbo@google.com nathan@kernel.org
netdev/build_clang success Errors and warnings before: 955 this patch: 955
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: 960 this patch: 960
netdev/checkpatch warning CHECK: Macro argument 'txq' may be better as '(txq)' to avoid precedence issues WARNING: A patch subject line should describe the change not the tool that found it WARNING: macros should not use a trailing semicolon
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Alexander Lobakin March 29, 2024, 5 p.m. UTC
Fix the following spam coming from <net/netdev_queues.h> when building
with W=12 and/or C=1:

Clang:

drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:9: warning: declaration shadows a local variable [-Wshadow]
 1992 |         return netif_txq_maybe_stop(nq, IDPF_DESC_UNUSED(tx_q), size, size);
      |                ^
./include/net/netdev_queues.h:137:11: note: expanded from macro 'netif_txq_maybe_stop'
  137 |                         _res = netif_txq_try_stop(txq, get_desc, start_thrs); \
      |                                ^
./include/net/netdev_queues.h:92:7: note: expanded from macro 'netif_txq_try_stop'
   92 |                 int _res;                                               \
      |                     ^
drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:9: note: previous declaration is here
./include/net/netdev_queues.h:133:7: note: expanded from macro 'netif_txq_maybe_stop'
  133 |                 int _res;                                               \
      |                     ^

Sparse:

drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:16: warning: symbol '_res' shadows an earlier one
drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:16: originally declared here

Use __UNIQUE_ID() in all of the macros which declare local variables.

Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
---
 include/net/netdev_queues.h | 54 +++++++++++++++++++++++++++----------
 1 file changed, 40 insertions(+), 14 deletions(-)

Comments

Jakub Kicinski March 29, 2024, 8:18 p.m. UTC | #1
On Fri, 29 Mar 2024 18:00:00 +0100 Alexander Lobakin wrote:
> drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:9: warning: declaration shadows a local variable [-Wshadow]
>  1992 |         return netif_txq_maybe_stop(nq, IDPF_DESC_UNUSED(tx_q), size, size);
>       |                ^
> ./include/net/netdev_queues.h:137:11: note: expanded from macro 'netif_txq_maybe_stop'
>   137 |                         _res = netif_txq_try_stop(txq, get_desc, start_thrs); \
>       |                                ^
> ./include/net/netdev_queues.h:92:7: note: expanded from macro 'netif_txq_try_stop'
>    92 |                 int _res;                                               \
>       |                     ^
> drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:9: note: previous declaration is here
> ./include/net/netdev_queues.h:133:7: note: expanded from macro 'netif_txq_maybe_stop'
>   133 |                 int _res;                                               \
>       |                     ^
> 
> Sparse:
> 
> drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:16: warning: symbol '_res' shadows an earlier one
> drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:16: originally declared here

I don't see these building with LLVM=1 W=12 C=1
and I really don't like complicating the code because the compiler
is stupid. Can't you solve this with some renames? Add another
underscore or something?
Jakub Kicinski March 29, 2024, 8:53 p.m. UTC | #2
On Fri, 29 Mar 2024 13:18:57 -0700 Jakub Kicinski wrote:
> > Sparse:
> > 
> > drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:16: warning: symbol '_res' shadows an earlier one
> > drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:16: originally declared here  
> 
> I don't see these building with LLVM=1 W=12 C=1
> and I really don't like complicating the code because the compiler
> is stupid. Can't you solve this with some renames? Add another
> underscore or something?

I'm stupid I tried on the test branch which already had your fix..

This is enough:

diff --git a/include/net/netdev_queues.h b/include/net/netdev_queues.h
index 1ec408585373..2270fbb99cf7 100644
--- a/include/net/netdev_queues.h
+++ b/include/net/netdev_queues.h
@@ -89,7 +89,7 @@ struct netdev_stat_ops {
 
 #define netif_txq_try_stop(txq, get_desc, start_thrs)			\
 	({								\
-		int _res;						\
+		int __res;						\
 									\
 		netif_tx_stop_queue(txq);				\
 		/* Producer index and stop bit must be visible		\
@@ -101,12 +101,12 @@ struct netdev_stat_ops {
 		/* We need to check again in a case another		\
 		 * CPU has just made room available.			\
 		 */							\
-		_res = 0;						\
+		__res = 0;						\
 		if (unlikely(get_desc >= start_thrs)) {			\
 			netif_tx_start_queue(txq);			\
-			_res = -1;					\
+			__res = -1;					\
 		}							\
-		_res;							\
+		__res;							\
 	})								\
 
 /**
Alexander Lobakin April 2, 2024, 11:53 a.m. UTC | #3
From: Jakub Kicinski <kuba@kernel.org>
Date: Fri, 29 Mar 2024 13:53:44 -0700

> On Fri, 29 Mar 2024 13:18:57 -0700 Jakub Kicinski wrote:
>>> Sparse:
>>>
>>> drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:16: warning: symbol '_res' shadows an earlier one
>>> drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:16: originally declared here  
>>
>> I don't see these building with LLVM=1 W=12 C=1
>> and I really don't like complicating the code because the compiler
>> is stupid. Can't you solve this with some renames? Add another

It's not the compiler, its warnings are valid actually. Shadowing makes
it very easy to confuse variables and make bugs...

>> underscore or something?
> 
> I'm stupid I tried on the test branch which already had your fix..

:D Sometimes it happens.

> 
> This is enough:
> 
> diff --git a/include/net/netdev_queues.h b/include/net/netdev_queues.h
> index 1ec408585373..2270fbb99cf7 100644
> --- a/include/net/netdev_queues.h
> +++ b/include/net/netdev_queues.h
> @@ -89,7 +89,7 @@ struct netdev_stat_ops {
>  
>  #define netif_txq_try_stop(txq, get_desc, start_thrs)			\
>  	({								\
> -		int _res;						\
> +		int __res;						\
>  									\
>  		netif_tx_stop_queue(txq);				\
>  		/* Producer index and stop bit must be visible		\
> @@ -101,12 +101,12 @@ struct netdev_stat_ops {
>  		/* We need to check again in a case another		\
>  		 * CPU has just made room available.			\
>  		 */							\
> -		_res = 0;						\
> +		__res = 0;						\
>  		if (unlikely(get_desc >= start_thrs)) {			\
>  			netif_tx_start_queue(txq);			\
> -			_res = -1;					\
> +			__res = -1;					\
>  		}							\
> -		_res;							\
> +		__res;							\
>  	})								\
>  
>  /**

But what if there's a function which calls one of these functions and
already has _res or __res or something? I know renaming is enough for
the warnings I mentioned, but without __UNIQUE_ID() anything can happen
anytime, so I wanted to fix that once and for all :z

I already saw some macros which have a layer of indirection for
__UNIQUE_ID(), but previously they didn't and then there were fixes
which added underscores, renamed variables etc etc...

Thanks,
Olek
Eric Dumazet April 2, 2024, 12:45 p.m. UTC | #4
On Tue, Apr 2, 2024 at 1:55 PM Alexander Lobakin
<aleksander.lobakin@intel.com> wrote:
>
> From: Jakub Kicinski <kuba@kernel.org>
> Date: Fri, 29 Mar 2024 13:53:44 -0700
>
> > On Fri, 29 Mar 2024 13:18:57 -0700 Jakub Kicinski wrote:
> >>> Sparse:
> >>>
> >>> drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:16: warning: symbol '_res' shadows an earlier one
> >>> drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:16: originally declared here
> >>
> >> I don't see these building with LLVM=1 W=12 C=1
> >> and I really don't like complicating the code because the compiler
> >> is stupid. Can't you solve this with some renames? Add another
>
> It's not the compiler, its warnings are valid actually. Shadowing makes
> it very easy to confuse variables and make bugs...
>
> >> underscore or something?
> >
> > I'm stupid I tried on the test branch which already had your fix..
>
> :D Sometimes it happens.
>
> >
> > This is enough:
> >
> > diff --git a/include/net/netdev_queues.h b/include/net/netdev_queues.h
> > index 1ec408585373..2270fbb99cf7 100644
> > --- a/include/net/netdev_queues.h
> > +++ b/include/net/netdev_queues.h
> > @@ -89,7 +89,7 @@ struct netdev_stat_ops {
> >
> >  #define netif_txq_try_stop(txq, get_desc, start_thrs)                        \
> >       ({                                                              \
> > -             int _res;                                               \
> > +             int __res;                                              \
> >                                                                       \
> >               netif_tx_stop_queue(txq);                               \
> >               /* Producer index and stop bit must be visible          \
> > @@ -101,12 +101,12 @@ struct netdev_stat_ops {
> >               /* We need to check again in a case another             \
> >                * CPU has just made room available.                    \
> >                */                                                     \
> > -             _res = 0;                                               \
> > +             __res = 0;                                              \
> >               if (unlikely(get_desc >= start_thrs)) {                 \
> >                       netif_tx_start_queue(txq);                      \
> > -                     _res = -1;                                      \
> > +                     __res = -1;                                     \
> >               }                                                       \
> > -             _res;                                                   \
> > +             __res;                                                  \
> >       })                                                              \
> >
> >  /**
>
> But what if there's a function which calls one of these functions and
> already has _res or __res or something? I know renaming is enough for
> the warnings I mentioned, but without __UNIQUE_ID() anything can happen
> anytime, so I wanted to fix that once and for all :z
>
> I already saw some macros which have a layer of indirection for
> __UNIQUE_ID(), but previously they didn't and then there were fixes
> which added underscores, renamed variables etc etc...
>

We have hundreds of macros in include/ directory which use local names without
__UNIQUE_ID()

What is the plan ? Hundreds of patches obfuscating them more than they are ?

Can you show us how rb_entry_safe() (random choice) would be rewritten ?
Alexander Lobakin April 2, 2024, 3:53 p.m. UTC | #5
From: Eric Dumazet <edumazet@google.com>
Date: Tue, 2 Apr 2024 14:45:07 +0200

> On Tue, Apr 2, 2024 at 1:55 PM Alexander Lobakin
> <aleksander.lobakin@intel.com> wrote:
>>
>> From: Jakub Kicinski <kuba@kernel.org>
>> Date: Fri, 29 Mar 2024 13:53:44 -0700
>>
>>> On Fri, 29 Mar 2024 13:18:57 -0700 Jakub Kicinski wrote:
>>>>> Sparse:
>>>>>
>>>>> drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:16: warning: symbol '_res' shadows an earlier one
>>>>> drivers/net/ethernet/intel/idpf/idpf_txrx.c:1992:16: originally declared here
>>>>
>>>> I don't see these building with LLVM=1 W=12 C=1
>>>> and I really don't like complicating the code because the compiler
>>>> is stupid. Can't you solve this with some renames? Add another
>>
>> It's not the compiler, its warnings are valid actually. Shadowing makes
>> it very easy to confuse variables and make bugs...
>>
>>>> underscore or something?
>>>
>>> I'm stupid I tried on the test branch which already had your fix..
>>
>> :D Sometimes it happens.
>>
>>>
>>> This is enough:
>>>
>>> diff --git a/include/net/netdev_queues.h b/include/net/netdev_queues.h
>>> index 1ec408585373..2270fbb99cf7 100644
>>> --- a/include/net/netdev_queues.h
>>> +++ b/include/net/netdev_queues.h
>>> @@ -89,7 +89,7 @@ struct netdev_stat_ops {
>>>
>>>  #define netif_txq_try_stop(txq, get_desc, start_thrs)                        \
>>>       ({                                                              \
>>> -             int _res;                                               \
>>> +             int __res;                                              \
>>>                                                                       \
>>>               netif_tx_stop_queue(txq);                               \
>>>               /* Producer index and stop bit must be visible          \
>>> @@ -101,12 +101,12 @@ struct netdev_stat_ops {
>>>               /* We need to check again in a case another             \
>>>                * CPU has just made room available.                    \
>>>                */                                                     \
>>> -             _res = 0;                                               \
>>> +             __res = 0;                                              \
>>>               if (unlikely(get_desc >= start_thrs)) {                 \
>>>                       netif_tx_start_queue(txq);                      \
>>> -                     _res = -1;                                      \
>>> +                     __res = -1;                                     \
>>>               }                                                       \
>>> -             _res;                                                   \
>>> +             __res;                                                  \
>>>       })                                                              \
>>>
>>>  /**
>>
>> But what if there's a function which calls one of these functions and
>> already has _res or __res or something? I know renaming is enough for
>> the warnings I mentioned, but without __UNIQUE_ID() anything can happen
>> anytime, so I wanted to fix that once and for all :z
>>
>> I already saw some macros which have a layer of indirection for
>> __UNIQUE_ID(), but previously they didn't and then there were fixes
>> which added underscores, renamed variables etc etc...
>>
> 
> We have hundreds of macros in include/ directory which use local names without
> __UNIQUE_ID()

Most of them were added before __UNIQUE_ID() became norm, weren't they?
Lots of them were switched to __UNIQUE_ID() because of issues, weren't they?

> 
> What is the plan ? Hundreds of patches obfuscating them more than they are ?

Only those which flood the console when building with W=12 C=1 to
recheck that my new code is fine.

> 
> Can you show us how rb_entry_safe() (random choice) would be rewritten ?

Is it unique in some way?

#define _rb_entry_safe(ptr, type, member, ____ptr) \
	({ typeof(ptr) ____ptr = (ptr); \
	   ____ptr ? rb_entry(____ptr, type, member) : NULL; \
	})
#define rb_entry_safe(ptr, type, member)		\
	_rb_entry_safe(ptr, type, member,		\
		       __UNIQUE_ID(ptr_)

(@____ptr can be renamed if needed, this one would give the smallest
 code diff)

If you think +1 layer is a terrible obfuscating, look at
<linux/fortify-string.h> :D

Thanks,
Olek
Jakub Kicinski April 2, 2024, 4:48 p.m. UTC | #6
On Tue, 2 Apr 2024 17:53:08 +0200 Alexander Lobakin wrote:
> >> But what if there's a function which calls one of these functions and
> >> already has _res or __res or something? I know renaming is enough for
> >> the warnings I mentioned, but without __UNIQUE_ID() anything can happen
> >> anytime, so I wanted to fix that once and for all :z
> >>
> >> I already saw some macros which have a layer of indirection for
> >> __UNIQUE_ID(), but previously they didn't and then there were fixes
> >> which added underscores, renamed variables etc etc...
> >>  
> > 
> > We have hundreds of macros in include/ directory which use local names without
> > __UNIQUE_ID()  
> 
> Most of them were added before __UNIQUE_ID() became norm, weren't they?
> Lots of them were switched to __UNIQUE_ID() because of issues, weren't they?

Lots of ugly code gets into the kernel. Just look at your patch and
then look at mine.

I understand __UNIQUE_ID() may be useful for libraries or global
macros in the kernel, but within a subsystem, for macros which are
rarely used, we can just patch the macro var names. Sprinkling
__UNIQUE_ID() is in bad taste.

> > What is the plan ? Hundreds of patches obfuscating them more than they are ?  
> 
> Only those which flood the console when building with W=12 C=1 to
> recheck that my new code is fine.

I have never seen this warning be useful in the context of a macro.
Sure if you shadow inside a function that may be pernicious.
But well written macro will not be a problem.
I guess that it may be really hard for the compiler to understand that
something was a macro but perhaps we should either:
 - ignore the warning if the shadowing happens inside a compound
   statement
 - add a declaration attribute to turn the warning off
?
diff mbox series

Patch

diff --git a/include/net/netdev_queues.h b/include/net/netdev_queues.h
index 1ec408585373..317d6bfe32c7 100644
--- a/include/net/netdev_queues.h
+++ b/include/net/netdev_queues.h
@@ -87,14 +87,14 @@  struct netdev_stat_ops {
  * be updated before invoking the macros.
  */
 
-#define netif_txq_try_stop(txq, get_desc, start_thrs)			\
+#define _netif_txq_try_stop(txq, get_desc, start_thrs, _res)		\
 	({								\
 		int _res;						\
 									\
 		netif_tx_stop_queue(txq);				\
 		/* Producer index and stop bit must be visible		\
 		 * to consumer before we recheck.			\
-		 * Pairs with a barrier in __netif_txq_completed_wake(). \
+		 * Pairs with a barrier in ___netif_txq_completed_wake(). \
 		 */							\
 		smp_mb__after_atomic();					\
 									\
@@ -107,16 +107,20 @@  struct netdev_stat_ops {
 			_res = -1;					\
 		}							\
 		_res;							\
-	})								\
+	})
+#define netif_txq_try_stop(txq, get_desc, start_thrs)			\
+	_netif_txq_try_stop(txq, get_desc, start_thrs,			\
+			    __UNIQUE_ID(res_))
 
 /**
- * netif_txq_maybe_stop() - locklessly stop a Tx queue, if needed
+ * _netif_txq_maybe_stop() - locklessly stop a Tx queue, if needed
  * @txq:	struct netdev_queue to stop/start
  * @get_desc:	get current number of free descriptors (see requirements below!)
  * @stop_thrs:	minimal number of available descriptors for queue to be left
  *		enabled
  * @start_thrs:	minimal number of descriptors to re-enable the queue, can be
  *		equal to @stop_thrs or higher to avoid frequent waking
+ * @_res: __UNIQUE_ID() to avoid variable name clash
  *
  * All arguments may be evaluated multiple times, beware of side effects.
  * @get_desc must be a formula or a function call, it must always
@@ -128,7 +132,8 @@  struct netdev_stat_ops {
  *	 1 if the queue was left enabled
  *	-1 if the queue was re-enabled (raced with waking)
  */
-#define netif_txq_maybe_stop(txq, get_desc, stop_thrs, start_thrs)	\
+#define _netif_txq_maybe_stop(txq, get_desc, stop_thrs, start_thrs,	\
+			      _res)					\
 	({								\
 		int _res;						\
 									\
@@ -136,7 +141,10 @@  struct netdev_stat_ops {
 		if (unlikely(get_desc < stop_thrs))			\
 			_res = netif_txq_try_stop(txq, get_desc, start_thrs); \
 		_res;							\
-	})								\
+	})
+#define netif_txq_maybe_stop(txq, get_desc, stop_thrs, start_thrs)	\
+	_netif_txq_maybe_stop(txq, get_desc, stop_thrs, start_thrs,	\
+			      __UNIQUE_ID(res_))
 
 /* Variant of netdev_tx_completed_queue() which guarantees smp_mb() if
  * @bytes != 0, regardless of kernel config.
@@ -152,7 +160,7 @@  netdev_txq_completed_mb(struct netdev_queue *dev_queue,
 }
 
 /**
- * __netif_txq_completed_wake() - locklessly wake a Tx queue, if needed
+ * ___netif_txq_completed_wake() - locklessly wake a Tx queue, if needed
  * @txq:	struct netdev_queue to stop/start
  * @pkts:	number of packets completed
  * @bytes:	number of bytes completed
@@ -160,6 +168,7 @@  netdev_txq_completed_mb(struct netdev_queue *dev_queue,
  * @start_thrs:	minimal number of descriptors to re-enable the queue
  * @down_cond:	down condition, predicate indicating that the queue should
  *		not be woken up even if descriptors are available
+ * @_res: __UNIQUE_ID() to avoid variable name clash
  *
  * All arguments may be evaluated multiple times.
  * @get_desc must be a formula or a function call, it must always
@@ -171,15 +180,15 @@  netdev_txq_completed_mb(struct netdev_queue *dev_queue,
  *	 1 if the queue was already enabled (or disabled but @down_cond is true)
  *	-1 if the queue was left unchanged (@start_thrs not reached)
  */
-#define __netif_txq_completed_wake(txq, pkts, bytes,			\
-				   get_desc, start_thrs, down_cond)	\
+#define ___netif_txq_completed_wake(txq, pkts, bytes, get_desc,		\
+				    start_thrs, down_cond, _res)	\
 	({								\
 		int _res;						\
 									\
 		/* Report to BQL and piggy back on its barrier.		\
 		 * Barrier makes sure that anybody stopping the queue	\
 		 * after this point sees the new consumer index.	\
-		 * Pairs with barrier in netif_txq_try_stop().		\
+		 * Pairs with barrier in _netif_txq_try_stop().		\
 		 */							\
 		netdev_txq_completed_mb(txq, pkts, bytes);		\
 									\
@@ -194,30 +203,43 @@  netdev_txq_completed_mb(struct netdev_queue *dev_queue,
 		}							\
 		_res;							\
 	})
+#define __netif_txq_completed_wake(txq, pkts, bytes, get_desc,		\
+				   start_thrs, down_cond)		\
+	___netif_txq_completed_wake(txq, pkts, bytes, get_desc,		\
+				    start_thrs, down_cond,		\
+				    __UNIQUE_ID(res_))
 
 #define netif_txq_completed_wake(txq, pkts, bytes, get_desc, start_thrs) \
 	__netif_txq_completed_wake(txq, pkts, bytes, get_desc, start_thrs, false)
 
 /* subqueue variants follow */
 
-#define netif_subqueue_try_stop(dev, idx, get_desc, start_thrs)		\
+#define _netif_subqueue_try_stop(dev, idx, get_desc, start_thrs, txq)	\
 	({								\
 		struct netdev_queue *txq;				\
 									\
 		txq = netdev_get_tx_queue(dev, idx);			\
 		netif_txq_try_stop(txq, get_desc, start_thrs);		\
 	})
+#define netif_subqueue_try_stop(dev, idx, get_desc, start_thrs)		\
+	_netif_subqueue_try_stop(dev, idx, get_desc, start_thrs,	\
+				 __UNIQUE_ID(txq_))
 
-#define netif_subqueue_maybe_stop(dev, idx, get_desc, stop_thrs, start_thrs) \
+#define _netif_subqueue_maybe_stop(dev, idx, get_desc, stop_thrs,	\
+				   start_thrs, txq)			\
 	({								\
 		struct netdev_queue *txq;				\
 									\
 		txq = netdev_get_tx_queue(dev, idx);			\
 		netif_txq_maybe_stop(txq, get_desc, stop_thrs, start_thrs); \
 	})
+#define netif_subqueue_maybe_stop(dev, idx, get_desc, stop_thrs,	\
+				  start_thrs)				\
+	_netif_subqueue_maybe_stop(dev, idx, get_desc, stop_thrs,	\
+				   start_thrs, __UNIQUE_ID(txq_))
 
-#define netif_subqueue_completed_wake(dev, idx, pkts, bytes,		\
-				      get_desc, start_thrs)		\
+#define _netif_subqueue_completed_wake(dev, idx, pkts, bytes, get_desc,	\
+				       start_thrs, txq)			\
 	({								\
 		struct netdev_queue *txq;				\
 									\
@@ -225,5 +247,9 @@  netdev_txq_completed_mb(struct netdev_queue *dev_queue,
 		netif_txq_completed_wake(txq, pkts, bytes,		\
 					 get_desc, start_thrs);		\
 	})
+#define netif_subqueue_completed_wake(dev, idx, pkts, bytes, get_desc,	\
+				      start_thrs)			\
+	_netif_subqueue_completed_wake(dev, idx, pkts, bytes, get_desc,	\
+				       start_thrs, __UNIQUE_ID(txq_))
 
 #endif