aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2011-08-26 03:45:15 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-10-08 01:25:52 -0400
commit7af40ad909e3e92a1cbb728999c427d2fa3b381d (patch)
treee0c44508a4ca6f300ff999e9ffabb2723e5fedd9 /drivers/net
parent1d0861acfb24d0ca0661ff5a156b992b2c589458 (diff)
igb: push data into first igb_tx_buffer sooner to reduce stack usage
Instead of storing most of the data for the TX hot path in the stack until we are ready to write the descriptor we can save ourselves some time and effort by pushing the SKB, tx_flags, gso_size, bytecount, and protocol into the first igb_tx_buffer since that is where we will end up putting it anyway. 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>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h1
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c103
2 files changed, 54 insertions, 50 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 77793a9debcc..de35c02876aa 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -146,6 +146,7 @@ struct igb_tx_buffer {
146 struct sk_buff *skb; 146 struct sk_buff *skb;
147 unsigned int bytecount; 147 unsigned int bytecount;
148 u16 gso_segs; 148 u16 gso_segs;
149 __be16 protocol;
149 dma_addr_t dma; 150 dma_addr_t dma;
150 u32 length; 151 u32 length;
151 u32 tx_flags; 152 u32 tx_flags;
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 862dd7c0cc70..1c234f03b21c 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3975,10 +3975,11 @@ void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens,
3975 context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); 3975 context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
3976} 3976}
3977 3977
3978static inline int igb_tso(struct igb_ring *tx_ring, struct sk_buff *skb, 3978static int igb_tso(struct igb_ring *tx_ring,
3979 u32 tx_flags, __be16 protocol, u8 *hdr_len) 3979 struct igb_tx_buffer *first,
3980 u8 *hdr_len)
3980{ 3981{
3981 int err; 3982 struct sk_buff *skb = first->skb;
3982 u32 vlan_macip_lens, type_tucmd; 3983 u32 vlan_macip_lens, type_tucmd;
3983 u32 mss_l4len_idx, l4len; 3984 u32 mss_l4len_idx, l4len;
3984 3985
@@ -3986,7 +3987,7 @@ static inline int igb_tso(struct igb_ring *tx_ring, struct sk_buff *skb,
3986 return 0; 3987 return 0;
3987 3988
3988 if (skb_header_cloned(skb)) { 3989 if (skb_header_cloned(skb)) {
3989 err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); 3990 int err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
3990 if (err) 3991 if (err)
3991 return err; 3992 return err;
3992 } 3993 }
@@ -3994,7 +3995,7 @@ static inline int igb_tso(struct igb_ring *tx_ring, struct sk_buff *skb,
3994 /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */ 3995 /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
3995 type_tucmd = E1000_ADVTXD_TUCMD_L4T_TCP; 3996 type_tucmd = E1000_ADVTXD_TUCMD_L4T_TCP;
3996 3997
3997 if (protocol == __constant_htons(ETH_P_IP)) { 3998 if (first->protocol == __constant_htons(ETH_P_IP)) {
3998 struct iphdr *iph = ip_hdr(skb); 3999 struct iphdr *iph = ip_hdr(skb);
3999 iph->tot_len = 0; 4000 iph->tot_len = 0;
4000 iph->check = 0; 4001 iph->check = 0;
@@ -4003,16 +4004,26 @@ static inline int igb_tso(struct igb_ring *tx_ring, struct sk_buff *skb,
4003 IPPROTO_TCP, 4004 IPPROTO_TCP,
4004 0); 4005 0);
4005 type_tucmd |= E1000_ADVTXD_TUCMD_IPV4; 4006 type_tucmd |= E1000_ADVTXD_TUCMD_IPV4;
4007 first->tx_flags |= IGB_TX_FLAGS_TSO |
4008 IGB_TX_FLAGS_CSUM |
4009 IGB_TX_FLAGS_IPV4;
4006 } else if (skb_is_gso_v6(skb)) { 4010 } else if (skb_is_gso_v6(skb)) {
4007 ipv6_hdr(skb)->payload_len = 0; 4011 ipv6_hdr(skb)->payload_len = 0;
4008 tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, 4012 tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
4009 &ipv6_hdr(skb)->daddr, 4013 &ipv6_hdr(skb)->daddr,
4010 0, IPPROTO_TCP, 0); 4014 0, IPPROTO_TCP, 0);
4015 first->tx_flags |= IGB_TX_FLAGS_TSO |
4016 IGB_TX_FLAGS_CSUM;
4011 } 4017 }
4012 4018
4019 /* compute header lengths */
4013 l4len = tcp_hdrlen(skb); 4020 l4len = tcp_hdrlen(skb);
4014 *hdr_len = skb_transport_offset(skb) + l4len; 4021 *hdr_len = skb_transport_offset(skb) + l4len;
4015 4022
4023 /* update gso size and bytecount with header size */
4024 first->gso_segs = skb_shinfo(skb)->gso_segs;
4025 first->bytecount += (first->gso_segs - 1) * *hdr_len;
4026
4016 /* MSS L4LEN IDX */ 4027 /* MSS L4LEN IDX */
4017 mss_l4len_idx = l4len << E1000_ADVTXD_L4LEN_SHIFT; 4028 mss_l4len_idx = l4len << E1000_ADVTXD_L4LEN_SHIFT;
4018 mss_l4len_idx |= skb_shinfo(skb)->gso_size << E1000_ADVTXD_MSS_SHIFT; 4029 mss_l4len_idx |= skb_shinfo(skb)->gso_size << E1000_ADVTXD_MSS_SHIFT;
@@ -4020,26 +4031,26 @@ static inline int igb_tso(struct igb_ring *tx_ring, struct sk_buff *skb,
4020 /* VLAN MACLEN IPLEN */ 4031 /* VLAN MACLEN IPLEN */
4021 vlan_macip_lens = skb_network_header_len(skb); 4032 vlan_macip_lens = skb_network_header_len(skb);
4022 vlan_macip_lens |= skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT; 4033 vlan_macip_lens |= skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT;
4023 vlan_macip_lens |= tx_flags & IGB_TX_FLAGS_VLAN_MASK; 4034 vlan_macip_lens |= first->tx_flags & IGB_TX_FLAGS_VLAN_MASK;
4024 4035
4025 igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx); 4036 igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx);
4026 4037
4027 return 1; 4038 return 1;
4028} 4039}
4029 4040
4030static inline bool igb_tx_csum(struct igb_ring *tx_ring, struct sk_buff *skb, 4041static void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first)
4031 u32 tx_flags, __be16 protocol)
4032{ 4042{
4043 struct sk_buff *skb = first->skb;
4033 u32 vlan_macip_lens = 0; 4044 u32 vlan_macip_lens = 0;
4034 u32 mss_l4len_idx = 0; 4045 u32 mss_l4len_idx = 0;
4035 u32 type_tucmd = 0; 4046 u32 type_tucmd = 0;
4036 4047
4037 if (skb->ip_summed != CHECKSUM_PARTIAL) { 4048 if (skb->ip_summed != CHECKSUM_PARTIAL) {
4038 if (!(tx_flags & IGB_TX_FLAGS_VLAN)) 4049 if (!(first->tx_flags & IGB_TX_FLAGS_VLAN))
4039 return false; 4050 return;
4040 } else { 4051 } else {
4041 u8 l4_hdr = 0; 4052 u8 l4_hdr = 0;
4042 switch (protocol) { 4053 switch (first->protocol) {
4043 case __constant_htons(ETH_P_IP): 4054 case __constant_htons(ETH_P_IP):
4044 vlan_macip_lens |= skb_network_header_len(skb); 4055 vlan_macip_lens |= skb_network_header_len(skb);
4045 type_tucmd |= E1000_ADVTXD_TUCMD_IPV4; 4056 type_tucmd |= E1000_ADVTXD_TUCMD_IPV4;
@@ -4053,7 +4064,7 @@ static inline bool igb_tx_csum(struct igb_ring *tx_ring, struct sk_buff *skb,
4053 if (unlikely(net_ratelimit())) { 4064 if (unlikely(net_ratelimit())) {
4054 dev_warn(tx_ring->dev, 4065 dev_warn(tx_ring->dev,
4055 "partial checksum but proto=%x!\n", 4066 "partial checksum but proto=%x!\n",
4056 protocol); 4067 first->protocol);
4057 } 4068 }
4058 break; 4069 break;
4059 } 4070 }
@@ -4081,14 +4092,15 @@ static inline bool igb_tx_csum(struct igb_ring *tx_ring, struct sk_buff *skb,
4081 } 4092 }
4082 break; 4093 break;
4083 } 4094 }
4095
4096 /* update TX checksum flag */
4097 first->tx_flags |= IGB_TX_FLAGS_CSUM;
4084 } 4098 }
4085 4099
4086 vlan_macip_lens |= skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT; 4100 vlan_macip_lens |= skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT;
4087 vlan_macip_lens |= tx_flags & IGB_TX_FLAGS_VLAN_MASK; 4101 vlan_macip_lens |= first->tx_flags & IGB_TX_FLAGS_VLAN_MASK;
4088 4102
4089 igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx); 4103 igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx);
4090
4091 return (skb->ip_summed == CHECKSUM_PARTIAL);
4092} 4104}
4093 4105
4094static __le32 igb_tx_cmd_type(u32 tx_flags) 4106static __le32 igb_tx_cmd_type(u32 tx_flags)
@@ -4113,8 +4125,9 @@ static __le32 igb_tx_cmd_type(u32 tx_flags)
4113 return cmd_type; 4125 return cmd_type;
4114} 4126}
4115 4127
4116static __le32 igb_tx_olinfo_status(u32 tx_flags, unsigned int paylen, 4128static void igb_tx_olinfo_status(struct igb_ring *tx_ring,
4117 struct igb_ring *tx_ring) 4129 union e1000_adv_tx_desc *tx_desc,
4130 u32 tx_flags, unsigned int paylen)
4118{ 4131{
4119 u32 olinfo_status = paylen << E1000_ADVTXD_PAYLEN_SHIFT; 4132 u32 olinfo_status = paylen << E1000_ADVTXD_PAYLEN_SHIFT;
4120 4133
@@ -4132,7 +4145,7 @@ static __le32 igb_tx_olinfo_status(u32 tx_flags, unsigned int paylen,
4132 olinfo_status |= E1000_TXD_POPTS_IXSM << 8; 4145 olinfo_status |= E1000_TXD_POPTS_IXSM << 8;
4133 } 4146 }
4134 4147
4135 return cpu_to_le32(olinfo_status); 4148 tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
4136} 4149}
4137 4150
4138/* 4151/*
@@ -4140,12 +4153,13 @@ static __le32 igb_tx_olinfo_status(u32 tx_flags, unsigned int paylen,
4140 * maintain a power of two alignment we have to limit ourselves to 32K. 4153 * maintain a power of two alignment we have to limit ourselves to 32K.
4141 */ 4154 */
4142#define IGB_MAX_TXD_PWR 15 4155#define IGB_MAX_TXD_PWR 15
4143#define IGB_MAX_DATA_PER_TXD (1 << IGB_MAX_TXD_PWR) 4156#define IGB_MAX_DATA_PER_TXD (1<<IGB_MAX_TXD_PWR)
4144 4157
4145static void igb_tx_map(struct igb_ring *tx_ring, struct sk_buff *skb, 4158static void igb_tx_map(struct igb_ring *tx_ring,
4146 struct igb_tx_buffer *first, u32 tx_flags, 4159 struct igb_tx_buffer *first,
4147 const u8 hdr_len) 4160 const u8 hdr_len)
4148{ 4161{
4162 struct sk_buff *skb = first->skb;
4149 struct igb_tx_buffer *tx_buffer_info; 4163 struct igb_tx_buffer *tx_buffer_info;
4150 union e1000_adv_tx_desc *tx_desc; 4164 union e1000_adv_tx_desc *tx_desc;
4151 dma_addr_t dma; 4165 dma_addr_t dma;
@@ -4154,24 +4168,12 @@ static void igb_tx_map(struct igb_ring *tx_ring, struct sk_buff *skb,
4154 unsigned int size = skb_headlen(skb); 4168 unsigned int size = skb_headlen(skb);
4155 unsigned int paylen = skb->len - hdr_len; 4169 unsigned int paylen = skb->len - hdr_len;
4156 __le32 cmd_type; 4170 __le32 cmd_type;
4171 u32 tx_flags = first->tx_flags;
4157 u16 i = tx_ring->next_to_use; 4172 u16 i = tx_ring->next_to_use;
4158 u16 gso_segs;
4159
4160 if (tx_flags & IGB_TX_FLAGS_TSO)
4161 gso_segs = skb_shinfo(skb)->gso_segs;
4162 else
4163 gso_segs = 1;
4164
4165 /* multiply data chunks by size of headers */
4166 first->bytecount = paylen + (gso_segs * hdr_len);
4167 first->gso_segs = gso_segs;
4168 first->skb = skb;
4169 4173
4170 tx_desc = IGB_TX_DESC(tx_ring, i); 4174 tx_desc = IGB_TX_DESC(tx_ring, i);
4171 4175
4172 tx_desc->read.olinfo_status = 4176 igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, paylen);
4173 igb_tx_olinfo_status(tx_flags, paylen, tx_ring);
4174
4175 cmd_type = igb_tx_cmd_type(tx_flags); 4177 cmd_type = igb_tx_cmd_type(tx_flags);
4176 4178
4177 dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE); 4179 dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE);
@@ -4181,7 +4183,6 @@ static void igb_tx_map(struct igb_ring *tx_ring, struct sk_buff *skb,
4181 /* record length, and DMA address */ 4183 /* record length, and DMA address */
4182 first->length = size; 4184 first->length = size;
4183 first->dma = dma; 4185 first->dma = dma;
4184 first->tx_flags = tx_flags;
4185 tx_desc->read.buffer_addr = cpu_to_le64(dma); 4186 tx_desc->read.buffer_addr = cpu_to_le64(dma);
4186 4187
4187 for (;;) { 4188 for (;;) {
@@ -4336,6 +4337,12 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
4336 return NETDEV_TX_BUSY; 4337 return NETDEV_TX_BUSY;
4337 } 4338 }
4338 4339
4340 /* record the location of the first descriptor for this packet */
4341 first = &tx_ring->tx_buffer_info[tx_ring->next_to_use];
4342 first->skb = skb;
4343 first->bytecount = skb->len;
4344 first->gso_segs = 1;
4345
4339 if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { 4346 if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
4340 skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 4347 skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
4341 tx_flags |= IGB_TX_FLAGS_TSTAMP; 4348 tx_flags |= IGB_TX_FLAGS_TSTAMP;
@@ -4346,22 +4353,17 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
4346 tx_flags |= (vlan_tx_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT); 4353 tx_flags |= (vlan_tx_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT);
4347 } 4354 }
4348 4355
4349 /* record the location of the first descriptor for this packet */ 4356 /* record initial flags and protocol */
4350 first = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; 4357 first->tx_flags = tx_flags;
4358 first->protocol = protocol;
4351 4359
4352 tso = igb_tso(tx_ring, skb, tx_flags, protocol, &hdr_len); 4360 tso = igb_tso(tx_ring, first, &hdr_len);
4353 if (tso < 0) { 4361 if (tso < 0)
4354 goto out_drop; 4362 goto out_drop;
4355 } else if (tso) { 4363 else if (!tso)
4356 tx_flags |= IGB_TX_FLAGS_TSO | IGB_TX_FLAGS_CSUM; 4364 igb_tx_csum(tx_ring, first);
4357 if (protocol == htons(ETH_P_IP))
4358 tx_flags |= IGB_TX_FLAGS_IPV4;
4359 } else if (igb_tx_csum(tx_ring, skb, tx_flags, protocol) &&
4360 (skb->ip_summed == CHECKSUM_PARTIAL)) {
4361 tx_flags |= IGB_TX_FLAGS_CSUM;
4362 }
4363 4365
4364 igb_tx_map(tx_ring, skb, first, tx_flags, hdr_len); 4366 igb_tx_map(tx_ring, first, hdr_len);
4365 4367
4366 /* Make sure there is space in the ring for the next send. */ 4368 /* Make sure there is space in the ring for the next send. */
4367 igb_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 4); 4369 igb_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 4);
@@ -4369,7 +4371,8 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
4369 return NETDEV_TX_OK; 4371 return NETDEV_TX_OK;
4370 4372
4371out_drop: 4373out_drop:
4372 dev_kfree_skb_any(skb); 4374 igb_unmap_and_free_tx_resource(tx_ring, first);
4375
4373 return NETDEV_TX_OK; 4376 return NETDEV_TX_OK;
4374} 4377}
4375 4378