summaryrefslogtreecommitdiff
path: root/sys/dev/pci/ixgbe_82599.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/ixgbe_82599.c')
-rw-r--r--sys/dev/pci/ixgbe_82599.c690
1 files changed, 1 insertions, 689 deletions
diff --git a/sys/dev/pci/ixgbe_82599.c b/sys/dev/pci/ixgbe_82599.c
index 78b506d2633..5a777331d3e 100644
--- a/sys/dev/pci/ixgbe_82599.c
+++ b/sys/dev/pci/ixgbe_82599.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ixgbe_82599.c,v 1.6 2012/08/11 06:53:31 mikeb Exp $ */
+/* $OpenBSD: ixgbe_82599.c,v 1.7 2012/11/06 17:29:39 mikeb Exp $ */
/******************************************************************************
@@ -74,14 +74,6 @@ int32_t ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, uint32_t regval);
int32_t ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
int ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
-uint32_t ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
- union ixgbe_atr_hash_dword common);
-int32_t ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_hash_dword input,
- union ixgbe_atr_hash_dword common,
- uint8_t queue);
-uint32_t ixgbe_get_fdirtcpm_82599(struct ixgbe_atr_input_masks *input_masks);
-
void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
{
struct ixgbe_mac_info *mac = &hw->mac;
@@ -1120,686 +1112,6 @@ reset_hw_out:
}
/**
- * ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables.
- * @hw: pointer to hardware structure
- **/
-int32_t ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
-{
- int i;
- uint32_t fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
- fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE;
-
- DEBUGFUNC("ixgbe_reinit_fdir_tables_82599");
-
- /*
- * Before starting reinitialization process,
- * FDIRCMD.CMD must be zero.
- */
- for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) {
- if (!(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
- IXGBE_FDIRCMD_CMD_MASK))
- break;
- usec_delay(10);
- }
- if (i >= IXGBE_FDIRCMD_CMD_POLL) {
- DEBUGOUT("Flow Director previous command isn't complete, "
- "aborting table re-initialization. \n");
- return IXGBE_ERR_FDIR_REINIT_FAILED;
- }
-
- IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0);
- IXGBE_WRITE_FLUSH(hw);
- /*
- * 82599 adapters flow director init flow cannot be restarted,
- * Workaround 82599 silicon errata by performing the following steps
- * before re-writing the FDIRCTRL control register with the same value.
- * - write 1 to bit 8 of FDIRCMD register &
- * - write 0 to bit 8 of FDIRCMD register
- */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
- (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) |
- IXGBE_FDIRCMD_CLEARHT));
- IXGBE_WRITE_FLUSH(hw);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
- (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
- ~IXGBE_FDIRCMD_CLEARHT));
- IXGBE_WRITE_FLUSH(hw);
- /*
- * Clear FDIR Hash register to clear any leftover hashes
- * waiting to be programmed.
- */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, 0x00);
- IXGBE_WRITE_FLUSH(hw);
-
- IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
- IXGBE_WRITE_FLUSH(hw);
-
- /* Poll init-done after we write FDIRCTRL register */
- for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
- if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
- IXGBE_FDIRCTRL_INIT_DONE)
- break;
- usec_delay(10);
- }
- if (i >= IXGBE_FDIR_INIT_DONE_POLL) {
- DEBUGOUT("Flow Director Signature poll time exceeded!\n");
- return IXGBE_ERR_FDIR_REINIT_FAILED;
- }
-
- /* Clear FDIR statistics registers (read to clear) */
- IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT);
- IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT);
- IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
- IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
- IXGBE_READ_REG(hw, IXGBE_FDIRLEN);
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
- * @hw: pointer to hardware structure
- * @pballoc: which mode to allocate filters with
- **/
-int32_t ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, uint32_t pballoc)
-{
- uint32_t fdirctrl = 0;
- uint32_t pbsize;
- int i;
-
- DEBUGFUNC("ixgbe_init_fdir_signature_82599");
-
- /*
- * Before enabling Flow Director, the Rx Packet Buffer size
- * must be reduced. The new value is the current size minus
- * flow director memory usage size.
- */
- pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
- (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
-
- /*
- * The defaults in the HW for RX PB 1-7 are not zero and so should be
- * intialized to zero for non DCB mode otherwise actual total RX PB
- * would be bigger than programmed and filter space would run into
- * the PB 0 region.
- */
- for (i = 1; i < 8; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
-
- /* Send interrupt when 64 filters are left */
- fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
-
- /* Set the maximum length per hash bucket to 0xA filters */
- fdirctrl |= 0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT;
-
- switch (pballoc) {
- case IXGBE_FDIR_PBALLOC_64K:
- /* 8k - 1 signature filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
- break;
- case IXGBE_FDIR_PBALLOC_128K:
- /* 16k - 1 signature filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
- break;
- case IXGBE_FDIR_PBALLOC_256K:
- /* 32k - 1 signature filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
- break;
- default:
- /* bad value */
- return IXGBE_ERR_CONFIG;
- };
-
- /* Move the flexible bytes to use the ethertype - shift 6 words */
- fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
-
-
- /* Prime the keys for hashing */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
-
- /*
- * Poll init-done after we write the register. Estimated times:
- * 10G: PBALLOC = 11b, timing is 60us
- * 1G: PBALLOC = 11b, timing is 600us
- * 100M: PBALLOC = 11b, timing is 6ms
- *
- * Multiple these timings by 4 if under full Rx load
- *
- * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
- * 1 msec per poll time. If we're at line rate and drop to 100M, then
- * this might not finish in our poll time, but we can live with that
- * for now.
- */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
- IXGBE_WRITE_FLUSH(hw);
- for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
- if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
- IXGBE_FDIRCTRL_INIT_DONE)
- break;
- msec_delay(1);
- }
- if (i >= IXGBE_FDIR_INIT_DONE_POLL)
- DEBUGOUT("Flow Director Signature poll time exceeded!\n");
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
- * @hw: pointer to hardware structure
- * @pballoc: which mode to allocate filters with
- **/
-int32_t ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, uint32_t pballoc)
-{
- uint32_t fdirctrl = 0;
- uint32_t pbsize;
- int i;
-
- DEBUGFUNC("ixgbe_init_fdir_perfect_82599");
-
- /*
- * Before enabling Flow Director, the Rx Packet Buffer size
- * must be reduced. The new value is the current size minus
- * flow director memory usage size.
- */
- pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
- (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
-
- /*
- * The defaults in the HW for RX PB 1-7 are not zero and so should be
- * intialized to zero for non DCB mode otherwise actual total RX PB
- * would be bigger than programmed and filter space would run into
- * the PB 0 region.
- */
- for (i = 1; i < 8; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
-
- /* Send interrupt when 64 filters are left */
- fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
-
- /* Initialize the drop queue to Rx queue 127 */
- fdirctrl |= (127 << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
-
- switch (pballoc) {
- case IXGBE_FDIR_PBALLOC_64K:
- /* 2k - 1 perfect filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
- break;
- case IXGBE_FDIR_PBALLOC_128K:
- /* 4k - 1 perfect filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
- break;
- case IXGBE_FDIR_PBALLOC_256K:
- /* 8k - 1 perfect filters */
- fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
- break;
- default:
- /* bad value */
- return IXGBE_ERR_CONFIG;
- };
-
- /* Turn perfect match filtering on */
- fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH;
- fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS;
-
- /* Move the flexible bytes to use the ethertype - shift 6 words */
- fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
-
- /* Prime the keys for hashing */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
-
- /*
- * Poll init-done after we write the register. Estimated times:
- * 10G: PBALLOC = 11b, timing is 60us
- * 1G: PBALLOC = 11b, timing is 600us
- * 100M: PBALLOC = 11b, timing is 6ms
- *
- * Multiple these timings by 4 if under full Rx load
- *
- * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
- * 1 msec per poll time. If we're at line rate and drop to 100M, then
- * this might not finish in our poll time, but we can live with that
- * for now.
- */
-
- /* Set the maximum length per hash bucket to 0xA filters */
- fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT);
-
- IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
- IXGBE_WRITE_FLUSH(hw);
- for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
- if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
- IXGBE_FDIRCTRL_INIT_DONE)
- break;
- msec_delay(1);
- }
- if (i >= IXGBE_FDIR_INIT_DONE_POLL)
- DEBUGOUT("Flow Director Perfect poll time exceeded!\n");
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_atr_compute_hash_82599 - Compute the hashes for SW ATR
- * @stream: input bitstream to compute the hash on
- * @key: 32-bit hash key
- **/
-uint32_t ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input,
- uint32_t key)
-{
- /*
- * The algorithm is as follows:
- * Hash[15:0] = Sum { S[n] x K[n+16] }, n = 0...350
- * where Sum {A[n]}, n = 0...n is bitwise XOR of A[0], A[1]...A[n]
- * and A[n] x B[n] is bitwise AND between same length strings
- *
- * K[n] is 16 bits, defined as:
- * for n modulo 32 >= 15, K[n] = K[n % 32 : (n % 32) - 15]
- * for n modulo 32 < 15, K[n] =
- * K[(n % 32:0) | (31:31 - (14 - (n % 32)))]
- *
- * S[n] is 16 bits, defined as:
- * for n >= 15, S[n] = S[n:n - 15]
- * for n < 15, S[n] = S[(n:0) | (350:350 - (14 - n))]
- *
- * To simplify for programming, the algorithm is implemented
- * in software this way:
- *
- * key[31:0], hi_hash_dword[31:0], lo_hash_dword[31:0], hash[15:0]
- *
- * for (i = 0; i < 352; i+=32)
- * hi_hash_dword[31:0] ^= Stream[(i+31):i];
- *
- * lo_hash_dword[15:0] ^= Stream[15:0];
- * lo_hash_dword[15:0] ^= hi_hash_dword[31:16];
- * lo_hash_dword[31:16] ^= hi_hash_dword[15:0];
- *
- * hi_hash_dword[31:0] ^= Stream[351:320];
- *
- * if(key[0])
- * hash[15:0] ^= Stream[15:0];
- *
- * for (i = 0; i < 16; i++) {
- * if (key[i])
- * hash[15:0] ^= lo_hash_dword[(i+15):i];
- * if (key[i + 16])
- * hash[15:0] ^= hi_hash_dword[(i+15):i];
- * }
- *
- */
- __be32 common_hash_dword = 0;
- uint32_t hi_hash_dword, lo_hash_dword, flow_vm_vlan;
- uint32_t hash_result = 0;
- uint8_t i;
-
- /* record the flow_vm_vlan bits as they are a key part to the hash */
- flow_vm_vlan = ntohl(atr_input->dword_stream[0]);
-
- /* generate common hash dword */
- for (i = 10; i; i -= 2)
- common_hash_dword ^= atr_input->dword_stream[i] ^
- atr_input->dword_stream[i - 1];
-
- hi_hash_dword = ntohl(common_hash_dword);
-
- /* low dword is word swapped version of common */
- lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
-
- /* apply flow ID/VM pool/VLAN ID bits to hash words */
- hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
-
- /* Process bits 0 and 16 */
- if (key & 0x0001) hash_result ^= lo_hash_dword;
- if (key & 0x00010000) hash_result ^= hi_hash_dword;
-
- /*
- * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
- * delay this because bit 0 of the stream should not be processed
- * so we do not add the vlan until after bit 0 was processed
- */
- lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
-
-
- /* process the remaining 30 bits in the key 2 bits at a time */
- for (i = 15; i; i-- ) {
- if (key & (0x0001 << i)) hash_result ^= lo_hash_dword >> i;
- if (key & (0x00010000 << i)) hash_result ^= hi_hash_dword >> i;
- }
-
- return hash_result & IXGBE_ATR_HASH_MASK;
-}
-
-/*
- * These defines allow us to quickly generate all of the necessary instructions
- * in the function below by simply calling out IXGBE_COMPUTE_SIG_HASH_ITERATION
- * for values 0 through 15
- */
-#define IXGBE_ATR_COMMON_HASH_KEY \
- (IXGBE_ATR_BUCKET_HASH_KEY & IXGBE_ATR_SIGNATURE_HASH_KEY)
-#define IXGBE_COMPUTE_SIG_HASH_ITERATION(_n) \
-do { \
- uint32_t n = (_n); \
- if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << n)) \
- common_hash ^= lo_hash_dword >> n; \
- else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \
- bucket_hash ^= lo_hash_dword >> n; \
- else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << n)) \
- sig_hash ^= lo_hash_dword << (16 - n); \
- if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << (n + 16))) \
- common_hash ^= hi_hash_dword >> n; \
- else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
- bucket_hash ^= hi_hash_dword >> n; \
- else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << (n + 16))) \
- sig_hash ^= hi_hash_dword << (16 - n); \
-} while (0);
-
-/**
- * ixgbe_atr_compute_sig_hash_82599 - Compute the signature hash
- * @stream: input bitstream to compute the hash on
- *
- * This function is almost identical to the function above but contains
- * several optomizations such as unwinding all of the loops, letting the
- * compiler work out all of the conditional ifs since the keys are static
- * defines, and computing two keys at once since the hashed dword stream
- * will be the same for both keys.
- **/
-uint32_t ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
- union ixgbe_atr_hash_dword common)
-{
- uint32_t hi_hash_dword, lo_hash_dword, flow_vm_vlan;
- uint32_t sig_hash = 0, bucket_hash = 0, common_hash = 0;
-
- /* record the flow_vm_vlan bits as they are a key part to the hash */
- flow_vm_vlan = ntohl(input.dword);
-
- /* generate common hash dword */
- hi_hash_dword = ntohl(common.dword);
-
- /* low dword is word swapped version of common */
- lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
-
- /* apply flow ID/VM pool/VLAN ID bits to hash words */
- hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
-
- /* Process bits 0 and 16 */
- IXGBE_COMPUTE_SIG_HASH_ITERATION(0);
-
- /*
- * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
- * delay this because bit 0 of the stream should not be processed
- * so we do not add the vlan until after bit 0 was processed
- */
- lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
-
- /* Process remaining 30 bit of the key */
- IXGBE_COMPUTE_SIG_HASH_ITERATION(1);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(2);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(3);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(4);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(5);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(6);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(7);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(8);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(9);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(10);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(11);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(12);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(13);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(14);
- IXGBE_COMPUTE_SIG_HASH_ITERATION(15);
-
- /* combine common_hash result with signature and bucket hashes */
- bucket_hash ^= common_hash;
- bucket_hash &= IXGBE_ATR_HASH_MASK;
-
- sig_hash ^= common_hash << 16;
- sig_hash &= IXGBE_ATR_HASH_MASK << 16;
-
- /* return completed signature hash */
- return sig_hash ^ bucket_hash;
-}
-
-/**
- * ixgbe_atr_add_signature_filter_82599 - Adds a signature hash filter
- * @hw: pointer to hardware structure
- * @stream: input bitstream
- * @queue: queue index to direct traffic to
- **/
-int32_t ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_hash_dword input,
- union ixgbe_atr_hash_dword common,
- uint8_t queue)
-{
- uint64_t fdirhashcmd;
- uint64_t fdircmd;
-
- DEBUGFUNC("ixgbe_fdir_add_signature_filter_82599");
-
- /*
- * Get the flow_type in order to program FDIRCMD properly
- * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6
- */
- switch (input.formatted.flow_type) {
- case IXGBE_ATR_FLOW_TYPE_TCPV4:
- case IXGBE_ATR_FLOW_TYPE_UDPV4:
- case IXGBE_ATR_FLOW_TYPE_SCTPV4:
- case IXGBE_ATR_FLOW_TYPE_TCPV6:
- case IXGBE_ATR_FLOW_TYPE_UDPV6:
- case IXGBE_ATR_FLOW_TYPE_SCTPV6:
- break;
- default:
- DEBUGOUT(" Error on flow type input\n");
- return IXGBE_ERR_CONFIG;
- }
-
- /* configure FDIRCMD register */
- fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
- IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
- fdircmd |= input.formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
- fdircmd |= (uint32_t)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
-
- /*
- * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits
- * is for FDIRCMD. Then do a 64-bit register write from FDIRHASH.
- */
- fdirhashcmd = (uint64_t)fdircmd << 32;
- fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common);
- IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
-
- DEBUGOUT2("Tx Queue=%x hash=%x\n", queue, (uint32_t)fdirhashcmd);
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_get_fdirtcpm_82599 - generate a tcp port from atr_input_masks
- * @input_mask: mask to be bit swapped
- *
- * The source and destination port masks for flow director are bit swapped
- * in that bit 15 effects bit 0, 14 effects 1, 13, 2 etc. In order to
- * generate a correctly swapped value we need to bit swap the mask and that
- * is what is accomplished by this function.
- **/
-uint32_t ixgbe_get_fdirtcpm_82599(struct ixgbe_atr_input_masks *input_masks)
-{
- uint32_t mask = ntohs(input_masks->dst_port_mask);
- mask <<= IXGBE_FDIRTCPM_DPORTM_SHIFT;
- mask |= ntohs(input_masks->src_port_mask);
- mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1);
- mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2);
- mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4);
- return ((mask & 0x00FF00FF) << 8) | ((mask & 0xFF00FF00) >> 8);
-}
-
-/*
- * These two macros are meant to address the fact that we have registers
- * that are either all or in part big-endian. As a result on big-endian
- * systems we will end up byte swapping the value to little-endian before
- * it is byte swapped again and written to the hardware in the original
- * big-endian format.
- */
-#define IXGBE_STORE_AS_BE32(_value) \
- (((uint32_t)(_value) >> 24) | (((uint32_t)(_value) & 0x00FF0000) >> 8) | \
- (((uint32_t)(_value) & 0x0000FF00) << 8) | ((uint32_t)(_value) << 24))
-
-#define IXGBE_WRITE_REG_BE32(a, reg, value) \
- IXGBE_WRITE_REG((a), (reg), IXGBE_STORE_AS_BE32(ntohl(value)))
-
-#define IXGBE_STORE_AS_BE16(_value) \
- (((uint16_t)(_value) >> 8) | ((uint16_t)(_value) << 8))
-
-
-/**
- * ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter
- * @hw: pointer to hardware structure
- * @input_masks: masks for the input bitstream
- * @soft_id: software index for the filters
- * @queue: queue index to direct traffic to
- *
- * Note that the caller to this function must lock before calling, since the
- * hardware writes must be protected from one another.
- **/
-int32_t ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_input *input,
- struct ixgbe_atr_input_masks *input_masks,
- uint16_t soft_id, uint8_t queue)
-{
- uint32_t fdirhash;
- uint32_t fdircmd;
- uint32_t fdirport, fdirtcpm;
- uint32_t fdirvlan;
- /* start with VLAN, flex bytes, VM pool, and IPv6 destination masked */
- uint32_t fdirm = IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP | IXGBE_FDIRM_FLEX |
- IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6;
-
- DEBUGFUNC("ixgbe_fdir_add_perfect_filter_82599");
-
- /*
- * Check flow_type formatting, and bail out before we touch the hardware
- * if there's a configuration issue
- */
- switch (input->formatted.flow_type) {
- case IXGBE_ATR_FLOW_TYPE_IPV4:
- /* use the L4 protocol mask for raw IPv4/IPv6 traffic */
- fdirm |= IXGBE_FDIRM_L4P;
- case IXGBE_ATR_FLOW_TYPE_SCTPV4:
- if (input_masks->dst_port_mask || input_masks->src_port_mask) {
- DEBUGOUT(" Error on src/dst port mask\n");
- return IXGBE_ERR_CONFIG;
- }
- case IXGBE_ATR_FLOW_TYPE_TCPV4:
- case IXGBE_ATR_FLOW_TYPE_UDPV4:
- break;
- default:
- DEBUGOUT(" Error on flow type input\n");
- return IXGBE_ERR_CONFIG;
- }
-
- /*
- * Program the relevant mask registers. If src/dst_port or src/dst_addr
- * are zero, then assume a full mask for that field. Also assume that
- * a VLAN of 0 is unspecified, so mask that out as well. L4type
- * cannot be masked out in this implementation.
- *
- * This also assumes IPv4 only. IPv6 masking isn't supported at this
- * point in time.
- */
-
- /* Program FDIRM */
- switch (ntohs(input_masks->vlan_id_mask) & 0xEFFF) {
- case 0xEFFF:
- /* Unmask VLAN ID - bit 0 and fall through to unmask prio */
- fdirm &= ~IXGBE_FDIRM_VLANID;
- case 0xE000:
- /* Unmask VLAN prio - bit 1 */
- fdirm &= ~IXGBE_FDIRM_VLANP;
- break;
- case 0x0FFF:
- /* Unmask VLAN ID - bit 0 */
- fdirm &= ~IXGBE_FDIRM_VLANID;
- break;
- case 0x0000:
- /* do nothing, vlans already masked */
- break;
- default:
- DEBUGOUT(" Error on VLAN mask\n");
- return IXGBE_ERR_CONFIG;
- }
-
- if (input_masks->flex_mask & 0xFFFF) {
- if ((input_masks->flex_mask & 0xFFFF) != 0xFFFF) {
- DEBUGOUT(" Error on flexible byte mask\n");
- return IXGBE_ERR_CONFIG;
- }
- /* Unmask Flex Bytes - bit 4 */
- fdirm &= ~IXGBE_FDIRM_FLEX;
- }
-
- /* Now mask VM pool and destination IPv6 - bits 5 and 2 */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
-
- /* store the TCP/UDP port masks, bit reversed from port layout */
- fdirtcpm = ixgbe_get_fdirtcpm_82599(input_masks);
-
- /* write both the same so that UDP and TCP use the same mask */
- IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm);
-
- /* store source and destination IP masks (big-enian) */
- IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
- ~input_masks->src_ip_mask[0]);
- IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M,
- ~input_masks->dst_ip_mask[0]);
-
- /* Apply masks to input data */
- input->formatted.vlan_id &= input_masks->vlan_id_mask;
- input->formatted.flex_bytes &= input_masks->flex_mask;
- input->formatted.src_port &= input_masks->src_port_mask;
- input->formatted.dst_port &= input_masks->dst_port_mask;
- input->formatted.src_ip[0] &= input_masks->src_ip_mask[0];
- input->formatted.dst_ip[0] &= input_masks->dst_ip_mask[0];
-
- /* record vlan (little-endian) and flex_bytes(big-endian) */
- fdirvlan =
- IXGBE_STORE_AS_BE16(ntohs(input->formatted.flex_bytes));
- fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
- fdirvlan |= ntohs(input->formatted.vlan_id);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
-
- /* record source and destination port (little-endian)*/
- fdirport = ntohs(input->formatted.dst_port);
- fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT;
- fdirport |= ntohs(input->formatted.src_port);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
-
- /* record the first 32 bits of the destination address (big-endian) */
- IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
-
- /* record the source address (big-endian) */
- IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
-
- /* configure FDIRCMD register */
- fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
- IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
- fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
- fdircmd |= (uint32_t)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
-
- /* we only want the bucket hash so drop the upper 16 bits */
- fdirhash = ixgbe_atr_compute_hash_82599(input,
- IXGBE_ATR_BUCKET_HASH_KEY);
- fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
-
- IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
- IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
-
- return IXGBE_SUCCESS;
-}
-
-/**
* ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register
* @hw: pointer to hardware structure
* @reg: analog register to read