Commit 7deee781 authored by Raghavendra Koushik's avatar Raghavendra Koushik Committed by Jeff Garzik

[PATCH] S2io: two buffer mode

Attached is the patch for implementing 2-buffer mode on Rx path.

On certain systems when a DMA has to happen on an un-aligned memory
location performance will take a significant hit. It's standard
practice to offset the Rx buffer address by 2 (as Mac header is 14
bytes) so the IP header starts from an aligned location.  Obviously
using a single Rx buffer both cannot be achieved. Thus XFrame supports
something called 2 buffer Rx mode, where in the Rx'ed frame is split
into 2 parts, one is the Ethernet header and the other is the Ethernet
payload. So now we can allocate proper aligned memory for both buffers,
hence the DMA is not slowed down. Also, the Ethernet payload(starting
from L3 header) is on an aligned location so OS need not have to do
un-aligned accesses to process IP header. To achieve this, the kernel
function eth_type_trans functionality has to be partially implemented
in the driver itself.
Signed-off-by: default avatarRaghavendra Koushik <raghavendra.koushik@s2io.com>
Signed-off-by: default avatarRavinandan Arakali <ravinandan.arakali@s2io.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent a5ebf123
...@@ -2267,6 +2267,17 @@ config S2IO_NAPI ...@@ -2267,6 +2267,17 @@ config S2IO_NAPI
If in doubt, say N. If in doubt, say N.
config 2BUFF_MODE
bool "Use 2 Buffer Mode on Rx side."
depends on S2IO
---help---
On enabling the 2 buffer mode, the received frame will be
split into 2 parts before being DMA'ed to the hosts memory.
The parts are the ethernet header and ethernet payload.
This is useful on systems where DMA'ing to to unaligned
physical memory loactions comes with a heavy price.
If not sure please say N.
endmenu endmenu
source "drivers/net/tokenring/Kconfig" source "drivers/net/tokenring/Kconfig"
......
This diff is collapsed.
...@@ -466,19 +466,46 @@ typedef struct _RxD_t { ...@@ -466,19 +466,46 @@ typedef struct _RxD_t {
#define RXD_GET_L4_CKSUM(val) ((u16)(val) & 0xFFFF) #define RXD_GET_L4_CKSUM(val) ((u16)(val) & 0xFFFF)
u64 Control_2; u64 Control_2;
#ifndef CONFIG_2BUFF_MODE
#define MASK_BUFFER0_SIZE vBIT(0xFFFF,0,16) #define MASK_BUFFER0_SIZE vBIT(0xFFFF,0,16)
#define SET_BUFFER0_SIZE(val) vBIT(val,0,16) #define SET_BUFFER0_SIZE(val) vBIT(val,0,16)
#else
#define MASK_BUFFER0_SIZE vBIT(0xFF,0,16)
#define MASK_BUFFER1_SIZE vBIT(0xFFFF,16,16)
#define MASK_BUFFER2_SIZE vBIT(0xFFFF,32,16)
#define SET_BUFFER0_SIZE(val) vBIT(val,8,8)
#define SET_BUFFER1_SIZE(val) vBIT(val,16,16)
#define SET_BUFFER2_SIZE(val) vBIT(val,32,16)
#endif
#define MASK_VLAN_TAG vBIT(0xFFFF,48,16) #define MASK_VLAN_TAG vBIT(0xFFFF,48,16)
#define SET_VLAN_TAG(val) vBIT(val,48,16) #define SET_VLAN_TAG(val) vBIT(val,48,16)
#define SET_NUM_TAG(val) vBIT(val,16,32) #define SET_NUM_TAG(val) vBIT(val,16,32)
#ifndef CONFIG_2BUFF_MODE
#define RXD_GET_BUFFER0_SIZE(Control_2) (u64)((Control_2 & vBIT(0xFFFF,0,16))) #define RXD_GET_BUFFER0_SIZE(Control_2) (u64)((Control_2 & vBIT(0xFFFF,0,16)))
#else
#define RXD_GET_BUFFER0_SIZE(Control_2) (u8)((Control_2 & MASK_BUFFER0_SIZE) \
>> 48)
#define RXD_GET_BUFFER1_SIZE(Control_2) (u16)((Control_2 & MASK_BUFFER1_SIZE) \
>> 32)
#define RXD_GET_BUFFER2_SIZE(Control_2) (u16)((Control_2 & MASK_BUFFER2_SIZE) \
>> 16)
#define BUF0_LEN 40
#define BUF1_LEN 1
#endif
u64 Buffer0_ptr; u64 Buffer0_ptr;
#ifdef CONFIG_2BUFF_MODE
u64 Buffer1_ptr;
u64 Buffer2_ptr;
#endif
} RxD_t; } RxD_t;
/* Structure that represents the Rx descriptor block which contains /* Structure that represents the Rx descriptor block which contains
* 128 Rx descriptors. * 128 Rx descriptors.
*/ */
#ifndef CONFIG_2BUFF_MODE
typedef struct _RxD_block { typedef struct _RxD_block {
#define MAX_RXDS_PER_BLOCK 127 #define MAX_RXDS_PER_BLOCK 127
RxD_t rxd[MAX_RXDS_PER_BLOCK]; RxD_t rxd[MAX_RXDS_PER_BLOCK];
...@@ -492,6 +519,27 @@ typedef struct _RxD_block { ...@@ -492,6 +519,27 @@ typedef struct _RxD_block {
* the upper 32 bits should * the upper 32 bits should
* be 0 */ * be 0 */
} RxD_block_t; } RxD_block_t;
#else
typedef struct _RxD_block {
#define MAX_RXDS_PER_BLOCK 85
RxD_t rxd[MAX_RXDS_PER_BLOCK];
#define END_OF_BLOCK 0xFEFFFFFFFFFFFFFFULL
u64 reserved_1; /* 0xFEFFFFFFFFFFFFFF to mark last Rxd
* in this blk */
u64 pNext_RxD_Blk_physical; /* Phy ponter to next blk. */
} RxD_block_t;
#define SIZE_OF_BLOCK 4096
/* Structure to hold virtual addresses of Buf0 and Buf1 in
* 2buf mode. */
typedef struct bufAdd {
void *ba_0_org;
void *ba_1_org;
void *ba_0;
void *ba_1;
} buffAdd_t;
#endif
/* Structure which stores all the MAC control parameters */ /* Structure which stores all the MAC control parameters */
...@@ -677,6 +725,10 @@ typedef struct s2io_nic { ...@@ -677,6 +725,10 @@ typedef struct s2io_nic {
#define LINK_DOWN 1 #define LINK_DOWN 1
#define LINK_UP 2 #define LINK_UP 2
#ifdef CONFIG_2BUFF_MODE
/* Buffer Address store. */
buffAdd_t **ba[MAX_RX_RINGS];
#endif
int task_flag; int task_flag;
} nic_t; } nic_t;
...@@ -802,7 +854,12 @@ void s2io_closer(void); ...@@ -802,7 +854,12 @@ void s2io_closer(void);
static void s2io_tx_watchdog(struct net_device *dev); static void s2io_tx_watchdog(struct net_device *dev);
static void s2io_tasklet(unsigned long dev_addr); static void s2io_tasklet(unsigned long dev_addr);
static void s2io_set_multicast(struct net_device *dev); static void s2io_set_multicast(struct net_device *dev);
#ifndef CONFIG_2BUFF_MODE
static int rx_osm_handler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no); static int rx_osm_handler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no);
#else
static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
buffAdd_t * ba);
#endif
void s2io_link(nic_t * sp, int link); void s2io_link(nic_t * sp, int link);
void s2io_reset(nic_t * sp); void s2io_reset(nic_t * sp);
#ifdef CONFIG_S2IO_NAPI #ifdef CONFIG_S2IO_NAPI
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment