igb: Update igb Tx flags to improve code efficiency

This change is meant to improve the efficiency of the Tx flags in igb by
aligning them with the values that will later be written into either the
cmd_type or olinfo.  By doing this we are able to reduce most of these
functions to either just a simple shift followed by an or in the case of
cmd_type, or an and followed by an or in the case of olinfo.

In order to avoid type conversion errors I also adjusted the locations
where we were switching between CPU and little endian.

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>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Alexander Duyck 2012-11-13 04:03:23 +00:00 committed by David S. Miller
parent ed6aa10580
commit 1d9daf45b4
2 changed files with 46 additions and 34 deletions

View File

@ -150,11 +150,18 @@ struct vf_data_storage {
#define IGB_MNG_VLAN_NONE -1
#define IGB_TX_FLAGS_CSUM 0x00000001
#define IGB_TX_FLAGS_VLAN 0x00000002
#define IGB_TX_FLAGS_TSO 0x00000004
#define IGB_TX_FLAGS_IPV4 0x00000008
#define IGB_TX_FLAGS_TSTAMP 0x00000010
enum igb_tx_flags {
/* cmd_type flags */
IGB_TX_FLAGS_VLAN = 0x01,
IGB_TX_FLAGS_TSO = 0x02,
IGB_TX_FLAGS_TSTAMP = 0x04,
/* olinfo flags */
IGB_TX_FLAGS_IPV4 = 0x10,
IGB_TX_FLAGS_CSUM = 0x20,
};
/* VLAN info */
#define IGB_TX_FLAGS_VLAN_MASK 0xffff0000
#define IGB_TX_FLAGS_VLAN_SHIFT 16

View File

@ -4121,24 +4121,32 @@ static void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first)
igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx);
}
static __le32 igb_tx_cmd_type(u32 tx_flags)
#define IGB_SET_FLAG(_input, _flag, _result) \
((_flag <= _result) ? \
((u32)(_input & _flag) * (_result / _flag)) : \
((u32)(_input & _flag) / (_flag / _result)))
static u32 igb_tx_cmd_type(struct sk_buff *skb, u32 tx_flags)
{
/* set type for advanced descriptor with frame checksum insertion */
__le32 cmd_type = cpu_to_le32(E1000_ADVTXD_DTYP_DATA |
E1000_ADVTXD_DCMD_IFCS |
E1000_ADVTXD_DCMD_DEXT);
u32 cmd_type = E1000_ADVTXD_DTYP_DATA |
E1000_ADVTXD_DCMD_DEXT |
E1000_ADVTXD_DCMD_IFCS;
/* set HW vlan bit if vlan is present */
if (tx_flags & IGB_TX_FLAGS_VLAN)
cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_VLE);
/* set timestamp bit if present */
if (unlikely(tx_flags & IGB_TX_FLAGS_TSTAMP))
cmd_type |= cpu_to_le32(E1000_ADVTXD_MAC_TSTAMP);
cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_VLAN,
(E1000_ADVTXD_DCMD_VLE));
/* set segmentation bits for TSO */
if (tx_flags & IGB_TX_FLAGS_TSO)
cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_TSE);
cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSO,
(E1000_ADVTXD_DCMD_TSE));
/* set timestamp bit if present */
cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSTAMP,
(E1000_ADVTXD_MAC_TSTAMP));
/* insert frame checksum */
cmd_type ^= IGB_SET_FLAG(skb->no_fcs, 1, E1000_ADVTXD_DCMD_IFCS);
return cmd_type;
}
@ -4149,19 +4157,19 @@ static void igb_tx_olinfo_status(struct igb_ring *tx_ring,
{
u32 olinfo_status = paylen << E1000_ADVTXD_PAYLEN_SHIFT;
/* 82575 requires a unique index per ring if any offload is enabled */
if ((tx_flags & (IGB_TX_FLAGS_CSUM | IGB_TX_FLAGS_VLAN)) &&
test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags))
/* 82575 requires a unique index per ring */
if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags))
olinfo_status |= tx_ring->reg_idx << 4;
/* insert L4 checksum */
if (tx_flags & IGB_TX_FLAGS_CSUM) {
olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
olinfo_status |= IGB_SET_FLAG(tx_flags,
IGB_TX_FLAGS_CSUM,
(E1000_TXD_POPTS_TXSM << 8));
/* insert IPv4 checksum */
if (tx_flags & IGB_TX_FLAGS_IPV4)
olinfo_status |= E1000_TXD_POPTS_IXSM << 8;
}
/* insert IPv4 checksum */
olinfo_status |= IGB_SET_FLAG(tx_flags,
IGB_TX_FLAGS_IPV4,
(E1000_TXD_POPTS_IXSM << 8));
tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
}
@ -4185,14 +4193,13 @@ static void igb_tx_map(struct igb_ring *tx_ring,
unsigned int data_len = skb->data_len;
unsigned int size = skb_headlen(skb);
unsigned int paylen = skb->len - hdr_len;
__le32 cmd_type;
u32 tx_flags = first->tx_flags;
u32 cmd_type = igb_tx_cmd_type(skb, tx_flags);
u16 i = tx_ring->next_to_use;
tx_desc = IGB_TX_DESC(tx_ring, i);
igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, paylen);
cmd_type = igb_tx_cmd_type(tx_flags);
dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE);
if (dma_mapping_error(tx_ring->dev, dma))
@ -4206,7 +4213,7 @@ static void igb_tx_map(struct igb_ring *tx_ring,
for (;;) {
while (unlikely(size > IGB_MAX_DATA_PER_TXD)) {
tx_desc->read.cmd_type_len =
cmd_type | cpu_to_le32(IGB_MAX_DATA_PER_TXD);
cpu_to_le32(cmd_type ^ IGB_MAX_DATA_PER_TXD);
i++;
tx_desc++;
@ -4225,7 +4232,7 @@ static void igb_tx_map(struct igb_ring *tx_ring,
if (likely(!data_len))
break;
tx_desc->read.cmd_type_len = cmd_type | cpu_to_le32(size);
tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type ^ size);
i++;
tx_desc++;
@ -4255,10 +4262,8 @@ static void igb_tx_map(struct igb_ring *tx_ring,
netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
/* write last descriptor with RS and EOP bits */
cmd_type |= cpu_to_le32(size) | cpu_to_le32(IGB_TXD_DCMD);
if (unlikely(skb->no_fcs))
cmd_type &= ~(cpu_to_le32(E1000_ADVTXD_DCMD_IFCS));
tx_desc->read.cmd_type_len = cmd_type;
cmd_type |= size | IGB_TXD_DCMD;
tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type);
/* set the timestamp */
first->time_stamp = jiffies;