diff options
author | Jan-Bernd Themann <themann@de.ibm.com> | 2007-09-25 19:16:34 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:47:47 -0400 |
commit | d4dc4ec9d84e0578b9bfbe56a11fafdb7cbac771 (patch) | |
tree | 03813a60023b75752ebcb8b3217018d472b21c86 /drivers/net/ehea/ehea_main.c | |
parent | 71c87e0cedca843162206c698cfa02e5fea9e2e3 (diff) |
[EHEA]: Use LRO.
Signed-off-by: Jan-Bernd Themann <themann@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ehea/ehea_main.c')
-rw-r--r-- | drivers/net/ehea/ehea_main.c | 84 |
1 files changed, 77 insertions, 7 deletions
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 5ebd545ab04e..b8e00391a5e3 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
@@ -52,6 +52,8 @@ static int rq2_entries = EHEA_DEF_ENTRIES_RQ2; | |||
52 | static int rq3_entries = EHEA_DEF_ENTRIES_RQ3; | 52 | static int rq3_entries = EHEA_DEF_ENTRIES_RQ3; |
53 | static int sq_entries = EHEA_DEF_ENTRIES_SQ; | 53 | static int sq_entries = EHEA_DEF_ENTRIES_SQ; |
54 | static int use_mcs = 0; | 54 | static int use_mcs = 0; |
55 | static int use_lro = 0; | ||
56 | static int lro_max_aggr = EHEA_LRO_MAX_AGGR; | ||
55 | static int num_tx_qps = EHEA_NUM_TX_QP; | 57 | static int num_tx_qps = EHEA_NUM_TX_QP; |
56 | static int prop_carrier_state = 0; | 58 | static int prop_carrier_state = 0; |
57 | 59 | ||
@@ -62,6 +64,8 @@ module_param(rq3_entries, int, 0); | |||
62 | module_param(sq_entries, int, 0); | 64 | module_param(sq_entries, int, 0); |
63 | module_param(prop_carrier_state, int, 0); | 65 | module_param(prop_carrier_state, int, 0); |
64 | module_param(use_mcs, int, 0); | 66 | module_param(use_mcs, int, 0); |
67 | module_param(use_lro, int, 0); | ||
68 | module_param(lro_max_aggr, int, 0); | ||
65 | module_param(num_tx_qps, int, 0); | 69 | module_param(num_tx_qps, int, 0); |
66 | 70 | ||
67 | MODULE_PARM_DESC(num_tx_qps, "Number of TX-QPS"); | 71 | MODULE_PARM_DESC(num_tx_qps, "Number of TX-QPS"); |
@@ -82,6 +86,11 @@ MODULE_PARM_DESC(sq_entries, " Number of entries for the Send Queue " | |||
82 | __MODULE_STRING(EHEA_DEF_ENTRIES_SQ) ")"); | 86 | __MODULE_STRING(EHEA_DEF_ENTRIES_SQ) ")"); |
83 | MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 0 "); | 87 | MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 0 "); |
84 | 88 | ||
89 | MODULE_PARM_DESC(lro_max_aggr, " LRO: Max packets to be aggregated. Default = " | ||
90 | __MODULE_STRING(EHEA_LRO_MAX_AGGR)); | ||
91 | MODULE_PARM_DESC(use_lro, " Large Receive Offload, 1: enable, 0: disable, " | ||
92 | "Default = 0"); | ||
93 | |||
85 | static int port_name_cnt = 0; | 94 | static int port_name_cnt = 0; |
86 | static LIST_HEAD(adapter_list); | 95 | static LIST_HEAD(adapter_list); |
87 | u64 ehea_driver_flags = 0; | 96 | u64 ehea_driver_flags = 0; |
@@ -393,6 +402,60 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq, | |||
393 | return 0; | 402 | return 0; |
394 | } | 403 | } |
395 | 404 | ||
405 | static int get_skb_hdr(struct sk_buff *skb, void **iphdr, | ||
406 | void **tcph, u64 *hdr_flags, void *priv) | ||
407 | { | ||
408 | struct ehea_cqe *cqe = priv; | ||
409 | unsigned int ip_len; | ||
410 | struct iphdr *iph; | ||
411 | |||
412 | /* non tcp/udp packets */ | ||
413 | if (!cqe->header_length) | ||
414 | return -1; | ||
415 | |||
416 | /* non tcp packet */ | ||
417 | skb_reset_network_header(skb); | ||
418 | iph = ip_hdr(skb); | ||
419 | if (iph->protocol != IPPROTO_TCP) | ||
420 | return -1; | ||
421 | |||
422 | ip_len = ip_hdrlen(skb); | ||
423 | skb_set_transport_header(skb, ip_len); | ||
424 | *tcph = tcp_hdr(skb); | ||
425 | |||
426 | /* check if ip header and tcp header are complete */ | ||
427 | if (iph->tot_len < ip_len + tcp_hdrlen(skb)) | ||
428 | return -1; | ||
429 | |||
430 | *hdr_flags = LRO_IPV4 | LRO_TCP; | ||
431 | *iphdr = iph; | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static void ehea_proc_skb(struct ehea_port_res *pr, struct ehea_cqe *cqe, | ||
437 | struct sk_buff *skb) | ||
438 | { | ||
439 | int vlan_extracted = (cqe->status & EHEA_CQE_VLAN_TAG_XTRACT) | ||
440 | && pr->port->vgrp; | ||
441 | |||
442 | if (use_lro) { | ||
443 | if (vlan_extracted) | ||
444 | lro_vlan_hwaccel_receive_skb(&pr->lro_mgr, skb, | ||
445 | pr->port->vgrp, | ||
446 | cqe->vlan_tag, | ||
447 | cqe); | ||
448 | else | ||
449 | lro_receive_skb(&pr->lro_mgr, skb, cqe); | ||
450 | } else { | ||
451 | if (vlan_extracted) | ||
452 | vlan_hwaccel_receive_skb(skb, pr->port->vgrp, | ||
453 | cqe->vlan_tag); | ||
454 | else | ||
455 | netif_receive_skb(skb); | ||
456 | } | ||
457 | } | ||
458 | |||
396 | static int ehea_proc_rwqes(struct net_device *dev, | 459 | static int ehea_proc_rwqes(struct net_device *dev, |
397 | struct ehea_port_res *pr, | 460 | struct ehea_port_res *pr, |
398 | int budget) | 461 | int budget) |
@@ -462,13 +525,7 @@ static int ehea_proc_rwqes(struct net_device *dev, | |||
462 | processed_rq3++; | 525 | processed_rq3++; |
463 | } | 526 | } |
464 | 527 | ||
465 | if ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT) | 528 | ehea_proc_skb(pr, cqe, skb); |
466 | && port->vgrp) | ||
467 | vlan_hwaccel_receive_skb(skb, port->vgrp, | ||
468 | cqe->vlan_tag); | ||
469 | else | ||
470 | netif_receive_skb(skb); | ||
471 | |||
472 | dev->last_rx = jiffies; | 529 | dev->last_rx = jiffies; |
473 | } else { | 530 | } else { |
474 | pr->p_stats.poll_receive_errors++; | 531 | pr->p_stats.poll_receive_errors++; |
@@ -480,6 +537,8 @@ static int ehea_proc_rwqes(struct net_device *dev, | |||
480 | } | 537 | } |
481 | cqe = ehea_poll_rq1(qp, &wqe_index); | 538 | cqe = ehea_poll_rq1(qp, &wqe_index); |
482 | } | 539 | } |
540 | if (use_lro) | ||
541 | lro_flush_all(&pr->lro_mgr); | ||
483 | 542 | ||
484 | pr->rx_packets += processed; | 543 | pr->rx_packets += processed; |
485 | 544 | ||
@@ -1231,6 +1290,15 @@ static int ehea_init_port_res(struct ehea_port *port, struct ehea_port_res *pr, | |||
1231 | 1290 | ||
1232 | netif_napi_add(pr->port->netdev, &pr->napi, ehea_poll, 64); | 1291 | netif_napi_add(pr->port->netdev, &pr->napi, ehea_poll, 64); |
1233 | 1292 | ||
1293 | pr->lro_mgr.max_aggr = pr->port->lro_max_aggr; | ||
1294 | pr->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS; | ||
1295 | pr->lro_mgr.lro_arr = pr->lro_desc; | ||
1296 | pr->lro_mgr.get_skb_header = get_skb_hdr; | ||
1297 | pr->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID; | ||
1298 | pr->lro_mgr.dev = port->netdev; | ||
1299 | pr->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY; | ||
1300 | pr->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; | ||
1301 | |||
1234 | ret = 0; | 1302 | ret = 0; |
1235 | goto out; | 1303 | goto out; |
1236 | 1304 | ||
@@ -2682,6 +2750,8 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, | |||
2682 | goto out_dereg_bc; | 2750 | goto out_dereg_bc; |
2683 | } | 2751 | } |
2684 | 2752 | ||
2753 | port->lro_max_aggr = lro_max_aggr; | ||
2754 | |||
2685 | ret = ehea_get_jumboframe_status(port, &jumbo); | 2755 | ret = ehea_get_jumboframe_status(port, &jumbo); |
2686 | if (ret) | 2756 | if (ret) |
2687 | ehea_error("failed determining jumbo frame status for %s", | 2757 | ehea_error("failed determining jumbo frame status for %s", |