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
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
source "drivers/net/tokenring/Kconfig"
......
......@@ -325,6 +325,10 @@ static int init_shared_mem(struct s2io_nic *nic)
int i, j, blk_cnt;
int lst_size, lst_per_page;
struct net_device *dev = nic->dev;
#ifdef CONFIG_2BUFF_MODE
u64 tmp;
buffAdd_t *ba;
#endif
mac_info_t *mac_control;
struct config_param *config;
......@@ -425,7 +429,11 @@ static int init_shared_mem(struct s2io_nic *nic)
config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
/* Allocating all the Rx blocks */
for (j = 0; j < blk_cnt; j++) {
#ifndef CONFIG_2BUFF_MODE
size = (MAX_RXDS_PER_BLOCK + 1) * (sizeof(RxD_t));
#else
size = SIZE_OF_BLOCK;
#endif
tmp_v_addr = pci_alloc_consistent(nic->pdev, size,
&tmp_p_addr);
if (tmp_v_addr == NULL) {
......@@ -458,13 +466,60 @@ static int init_shared_mem(struct s2io_nic *nic)
pre_rxd_blk->reserved_1 = END_OF_BLOCK; /* last RxD
* marker.
*/
#ifndef CONFIG_2BUFF_MODE
pre_rxd_blk->reserved_2_pNext_RxD_block =
(unsigned long) tmp_v_addr_next;
#endif
pre_rxd_blk->pNext_RxD_Blk_physical =
(u64) tmp_p_addr_next;
}
}
#ifdef CONFIG_2BUFF_MODE
/*
* Allocation of Storages for buffer addresses in 2BUFF mode
* and the buffers as well.
*/
for (i = 0; i < config->rx_ring_num; i++) {
blk_cnt =
config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
nic->ba[i] = kmalloc((sizeof(buffAdd_t *) * blk_cnt),
GFP_KERNEL);
if (!nic->ba[i])
return -ENOMEM;
for (j = 0; j < blk_cnt; j++) {
int k = 0;
nic->ba[i][j] = kmalloc((sizeof(buffAdd_t) *
(MAX_RXDS_PER_BLOCK + 1)),
GFP_KERNEL);
if (!nic->ba[i][j])
return -ENOMEM;
while (k != MAX_RXDS_PER_BLOCK) {
ba = &nic->ba[i][j][k];
ba->ba_0_org = (void *) kmalloc
(BUF0_LEN + ALIGN_SIZE, GFP_ATOMIC);
if (!ba->ba_0_org)
return -ENOMEM;
tmp = (u64) ba->ba_0_org;
tmp += ALIGN_SIZE;
tmp &= ~((u64) ALIGN_SIZE);
ba->ba_0 = (void *) tmp;
ba->ba_1_org = (void *) kmalloc
(BUF1_LEN + ALIGN_SIZE, GFP_ATOMIC);
if (!ba->ba_1_org)
return -ENOMEM;
tmp = (u64) ba->ba_1_org;
tmp += ALIGN_SIZE;
tmp &= ~((u64) ALIGN_SIZE);
ba->ba_1 = (void *) tmp;
k++;
}
}
}
#endif
/* Allocation and initialization of Statistics block */
size = sizeof(StatInfo_t);
mac_control->stats_mem = pci_alloc_consistent
......@@ -532,7 +587,11 @@ static void free_shared_mem(struct s2io_nic *nic)
kfree(nic->list_info[i]);
}
#ifndef CONFIG_2BUFF_MODE
size = (MAX_RXDS_PER_BLOCK + 1) * (sizeof(RxD_t));
#else
size = SIZE_OF_BLOCK;
#endif
for (i = 0; i < config->rx_ring_num; i++) {
blk_cnt = nic->block_count[i];
for (j = 0; j < blk_cnt; j++) {
......@@ -545,6 +604,27 @@ static void free_shared_mem(struct s2io_nic *nic)
}
}
#ifdef CONFIG_2BUFF_MODE
/* Freeing buffer storage addresses in 2BUFF mode. */
for (i = 0; i < config->rx_ring_num; i++) {
blk_cnt =
config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
for (j = 0; j < blk_cnt; j++) {
int k = 0;
if (!nic->ba[i][j])
continue;
while (k != MAX_RXDS_PER_BLOCK) {
buffAdd_t *ba = &nic->ba[i][j][k];
kfree(ba->ba_0_org);
kfree(ba->ba_1_org);
k++;
}
kfree(nic->ba[i][j]);
}
if (nic->ba[i])
kfree(nic->ba[i]);
}
#endif
if (mac_control->stats_mem) {
pci_free_consistent(nic->pdev,
......@@ -1366,10 +1446,21 @@ static int start_nic(struct s2io_nic *nic)
&bar0->prc_rxd0_n[i]);
val64 = readq(&bar0->prc_ctrl_n[i]);
#ifndef CONFIG_2BUFF_MODE
val64 |= PRC_CTRL_RC_ENABLED;
#else
val64 |= PRC_CTRL_RC_ENABLED | PRC_CTRL_RING_MODE_3;
#endif
writeq(val64, &bar0->prc_ctrl_n[i]);
}
#ifdef CONFIG_2BUFF_MODE
/* Enabling 2 buffer mode by writing into Rx_pa_cfg reg. */
val64 = readq(&bar0->rx_pa_cfg);
val64 |= RX_PA_CFG_IGNORE_L2_ERR;
writeq(val64, &bar0->rx_pa_cfg);
#endif
/*
* Enabling MC-RLDRAM. After enabling the device, we timeout
* for around 100ms, which is approximately the time required
......@@ -1436,6 +1527,12 @@ static int start_nic(struct s2io_nic *nic)
writeq(val64, (void *) ((u8 *) bar0 + 0x2700));
}
/*
* Don't see link state interrupts on certain switches, so
* directly scheduling a link state task from here.
*/
schedule_work(&nic->set_link_task);
/*
* Here we are performing soft reset on XGXS to
* force link down. Since link is already up, we will get
......@@ -1565,6 +1662,13 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
atomic_read(&nic->rx_bufs_left[ring_no]);
mac_info_t *mac_control;
struct config_param *config;
#ifdef CONFIG_2BUFF_MODE
RxD_t *rxdpnext;
int nextblk;
u64 tmp;
buffAdd_t *ba;
dma_addr_t rxdpphys;
#endif
#ifndef CONFIG_S2IO_NAPI
unsigned long flags;
#endif
......@@ -1589,10 +1693,14 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
block_index;
off = mac_control->rx_curr_put_info[ring_no].offset;
off1 = mac_control->rx_curr_get_info[ring_no].offset;
#ifndef CONFIG_2BUFF_MODE
offset = block_no * (MAX_RXDS_PER_BLOCK + 1) + off;
offset1 = block_no1 * (MAX_RXDS_PER_BLOCK + 1) + off1;
#else
offset = block_no * (MAX_RXDS_PER_BLOCK) + off;
offset1 = block_no1 * (MAX_RXDS_PER_BLOCK) + off1;
#endif
rxdp = nic->rx_blocks[ring_no][block_no].
block_virt_addr + off;
if ((offset == offset1) && (rxdp->Host_Control)) {
......@@ -1600,6 +1708,7 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
DBG_PRINT(INTR_DBG, " info equated\n");
goto end;
}
#ifndef CONFIG_2BUFF_MODE
if (rxdp->Control_1 == END_OF_BLOCK) {
mac_control->rx_curr_put_info[ring_no].
block_index++;
......@@ -1615,25 +1724,83 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n",
dev->name, rxdp);
}
#ifndef CONFIG_S2IO_NAPI
spin_lock_irqsave(&nic->put_lock, flags);
nic->put_pos[ring_no] =
(block_no * (MAX_RXDS_PER_BLOCK + 1)) + off;
spin_unlock_irqrestore(&nic->put_lock, flags);
#endif
#else
if (rxdp->Host_Control == END_OF_BLOCK) {
mac_control->rx_curr_put_info[ring_no].
block_index++;
mac_control->rx_curr_put_info[ring_no].
block_index %= nic->block_count[ring_no];
block_no = mac_control->rx_curr_put_info
[ring_no].block_index;
off = 0;
DBG_PRINT(INTR_DBG, "%s: block%d at: 0x%llx\n",
dev->name, block_no,
(unsigned long long) rxdp->Control_1);
mac_control->rx_curr_put_info[ring_no].offset =
off;
rxdp = nic->rx_blocks[ring_no][block_no].
block_virt_addr;
}
#ifndef CONFIG_S2IO_NAPI
spin_lock_irqsave(&nic->put_lock, flags);
nic->put_pos[ring_no] = (block_no *
(MAX_RXDS_PER_BLOCK + 1)) + off;
spin_unlock_irqrestore(&nic->put_lock, flags);
#endif
#endif
if (rxdp->Control_1 & RXD_OWN_XENA) {
#ifndef CONFIG_2BUFF_MODE
if (rxdp->Control_1 & RXD_OWN_XENA)
#else
if (rxdp->Control_2 & BIT(0))
#endif
{
mac_control->rx_curr_put_info[ring_no].
offset = off;
goto end;
}
#ifdef CONFIG_2BUFF_MODE
/*
* RxDs Spanning cache lines will be replenished only
* if the succeeding RxD is also owned by Host. It
* will always be the ((8*i)+3) and ((8*i)+6)
* descriptors for the 48 byte descriptor. The offending
* decsriptor is of-course the 3rd descriptor.
*/
rxdpphys = nic->rx_blocks[ring_no][block_no].
block_dma_addr + (off * sizeof(RxD_t));
if (((u64) (rxdpphys)) % 128 > 80) {
rxdpnext = nic->rx_blocks[ring_no][block_no].
block_virt_addr + (off + 1);
if (rxdpnext->Host_Control == END_OF_BLOCK) {
nextblk = (block_no + 1) %
(nic->block_count[ring_no]);
rxdpnext = nic->rx_blocks[ring_no]
[nextblk].block_virt_addr;
}
if (rxdpnext->Control_2 & BIT(0))
goto end;
}
#endif
#ifndef CONFIG_2BUFF_MODE
skb = dev_alloc_skb(size + NET_IP_ALIGN);
#else
skb = dev_alloc_skb(dev->mtu + ALIGN_SIZE +
/*BUF0_LEN + */ 22);
#endif
if (!skb) {
DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name);
DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n");
return -ENOMEM;
}
#ifndef CONFIG_2BUFF_MODE
skb_reserve(skb, NET_IP_ALIGN);
memset(rxdp, 0, sizeof(RxD_t));
rxdp->Buffer0_ptr = pci_map_single
......@@ -1645,6 +1812,33 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
off++;
off %= (MAX_RXDS_PER_BLOCK + 1);
mac_control->rx_curr_put_info[ring_no].offset = off;
#else
ba = &nic->ba[ring_no][block_no][off];
tmp = (u64) skb->data;
tmp += ALIGN_SIZE;
tmp &= ~ALIGN_SIZE;
skb->data = (void *) tmp;
memset(rxdp, 0, sizeof(RxD_t));
rxdp->Buffer2_ptr = pci_map_single
(nic->pdev, skb->data, dev->mtu + 22,
PCI_DMA_FROMDEVICE);
rxdp->Buffer0_ptr =
pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN,
PCI_DMA_FROMDEVICE);
rxdp->Buffer1_ptr =
pci_map_single(nic->pdev, ba->ba_1, BUF1_LEN,
PCI_DMA_FROMDEVICE);
rxdp->Control_2 = SET_BUFFER2_SIZE(dev->mtu + 22);
rxdp->Control_2 |= SET_BUFFER0_SIZE(BUF0_LEN);
rxdp->Control_2 |= SET_BUFFER1_SIZE(1); /* dummy. */
rxdp->Control_2 |= BIT(0); /* Set Buffer_Empty bit. */
rxdp->Host_Control = (u64) ((unsigned long) (skb));
rxdp->Control_1 |= RXD_OWN_XENA;
off++;
mac_control->rx_curr_put_info[ring_no].offset = off;
#endif
atomic_inc(&nic->rx_bufs_left[ring_no]);
alloc_tab++;
}
......@@ -1670,6 +1864,9 @@ static void free_rx_buffers(struct s2io_nic *sp)
struct sk_buff *skb;
mac_info_t *mac_control;
struct config_param *config;
#ifdef CONFIG_2BUFF_MODE
buffAdd_t *ba;
#endif
mac_control = &sp->mac_control;
config = &sp->config;
......@@ -1679,6 +1876,7 @@ static void free_rx_buffers(struct s2io_nic *sp)
off = j % (MAX_RXDS_PER_BLOCK + 1);
rxdp = sp->rx_blocks[i][blk].block_virt_addr + off;
#ifndef CONFIG_2BUFF_MODE
if (rxdp->Control_1 == END_OF_BLOCK) {
rxdp =
(RxD_t *) ((unsigned long) rxdp->
......@@ -1686,6 +1884,12 @@ static void free_rx_buffers(struct s2io_nic *sp)
j++;
blk++;
}
#else
if (rxdp->Host_Control == END_OF_BLOCK) {
blk++;
continue;
}
#endif
if (!(rxdp->Control_1 & RXD_OWN_XENA)) {
memset(rxdp, 0, sizeof(RxD_t));
......@@ -1696,6 +1900,7 @@ static void free_rx_buffers(struct s2io_nic *sp)
(struct sk_buff *) ((unsigned long) rxdp->
Host_Control);
if (skb) {
#ifndef CONFIG_2BUFF_MODE
pci_unmap_single(sp->pdev, (dma_addr_t)
rxdp->Buffer0_ptr,
dev->mtu +
......@@ -1703,6 +1908,21 @@ static void free_rx_buffers(struct s2io_nic *sp)
+ HEADER_802_2_SIZE +
HEADER_SNAP_SIZE,
PCI_DMA_FROMDEVICE);
#else
ba = &sp->ba[i][blk][off];
pci_unmap_single(sp->pdev, (dma_addr_t)
rxdp->Buffer0_ptr,
BUF0_LEN,
PCI_DMA_FROMDEVICE);
pci_unmap_single(sp->pdev, (dma_addr_t)
rxdp->Buffer1_ptr,
BUF1_LEN,
PCI_DMA_FROMDEVICE);
pci_unmap_single(sp->pdev, (dma_addr_t)
rxdp->Buffer2_ptr,
dev->mtu + 22,
PCI_DMA_FROMDEVICE);
#endif
dev_kfree_skb(skb);
atomic_dec(&sp->rx_bufs_left[i]);
buf_cnt++;
......@@ -1741,11 +1961,16 @@ static int s2io_poll(struct net_device *dev, int *budget)
register u64 val64 = 0;
rx_curr_get_info_t get_info, put_info;
int i, get_block, put_block, get_offset, put_offset, ring_bufs;
#ifndef CONFIG_2BUFF_MODE
u16 val16, cksum;
#endif
struct sk_buff *skb;
RxD_t *rxdp;
mac_info_t *mac_control;
struct config_param *config;
#ifdef CONFIG_2BUFF_MODE
buffAdd_t *ba;
#endif
mac_control = &nic->mac_control;
config = &nic->config;
......@@ -1764,6 +1989,7 @@ static int s2io_poll(struct net_device *dev, int *budget)
ring_bufs = config->rx_cfg[i].num_rxd;
rxdp = nic->rx_blocks[i][get_block].block_virt_addr +
get_info.offset;
#ifndef CONFIG_2BUFF_MODE
get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
get_info.offset;
put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) +
......@@ -1820,6 +2046,66 @@ static int s2io_poll(struct net_device *dev, int *budget)
mac_control->rx_curr_get_info[i].offset =
get_info.offset;
}
#else
get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
get_info.offset;
put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) +
put_info.offset;
while (((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
!(rxdp->Control_2 & BIT(0))) &&
(((get_offset + 1) % ring_bufs) != put_offset)) {
if (--pkts_to_process < 0) {
goto no_rx;
}
skb = (struct sk_buff *) ((unsigned long)
rxdp->Host_Control);
if (skb == NULL) {
DBG_PRINT(ERR_DBG, "%s: The skb is ",
dev->name);
DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
goto no_rx;
}
pci_unmap_single(nic->pdev, (dma_addr_t)
rxdp->Buffer0_ptr,
BUF0_LEN, PCI_DMA_FROMDEVICE);
pci_unmap_single(nic->pdev, (dma_addr_t)
rxdp->Buffer1_ptr,
BUF1_LEN, PCI_DMA_FROMDEVICE);
pci_unmap_single(nic->pdev, (dma_addr_t)
rxdp->Buffer2_ptr,
dev->mtu + 22,
PCI_DMA_FROMDEVICE);
ba = &nic->ba[i][get_block][get_info.offset];
rx_osm_handler(nic, rxdp, i, ba);
get_info.offset++;
mac_control->rx_curr_get_info[i].offset =
get_info.offset;
rxdp =
nic->rx_blocks[i][get_block].block_virt_addr +
get_info.offset;
if (get_info.offset &&
(!(get_info.offset % MAX_RXDS_PER_BLOCK))) {
get_info.offset = 0;
mac_control->rx_curr_get_info[i].
offset = get_info.offset;
get_block++;
get_block %= nic->block_count[i];
mac_control->rx_curr_get_info[i].
block_index = get_block;
rxdp =
nic->rx_blocks[i][get_block].
block_virt_addr;
}
get_offset =
(get_block * (MAX_RXDS_PER_BLOCK + 1)) +
get_info.offset;
pkt_cnt++;
}
#endif
}
if (!pkt_cnt)
pkt_cnt = 1;
......@@ -1873,12 +2159,17 @@ static void rx_intr_handler(struct s2io_nic *nic)
rx_curr_get_info_t get_info, put_info;
RxD_t *rxdp;
struct sk_buff *skb;
#ifndef CONFIG_2BUFF_MODE
u16 val16, cksum;
#endif
register u64 val64 = 0;
int get_block, get_offset, put_block, put_offset, ring_bufs;
int i, pkt_cnt = 0;
mac_info_t *mac_control;
struct config_param *config;
#ifdef CONFIG_2BUFF_MODE
buffAdd_t *ba;
#endif
mac_control = &nic->mac_control;
config = &nic->config;
......@@ -1898,6 +2189,7 @@ static void rx_intr_handler(struct s2io_nic *nic)
ring_bufs = config->rx_cfg[i].num_rxd;
rxdp = nic->rx_blocks[i][get_block].block_virt_addr +
get_info.offset;
#ifndef CONFIG_2BUFF_MODE
get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
get_info.offset;
spin_lock(&nic->put_lock);
......@@ -1953,6 +2245,67 @@ static void rx_intr_handler(struct s2io_nic *nic)
&& (pkt_cnt > indicate_max_pkts))
break;
}
#else
get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
get_info.offset;
spin_lock(&nic->put_lock);
put_offset = nic->put_pos[i];
spin_unlock(&nic->put_lock);
while (((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
!(rxdp->Control_2 & BIT(0))) &&
(((get_offset + 1) % ring_bufs) != put_offset)) {
skb = (struct sk_buff *) ((unsigned long)
rxdp->Host_Control);
if (skb == NULL) {
DBG_PRINT(ERR_DBG, "%s: The skb is ",
dev->name);
DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
return;
}
pci_unmap_single(nic->pdev, (dma_addr_t)
rxdp->Buffer0_ptr,
BUF0_LEN, PCI_DMA_FROMDEVICE);
pci_unmap_single(nic->pdev, (dma_addr_t)
rxdp->Buffer1_ptr,
BUF1_LEN, PCI_DMA_FROMDEVICE);
pci_unmap_single(nic->pdev, (dma_addr_t)
rxdp->Buffer2_ptr,
dev->mtu + 22,
PCI_DMA_FROMDEVICE);
ba = &nic->ba[i][get_block][get_info.offset];
rx_osm_handler(nic, rxdp, i, ba);
get_info.offset++;
mac_control->rx_curr_get_info[i].offset =
get_info.offset;
rxdp =
nic->rx_blocks[i][get_block].block_virt_addr +
get_info.offset;
if (get_info.offset &&
(!(get_info.offset % MAX_RXDS_PER_BLOCK))) {
get_info.offset = 0;
mac_control->rx_curr_get_info[i].
offset = get_info.offset;
get_block++;
get_block %= nic->block_count[i];
mac_control->rx_curr_get_info[i].
block_index = get_block;
rxdp =
nic->rx_blocks[i][get_block].
block_virt_addr;
}
get_offset =
(get_block * (MAX_RXDS_PER_BLOCK + 1)) +
get_info.offset;
pkt_cnt++;
if ((indicate_max_pkts)
&& (pkt_cnt > indicate_max_pkts))
break;
}
#endif
if ((indicate_max_pkts) && (pkt_cnt > indicate_max_pkts))
break;
}
......@@ -4096,12 +4449,21 @@ static void s2io_tx_watchdog(struct net_device *dev)
* Return value:
* SUCCESS on success and -1 on failure.
*/
#ifndef CONFIG_2BUFF_MODE
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
{
struct net_device *dev = (struct net_device *) sp->dev;
struct sk_buff *skb =
(struct sk_buff *) ((unsigned long) rxdp->Host_Control);
u16 l3_csum, l4_csum;
#ifdef CONFIG_2BUFF_MODE
int buf0_len, buf2_len;
struct ethhdr *eth = (struct ethhdr *) ba->ba_0;
#endif
l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1);
if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && (sp->rx_csum)) {
......@@ -4129,10 +4491,32 @@ static int rx_osm_handler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no)
DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
dev->name, err);
}
#ifdef CONFIG_2BUFF_MODE
buf0_len = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
buf2_len = RXD_GET_BUFFER2_SIZE(rxdp->Control_2);
#endif
skb->dev = dev;
#ifndef CONFIG_2BUFF_MODE
skb_put(skb, len);
skb->protocol = eth_type_trans(skb, dev);
#else
skb_put(skb, buf2_len);
/*
* Reproducing eth_type_trans functionality and running
* on the ethernet header 'eth' stripped and given to us
* by the hardware in 2Buff mode.
*/
if (*eth->h_dest & 1) {
if (!memcmp(eth->h_dest, dev->broadcast, ETH_ALEN))
skb->pkt_type = PACKET_BROADCAST;
else
skb->pkt_type = PACKET_MULTICAST;
} else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN)) {
skb->pkt_type = PACKET_OTHERHOST;
}
skb->protocol = eth->h_proto;
#endif
#ifdef CONFIG_S2IO_NAPI
netif_receive_skb(skb);
......@@ -4143,7 +4527,11 @@ static int rx_osm_handler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no)
dev->last_rx = jiffies;
sp->rx_pkt_count++;
sp->stats.rx_packets++;
#ifndef CONFIG_2BUFF_MODE
sp->stats.rx_bytes += len;
#else
sp->stats.rx_bytes += buf0_len + buf2_len;
#endif
atomic_dec(&sp->rx_bufs_left[ring_no]);
rxdp->Host_Control = 0;
......
......@@ -466,19 +466,46 @@ typedef struct _RxD_t {
#define RXD_GET_L4_CKSUM(val) ((u16)(val) & 0xFFFF)
u64 Control_2;
#ifndef CONFIG_2BUFF_MODE
#define MASK_BUFFER0_SIZE vBIT(0xFFFF,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 SET_VLAN_TAG(val) vBIT(val,48,16)
#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)))
#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;
#ifdef CONFIG_2BUFF_MODE
u64 Buffer1_ptr;
u64 Buffer2_ptr;
#endif
} RxD_t;
/* Structure that represents the Rx descriptor block which contains
* 128 Rx descriptors.
*/
#ifndef CONFIG_2BUFF_MODE
typedef struct _RxD_block {
#define MAX_RXDS_PER_BLOCK 127
RxD_t rxd[MAX_RXDS_PER_BLOCK];
......@@ -492,6 +519,27 @@ typedef struct _RxD_block {
* the upper 32 bits should
* be 0 */
} 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 */
......@@ -677,6 +725,10 @@ typedef struct s2io_nic {
#define LINK_DOWN 1
#define LINK_UP 2
#ifdef CONFIG_2BUFF_MODE
/* Buffer Address store. */
buffAdd_t **ba[MAX_RX_RINGS];
#endif
int task_flag;
} nic_t;
......@@ -802,7 +854,12 @@ void s2io_closer(void);
static void s2io_tx_watchdog(struct net_device *dev);
static void s2io_tasklet(unsigned long dev_addr);
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);
#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_reset(nic_t * sp);
#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