netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alexander Duyck <alexander.h.duyck@intel.com>
To: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>,
	davem@davemloft.net, netdev@vger.kernel.org, gospo@redhat.com,
	sassmann@redhat.com
Subject: Re: [net-next 05/10] igb: Update igb to use a path similar to ixgbe to determine when to stop Tx
Date: Fri, 08 Feb 2013 09:11:10 -0800	[thread overview]
Message-ID: <511531AE.8030807@intel.com> (raw)
In-Reply-To: <1360326369.28557.95.camel@edumazet-glaptop>

On 2/8/2013 4:26 AM, Eric Dumazet wrote:
> On Fri, 2013-02-08 at 02:39 -0800, Jeff Kirsher wrote:
>> From: Alexander Duyck <alexander.h.duyck@intel.com>
>>
>> After reviewing the igb and ixgbe code I realized there are a few issues in
>> how the code is structured.  Specifically we are not checking the size of the
>> buffers being used in transmits and we are not using the same value to
>> determine when to stop or start a Tx queue.  As such the code is prone to be
>> buggy.
>>
>> This patch makes it so that we have one value DESC_NEEDED that we will use for
>> starting and stopping the queue.  In addition we will check the size of
>> buffers being used when setting up a transmit so as to avoid a possible buffer
>> overrun if we were to receive a frame with a block of data larger than 32K in
>> skb->data.
>>
>> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
>> Tested-by: Aaron Brown <aaron.f.brown@intel.com>
>> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
>> ---
>>   drivers/net/ethernet/intel/igb/igb.h      | 13 +++++++++++--
>>   drivers/net/ethernet/intel/igb/igb_main.c | 32 ++++++++++++++++++-------------
>>   2 files changed, 30 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
>> index afdb8bb..d27edbc 100644
>> --- a/drivers/net/ethernet/intel/igb/igb.h
>> +++ b/drivers/net/ethernet/intel/igb/igb.h
>> @@ -139,8 +139,6 @@ struct vf_data_storage {
>>   #define IGB_RX_HDR_LEN		IGB_RXBUFFER_256
>>   #define IGB_RX_BUFSZ		IGB_RXBUFFER_2048
>>   
>> -/* How many Tx Descriptors do we need to call netif_wake_queue ? */
>> -#define IGB_TX_QUEUE_WAKE	16
>>   /* How many Rx Buffers do we bundle into one write to the hardware ? */
>>   #define IGB_RX_BUFFER_WRITE	16	/* Must be power of 2 */
>>   
>> @@ -169,6 +167,17 @@ enum igb_tx_flags {
>>   #define IGB_TX_FLAGS_VLAN_MASK		0xffff0000
>>   #define IGB_TX_FLAGS_VLAN_SHIFT	16
>>   
>> +/*
>> + * The largest size we can write to the descriptor is 65535.  In order to
>> + * maintain a power of two alignment we have to limit ourselves to 32K.
>> + */
>> +#define IGB_MAX_TXD_PWR	15
>> +#define IGB_MAX_DATA_PER_TXD	(1 << IGB_MAX_TXD_PWR)
>> +
>> +/* Tx Descriptors needed, worst case */
>> +#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGB_MAX_DATA_PER_TXD)
>> +#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
>> +
>>   /* wrapper around a pointer to a socket buffer,
>>    * so a DMA handle can be stored along with the buffer */
>>   struct igb_tx_buffer {
>> diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
>> index ebf8384..e69dd4f 100644
>> --- a/drivers/net/ethernet/intel/igb/igb_main.c
>> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
>> @@ -4434,13 +4434,6 @@ static void igb_tx_olinfo_status(struct igb_ring *tx_ring,
>>   	tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
>>   }
>>   
>> -/*
>> - * The largest size we can write to the descriptor is 65535.  In order to
>> - * maintain a power of two alignment we have to limit ourselves to 32K.
>> - */
>> -#define IGB_MAX_TXD_PWR	15
>> -#define IGB_MAX_DATA_PER_TXD	(1<<IGB_MAX_TXD_PWR)
>> -
>>   static void igb_tx_map(struct igb_ring *tx_ring,
>>   		       struct igb_tx_buffer *first,
>>   		       const u8 hdr_len)
>> @@ -4609,15 +4602,27 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
>>   	struct igb_tx_buffer *first;
>>   	int tso;
>>   	u32 tx_flags = 0;
>> +#if PAGE_SIZE > IGB_MAX_DATA_PER_TXD
>> +	unsigned short f;
>> +#endif
>> +	u16 count = TXD_USE_COUNT(skb_headlen(skb));
>>   	__be16 protocol = vlan_get_protocol(skb);
>>   	u8 hdr_len = 0;
>>   
>> -	/* need: 1 descriptor per page,
>> +	/*
>> +	 * need: 1 descriptor per page * PAGE_SIZE/IGB_MAX_DATA_PER_TXD,
>> +	 *       + 1 desc for skb_headlen/IGB_MAX_DATA_PER_TXD,
>>   	 *       + 2 desc gap to keep tail from touching head,
>> -	 *       + 1 desc for skb->data,
>>   	 *       + 1 desc for context descriptor,
>> -	 * otherwise try next time */
>> -	if (igb_maybe_stop_tx(tx_ring, skb_shinfo(skb)->nr_frags + 4)) {
>> +	 * otherwise try next time
>> +	 */
>> +#if PAGE_SIZE > IGB_MAX_DATA_PER_TXD
> This code assumes a frag is at most PAGE_SIZE, but its not true.
>
>> +	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
>> +		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
>> +#else
>> +	count += skb_shinfo(skb)->nr_frags;
>> +#endif
> Current practical limit is 32768 bytes on x86

For igb the IGB_MAX_DATA_PER_TXD is 32K as well.  So if I am not 
mistaken we should be fine.  The only time we risk exceeding that is if 
we have 64K page size.  It sounds like we may need to work in the ixgbe 
driver though since I believe the limit for it is only 16K per descriptor.

I will also submit an update for this patch that replaces PAGE_SIZE with 
NETDEV_FRAG_PAGE_MAX_SIZE in order to keep the two in sync.

Thanks,

Alex

  reply	other threads:[~2013-02-08 17:11 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-02-08 10:39 [net-next 00/10][pull request] Intel Wired LAN Driver Updates Jeff Kirsher
2013-02-08 10:39 ` [net-next 01/10] igb: Support using build_skb in the case that jumbo frames are disabled Jeff Kirsher
2013-02-08 10:39 ` [net-next 02/10] igb: Fix for improper exit in igb_get_i2c_client Jeff Kirsher
2013-02-08 10:39 ` [net-next 03/10] igb: Fix for improper allocation flag " Jeff Kirsher
2013-02-08 10:39 ` [net-next 04/10] igb: Fix for sparse warning " Jeff Kirsher
2013-02-11 17:05   ` Ben Hutchings
2013-02-11 17:27     ` Wyborny, Carolyn
2013-02-12 17:12     ` Wyborny, Carolyn
2013-02-12 17:17     ` Wyborny, Carolyn
2013-02-08 10:39 ` [net-next 05/10] igb: Update igb to use a path similar to ixgbe to determine when to stop Tx Jeff Kirsher
2013-02-08 12:26   ` Eric Dumazet
2013-02-08 17:11     ` Alexander Duyck [this message]
2013-02-08 19:18       ` David Miller
2013-02-08 20:19         ` Alexander Duyck
2013-02-08 10:39 ` [net-next 06/10] igb: Initialize PHY function pointers Jeff Kirsher
2013-02-08 10:39 ` [net-next 07/10] igb: Initialize NVM " Jeff Kirsher
2013-02-08 10:39 ` [net-next 08/10] igb: Intialize MAC " Jeff Kirsher
2013-02-08 10:39 ` [net-next 09/10] igb: Refractoring function pointers in igb_get_invariants function Jeff Kirsher
2013-02-08 10:39 ` [net-next 10/10] ixgbe: refactor initialization of feature flags Jeff Kirsher

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=511531AE.8030807@intel.com \
    --to=alexander.h.duyck@intel.com \
    --cc=davem@davemloft.net \
    --cc=eric.dumazet@gmail.com \
    --cc=gospo@redhat.com \
    --cc=jeffrey.t.kirsher@intel.com \
    --cc=netdev@vger.kernel.org \
    --cc=sassmann@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).