aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/netxen/netxen_nic.h21
-rw-r--r--drivers/net/netxen/netxen_nic_ctx.c2
-rw-r--r--drivers/net/netxen/netxen_nic_init.c124
3 files changed, 125 insertions, 22 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index bb4aa4f58676..ae81f7022d23 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -365,6 +365,7 @@ struct rcv_desc {
365#define NETXEN_NIC_RXPKT_DESC 0x04 365#define NETXEN_NIC_RXPKT_DESC 0x04
366#define NETXEN_OLD_RXPKT_DESC 0x3f 366#define NETXEN_OLD_RXPKT_DESC 0x3f
367#define NETXEN_NIC_RESPONSE_DESC 0x05 367#define NETXEN_NIC_RESPONSE_DESC 0x05
368#define NETXEN_NIC_LRO_DESC 0x12
368 369
369/* for status field in status_desc */ 370/* for status field in status_desc */
370#define STATUS_NEED_CKSUM (1) 371#define STATUS_NEED_CKSUM (1)
@@ -398,6 +399,24 @@ struct rcv_desc {
398#define netxen_get_sts_opcode(sts_data) \ 399#define netxen_get_sts_opcode(sts_data) \
399 (((sts_data) >> 58) & 0x03F) 400 (((sts_data) >> 58) & 0x03F)
400 401
402#define netxen_get_lro_sts_refhandle(sts_data) \
403 ((sts_data) & 0x0FFFF)
404#define netxen_get_lro_sts_length(sts_data) \
405 (((sts_data) >> 16) & 0x0FFFF)
406#define netxen_get_lro_sts_l2_hdr_offset(sts_data) \
407 (((sts_data) >> 32) & 0x0FF)
408#define netxen_get_lro_sts_l4_hdr_offset(sts_data) \
409 (((sts_data) >> 40) & 0x0FF)
410#define netxen_get_lro_sts_timestamp(sts_data) \
411 (((sts_data) >> 48) & 0x1)
412#define netxen_get_lro_sts_type(sts_data) \
413 (((sts_data) >> 49) & 0x7)
414#define netxen_get_lro_sts_push_flag(sts_data) \
415 (((sts_data) >> 52) & 0x1)
416#define netxen_get_lro_sts_seq_number(sts_data) \
417 ((sts_data) & 0x0FFFFFFFF)
418
419
401struct status_desc { 420struct status_desc {
402 __le64 status_desc_data[2]; 421 __le64 status_desc_data[2];
403} __attribute__ ((aligned(16))); 422} __attribute__ ((aligned(16)));
@@ -712,6 +731,7 @@ struct netxen_recv_context {
712#define NX_CAP0_LSO NX_CAP_BIT(0, 6) 731#define NX_CAP0_LSO NX_CAP_BIT(0, 6)
713#define NX_CAP0_JUMBO_CONTIGUOUS NX_CAP_BIT(0, 7) 732#define NX_CAP0_JUMBO_CONTIGUOUS NX_CAP_BIT(0, 7)
714#define NX_CAP0_LRO_CONTIGUOUS NX_CAP_BIT(0, 8) 733#define NX_CAP0_LRO_CONTIGUOUS NX_CAP_BIT(0, 8)
734#define NX_CAP0_HW_LRO NX_CAP_BIT(0, 10)
715 735
716/* 736/*
717 * Context state 737 * Context state
@@ -969,6 +989,7 @@ typedef struct {
969#define NX_FW_CAPABILITY_PEXQ (1 << 7) 989#define NX_FW_CAPABILITY_PEXQ (1 << 7)
970#define NX_FW_CAPABILITY_BDG (1 << 8) 990#define NX_FW_CAPABILITY_BDG (1 << 8)
971#define NX_FW_CAPABILITY_FVLANTX (1 << 9) 991#define NX_FW_CAPABILITY_FVLANTX (1 << 9)
992#define NX_FW_CAPABILITY_HW_LRO (1 << 10)
972 993
973/* module types */ 994/* module types */
974#define LINKEVENT_MODULE_NOT_PRESENT 1 995#define LINKEVENT_MODULE_NOT_PRESENT 1
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
index 9e0469643d34..412d65829d20 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -203,6 +203,8 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
203 203
204 cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN); 204 cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN);
205 cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS); 205 cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS);
206 if (adapter->capabilities & NX_FW_CAPABILITY_HW_LRO)
207 cap |= NX_CAP0_HW_LRO;
206 208
207 prq->capabilities[0] = cpu_to_le32(cap); 209 prq->capabilities[0] = cpu_to_le32(cap);
208 prq->host_int_crb_mode = 210 prq->host_int_crb_mode =
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 81253abbfa34..582828756ef4 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -1242,20 +1242,31 @@ no_skb:
1242 1242
1243static struct netxen_rx_buffer * 1243static struct netxen_rx_buffer *
1244netxen_process_rcv(struct netxen_adapter *adapter, 1244netxen_process_rcv(struct netxen_adapter *adapter,
1245 int ring, int index, int length, int cksum, int pkt_offset, 1245 struct nx_host_sds_ring *sds_ring,
1246 struct nx_host_sds_ring *sds_ring) 1246 int ring, u64 sts_data0)
1247{ 1247{
1248 struct net_device *netdev = adapter->netdev; 1248 struct net_device *netdev = adapter->netdev;
1249 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; 1249 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
1250 struct netxen_rx_buffer *buffer; 1250 struct netxen_rx_buffer *buffer;
1251 struct sk_buff *skb; 1251 struct sk_buff *skb;
1252 struct nx_host_rds_ring *rds_ring = &recv_ctx->rds_rings[ring]; 1252 struct nx_host_rds_ring *rds_ring;
1253 int index, length, cksum, pkt_offset;
1253 1254
1254 if (unlikely(index > rds_ring->num_desc)) 1255 if (unlikely(ring >= adapter->max_rds_rings))
1256 return NULL;
1257
1258 rds_ring = &recv_ctx->rds_rings[ring];
1259
1260 index = netxen_get_sts_refhandle(sts_data0);
1261 if (unlikely(index >= rds_ring->num_desc))
1255 return NULL; 1262 return NULL;
1256 1263
1257 buffer = &rds_ring->rx_buf_arr[index]; 1264 buffer = &rds_ring->rx_buf_arr[index];
1258 1265
1266 length = netxen_get_sts_totallength(sts_data0);
1267 cksum = netxen_get_sts_status(sts_data0);
1268 pkt_offset = netxen_get_sts_pkt_offset(sts_data0);
1269
1259 skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum); 1270 skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum);
1260 if (!skb) 1271 if (!skb)
1261 return buffer; 1272 return buffer;
@@ -1279,6 +1290,78 @@ netxen_process_rcv(struct netxen_adapter *adapter,
1279 return buffer; 1290 return buffer;
1280} 1291}
1281 1292
1293#define TCP_HDR_SIZE 20
1294#define TCP_TS_OPTION_SIZE 12
1295#define TCP_TS_HDR_SIZE (TCP_HDR_SIZE + TCP_TS_OPTION_SIZE)
1296
1297static struct netxen_rx_buffer *
1298netxen_process_lro(struct netxen_adapter *adapter,
1299 struct nx_host_sds_ring *sds_ring,
1300 int ring, u64 sts_data0, u64 sts_data1)
1301{
1302 struct net_device *netdev = adapter->netdev;
1303 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
1304 struct netxen_rx_buffer *buffer;
1305 struct sk_buff *skb;
1306 struct nx_host_rds_ring *rds_ring;
1307 struct iphdr *iph;
1308 struct tcphdr *th;
1309 bool push, timestamp;
1310 int l2_hdr_offset, l4_hdr_offset;
1311 int index;
1312 u16 lro_length, length, data_offset;
1313 u32 seq_number;
1314
1315 if (unlikely(ring > adapter->max_rds_rings))
1316 return NULL;
1317
1318 rds_ring = &recv_ctx->rds_rings[ring];
1319
1320 index = netxen_get_lro_sts_refhandle(sts_data0);
1321 if (unlikely(index > rds_ring->num_desc))
1322 return NULL;
1323
1324 buffer = &rds_ring->rx_buf_arr[index];
1325
1326 timestamp = netxen_get_lro_sts_timestamp(sts_data0);
1327 lro_length = netxen_get_lro_sts_length(sts_data0);
1328 l2_hdr_offset = netxen_get_lro_sts_l2_hdr_offset(sts_data0);
1329 l4_hdr_offset = netxen_get_lro_sts_l4_hdr_offset(sts_data0);
1330 push = netxen_get_lro_sts_push_flag(sts_data0);
1331 seq_number = netxen_get_lro_sts_seq_number(sts_data1);
1332
1333 skb = netxen_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
1334 if (!skb)
1335 return buffer;
1336
1337 if (timestamp)
1338 data_offset = l4_hdr_offset + TCP_TS_HDR_SIZE;
1339 else
1340 data_offset = l4_hdr_offset + TCP_HDR_SIZE;
1341
1342 skb_put(skb, lro_length + data_offset);
1343
1344 skb->truesize = (skb->len + sizeof(struct sk_buff) +
1345 ((unsigned long)skb->data - (unsigned long)skb->head));
1346
1347 skb_pull(skb, l2_hdr_offset);
1348 skb->protocol = eth_type_trans(skb, netdev);
1349
1350 iph = (struct iphdr *)skb->data;
1351 th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
1352
1353 length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
1354 iph->tot_len = htons(length);
1355 iph->check = 0;
1356 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
1357 th->psh = push;
1358 th->seq = htonl(seq_number);
1359
1360 netif_receive_skb(skb);
1361
1362 return buffer;
1363}
1364
1282#define netxen_merge_rx_buffers(list, head) \ 1365#define netxen_merge_rx_buffers(list, head) \
1283 do { list_splice_tail_init(list, head); } while (0); 1366 do { list_splice_tail_init(list, head); } while (0);
1284 1367
@@ -1295,28 +1378,33 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max)
1295 u32 consumer = sds_ring->consumer; 1378 u32 consumer = sds_ring->consumer;
1296 1379
1297 int count = 0; 1380 int count = 0;
1298 u64 sts_data; 1381 u64 sts_data0, sts_data1;
1299 int opcode, ring, index, length, cksum, pkt_offset, desc_cnt; 1382 int opcode, ring = 0, desc_cnt;
1300 1383
1301 while (count < max) { 1384 while (count < max) {
1302 desc = &sds_ring->desc_head[consumer]; 1385 desc = &sds_ring->desc_head[consumer];
1303 sts_data = le64_to_cpu(desc->status_desc_data[0]); 1386 sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
1304 1387
1305 if (!(sts_data & STATUS_OWNER_HOST)) 1388 if (!(sts_data0 & STATUS_OWNER_HOST))
1306 break; 1389 break;
1307 1390
1308 desc_cnt = netxen_get_sts_desc_cnt(sts_data); 1391 desc_cnt = netxen_get_sts_desc_cnt(sts_data0);
1309 ring = netxen_get_sts_type(sts_data);
1310 1392
1311 if (ring > RCV_RING_JUMBO) 1393 opcode = netxen_get_sts_opcode(sts_data0);
1312 goto skip;
1313
1314 opcode = netxen_get_sts_opcode(sts_data);
1315 1394
1316 switch (opcode) { 1395 switch (opcode) {
1317 case NETXEN_NIC_RXPKT_DESC: 1396 case NETXEN_NIC_RXPKT_DESC:
1318 case NETXEN_OLD_RXPKT_DESC: 1397 case NETXEN_OLD_RXPKT_DESC:
1319 case NETXEN_NIC_SYN_OFFLOAD: 1398 case NETXEN_NIC_SYN_OFFLOAD:
1399 ring = netxen_get_sts_type(sts_data0);
1400 rxbuf = netxen_process_rcv(adapter, sds_ring,
1401 ring, sts_data0);
1402 break;
1403 case NETXEN_NIC_LRO_DESC:
1404 ring = netxen_get_lro_sts_type(sts_data0);
1405 sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
1406 rxbuf = netxen_process_lro(adapter, sds_ring,
1407 ring, sts_data0, sts_data1);
1320 break; 1408 break;
1321 case NETXEN_NIC_RESPONSE_DESC: 1409 case NETXEN_NIC_RESPONSE_DESC:
1322 netxen_handle_fw_message(desc_cnt, consumer, sds_ring); 1410 netxen_handle_fw_message(desc_cnt, consumer, sds_ring);
@@ -1326,14 +1414,6 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max)
1326 1414
1327 WARN_ON(desc_cnt > 1); 1415 WARN_ON(desc_cnt > 1);
1328 1416
1329 index = netxen_get_sts_refhandle(sts_data);
1330 length = netxen_get_sts_totallength(sts_data);
1331 cksum = netxen_get_sts_status(sts_data);
1332 pkt_offset = netxen_get_sts_pkt_offset(sts_data);
1333
1334 rxbuf = netxen_process_rcv(adapter, ring, index,
1335 length, cksum, pkt_offset, sds_ring);
1336
1337 if (rxbuf) 1417 if (rxbuf)
1338 list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); 1418 list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
1339 1419