sfc: Generalise packet hash lookup to support EF10 RX prefix
authorJon Cooper <jcooper@solarflare.com>
Thu, 18 Oct 2012 14:49:54 +0000 (15:49 +0100)
committerBen Hutchings <bhutchings@solarflare.com>
Tue, 27 Aug 2013 21:28:24 +0000 (22:28 +0100)
EF10 uses an entirely different RX prefix format from Falcon-arch.
Extend struct efx_nic_type to describe this.

[bwh: Also replace the magic numbers used for the Falcon-arch RX prefix]
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/falcon.c
drivers/net/ethernet/sfc/farch_regs.h
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/rx.c
drivers/net/ethernet/sfc/siena.c

index 3af28a81f7cd9e5092fe09601ec87ed8af26c2cf..db2f119d7fec202d8b6e6f9174ebd253e7b0eef8 100644 (file)
@@ -573,7 +573,7 @@ static void efx_start_datapath(struct efx_nic *efx)
         * support the current MTU, including padding for header
         * alignment and overruns.
         */
-       efx->rx_dma_len = (efx->type->rx_buffer_hash_size +
+       efx->rx_dma_len = (efx->rx_prefix_size +
                           EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
                           efx->type->rx_buffer_padding);
        rx_buf_len = (sizeof(struct efx_rx_page_state) +
@@ -2456,6 +2456,9 @@ static int efx_init_struct(struct efx_nic *efx,
        strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
 
        efx->net_dev = net_dev;
+       efx->rx_prefix_size = efx->type->rx_prefix_size;
+       efx->rx_packet_hash_offset =
+               efx->type->rx_hash_offset - efx->type->rx_prefix_size;
        spin_lock_init(&efx->stats_lock);
        mutex_init(&efx->mac_lock);
        efx->phy_op = &efx_dummy_phy_operations;
index 1140b832d5416aeb61c56a422b1fdb67f8abac9f..ec77611a52e453cc50d839a3331c6622578ef5c3 100644 (file)
@@ -2827,7 +2827,8 @@ const struct efx_nic_type falcon_b0_nic_type = {
        .evq_ptr_tbl_base = FR_BZ_EVQ_PTR_TBL,
        .evq_rptr_tbl_base = FR_BZ_EVQ_RPTR,
        .max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH),
-       .rx_buffer_hash_size = 0x10,
+       .rx_prefix_size = FS_BZ_RX_PREFIX_SIZE,
+       .rx_hash_offset = FS_BZ_RX_PREFIX_HASH_OFST,
        .rx_buffer_padding = 0,
        .can_rx_scatter = true,
        .max_interrupt_mode = EFX_INT_MODE_MSIX,
index 00ef17a59187d2e21fad12264ac422f12fe6962b..491b1039006b80c108547295f363b9557c611d81 100644 (file)
 #define FSF_AZ_DRV_GEN_EV_MAGIC_LBN 0
 #define FSF_AZ_DRV_GEN_EV_MAGIC_WIDTH 32
 
+/* RX packet prefix */
+#define FS_BZ_RX_PREFIX_HASH_OFST 12
+#define FS_BZ_RX_PREFIX_SIZE 16
+
 #endif /* EFX_FARCH_REGS_H */
index 21b1c2a2a1918e485379b7a61b6a91de64e76809..481e41219869ba60941e07c3e35c607f49bacfb2 100644 (file)
@@ -663,6 +663,9 @@ struct vfdi_status;
  * @rx_buffer_order: Order (log2) of number of pages for each RX buffer
  * @rx_buffer_truesize: Amortised allocation size of an RX buffer,
  *     for use in sk_buff::truesize
+ * @rx_prefix_size: Size of RX prefix before packet data
+ * @rx_packet_hash_offset: Offset of RX flow hash from start of packet data
+ *     (valid only if @rx_prefix_size != 0; always negative)
  * @rx_hash_key: Toeplitz hash key for RSS
  * @rx_indir_table: Indirection table for RSS
  * @rx_scatter: Scatter mode enabled for receives
@@ -793,6 +796,8 @@ struct efx_nic {
        unsigned int rx_page_buf_step;
        unsigned int rx_bufs_per_page;
        unsigned int rx_pages_per_batch;
+       unsigned int rx_prefix_size;
+       int rx_packet_hash_offset;
        u8 rx_hash_key[40];
        u32 rx_indir_table[128];
        bool rx_scatter;
@@ -1009,7 +1014,8 @@ struct efx_mtd_partition {
  * @evq_ptr_tbl_base: Event queue pointer table base address
  * @evq_rptr_tbl_base: Event queue read-pointer table base address
  * @max_dma_mask: Maximum possible DMA mask
- * @rx_buffer_hash_size: Size of hash at start of RX packet
+ * @rx_prefix_size: Size of RX prefix before packet data
+ * @rx_hash_offset: Offset of RX flow hash within prefix
  * @rx_buffer_padding: Size of padding at end of RX packet
  * @can_rx_scatter: NIC is able to scatter packet to multiple buffers
  * @max_interrupt_mode: Highest capability interrupt mode supported
@@ -1126,7 +1132,8 @@ struct efx_nic_type {
        unsigned int evq_ptr_tbl_base;
        unsigned int evq_rptr_tbl_base;
        u64 max_dma_mask;
-       unsigned int rx_buffer_hash_size;
+       unsigned int rx_prefix_size;
+       unsigned int rx_hash_offset;
        unsigned int rx_buffer_padding;
        bool can_rx_scatter;
        unsigned int max_interrupt_mode;
index 12990929e2745e3fa62da7c5c57e5bd8caba1121..7646bb3c926d490fdd1cc9db01bbd60134f7e327 100644 (file)
@@ -61,13 +61,12 @@ static inline u8 *efx_rx_buf_va(struct efx_rx_buffer *buf)
        return page_address(buf->page) + buf->page_offset;
 }
 
-static inline u32 efx_rx_buf_hash(const u8 *eh)
+static inline u32 efx_rx_buf_hash(struct efx_nic *efx, const u8 *eh)
 {
-       /* The ethernet header is always directly after any hash. */
-#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || NET_IP_ALIGN % 4 == 0
-       return __le32_to_cpup((const __le32 *)(eh - 4));
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+       return __le32_to_cpup((const __le32 *)(eh + efx->rx_packet_hash_offset));
 #else
-       const u8 *data = eh - 4;
+       const u8 *data = eh + efx->rx_packet_hash_offset;
        return (u32)data[0]       |
               (u32)data[1] << 8  |
               (u32)data[2] << 16 |
@@ -439,7 +438,7 @@ efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf,
        }
 
        if (efx->net_dev->features & NETIF_F_RXHASH)
-               skb->rxhash = efx_rx_buf_hash(eh);
+               skb->rxhash = efx_rx_buf_hash(efx, eh);
        skb->ip_summed = ((rx_buf->flags & EFX_RX_PKT_CSUMMED) ?
                          CHECKSUM_UNNECESSARY : CHECKSUM_NONE);
 
@@ -568,8 +567,8 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
         */
        prefetch(efx_rx_buf_va(rx_buf));
 
-       rx_buf->page_offset += efx->type->rx_buffer_hash_size;
-       rx_buf->len -= efx->type->rx_buffer_hash_size;
+       rx_buf->page_offset += efx->rx_prefix_size;
+       rx_buf->len -= efx->rx_prefix_size;
 
        if (n_frags > 1) {
                /* Release/sync DMA mapping for additional fragments.
index 3c0a5440026028b4efeb289d751ce61dba46c559..89180d47536788267e6e2631597d9fd1771b3f85 100644 (file)
@@ -965,7 +965,8 @@ const struct efx_nic_type siena_a0_nic_type = {
        .evq_ptr_tbl_base = FR_BZ_EVQ_PTR_TBL,
        .evq_rptr_tbl_base = FR_BZ_EVQ_RPTR,
        .max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH),
-       .rx_buffer_hash_size = 0x10,
+       .rx_prefix_size = FS_BZ_RX_PREFIX_SIZE,
+       .rx_hash_offset = FS_BZ_RX_PREFIX_HASH_OFST,
        .rx_buffer_padding = 0,
        .can_rx_scatter = true,
        .max_interrupt_mode = EFX_INT_MODE_MSIX,