diff options
author | David S. Miller <davem@davemloft.net> | 2018-08-23 00:47:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-08-23 00:47:36 -0400 |
commit | 58ce660f911c9fae146a94245efb04b4af6f02a9 (patch) | |
tree | 276d8ca08182631f8b91e4fc9e803a3cc95fce6e | |
parent | 12a7f8696b85aaff3a76cd12a15b101b2af65404 (diff) | |
parent | 339379a2fb13decd1802b403370cc3cdf21d819f (diff) |
Merge branch 'hns-fixes'
Huazhong Tan says:
====================
net: hns: bug fixes & optimization for HNS driver
This patchset presents some bug fixes found out when CONFIG_ARM64_64K_PAGES
enable and an optimization for HNS driver.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/hisilicon/hns/hnae.h | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/hisilicon/hns/hns_enet.c | 108 |
2 files changed, 7 insertions, 107 deletions
diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index fa5b30f547f6..cad52bd331f7 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h | |||
@@ -220,10 +220,10 @@ struct hnae_desc_cb { | |||
220 | 220 | ||
221 | /* priv data for the desc, e.g. skb when use with ip stack*/ | 221 | /* priv data for the desc, e.g. skb when use with ip stack*/ |
222 | void *priv; | 222 | void *priv; |
223 | u16 page_offset; | 223 | u32 page_offset; |
224 | u16 reuse_flag; | 224 | u32 length; /* length of the buffer */ |
225 | 225 | ||
226 | u16 length; /* length of the buffer */ | 226 | u16 reuse_flag; |
227 | 227 | ||
228 | /* desc type, used by the ring user to mark the type of the priv data */ | 228 | /* desc type, used by the ring user to mark the type of the priv data */ |
229 | u16 type; | 229 | u16 type; |
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 9f2b552aee33..02a0ba20fad5 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c | |||
@@ -406,113 +406,13 @@ out_net_tx_busy: | |||
406 | return NETDEV_TX_BUSY; | 406 | return NETDEV_TX_BUSY; |
407 | } | 407 | } |
408 | 408 | ||
409 | /** | ||
410 | * hns_nic_get_headlen - determine size of header for RSC/LRO/GRO/FCOE | ||
411 | * @data: pointer to the start of the headers | ||
412 | * @max: total length of section to find headers in | ||
413 | * | ||
414 | * This function is meant to determine the length of headers that will | ||
415 | * be recognized by hardware for LRO, GRO, and RSC offloads. The main | ||
416 | * motivation of doing this is to only perform one pull for IPv4 TCP | ||
417 | * packets so that we can do basic things like calculating the gso_size | ||
418 | * based on the average data per packet. | ||
419 | **/ | ||
420 | static unsigned int hns_nic_get_headlen(unsigned char *data, u32 flag, | ||
421 | unsigned int max_size) | ||
422 | { | ||
423 | unsigned char *network; | ||
424 | u8 hlen; | ||
425 | |||
426 | /* this should never happen, but better safe than sorry */ | ||
427 | if (max_size < ETH_HLEN) | ||
428 | return max_size; | ||
429 | |||
430 | /* initialize network frame pointer */ | ||
431 | network = data; | ||
432 | |||
433 | /* set first protocol and move network header forward */ | ||
434 | network += ETH_HLEN; | ||
435 | |||
436 | /* handle any vlan tag if present */ | ||
437 | if (hnae_get_field(flag, HNS_RXD_VLAN_M, HNS_RXD_VLAN_S) | ||
438 | == HNS_RX_FLAG_VLAN_PRESENT) { | ||
439 | if ((typeof(max_size))(network - data) > (max_size - VLAN_HLEN)) | ||
440 | return max_size; | ||
441 | |||
442 | network += VLAN_HLEN; | ||
443 | } | ||
444 | |||
445 | /* handle L3 protocols */ | ||
446 | if (hnae_get_field(flag, HNS_RXD_L3ID_M, HNS_RXD_L3ID_S) | ||
447 | == HNS_RX_FLAG_L3ID_IPV4) { | ||
448 | if ((typeof(max_size))(network - data) > | ||
449 | (max_size - sizeof(struct iphdr))) | ||
450 | return max_size; | ||
451 | |||
452 | /* access ihl as a u8 to avoid unaligned access on ia64 */ | ||
453 | hlen = (network[0] & 0x0F) << 2; | ||
454 | |||
455 | /* verify hlen meets minimum size requirements */ | ||
456 | if (hlen < sizeof(struct iphdr)) | ||
457 | return network - data; | ||
458 | |||
459 | /* record next protocol if header is present */ | ||
460 | } else if (hnae_get_field(flag, HNS_RXD_L3ID_M, HNS_RXD_L3ID_S) | ||
461 | == HNS_RX_FLAG_L3ID_IPV6) { | ||
462 | if ((typeof(max_size))(network - data) > | ||
463 | (max_size - sizeof(struct ipv6hdr))) | ||
464 | return max_size; | ||
465 | |||
466 | /* record next protocol */ | ||
467 | hlen = sizeof(struct ipv6hdr); | ||
468 | } else { | ||
469 | return network - data; | ||
470 | } | ||
471 | |||
472 | /* relocate pointer to start of L4 header */ | ||
473 | network += hlen; | ||
474 | |||
475 | /* finally sort out TCP/UDP */ | ||
476 | if (hnae_get_field(flag, HNS_RXD_L4ID_M, HNS_RXD_L4ID_S) | ||
477 | == HNS_RX_FLAG_L4ID_TCP) { | ||
478 | if ((typeof(max_size))(network - data) > | ||
479 | (max_size - sizeof(struct tcphdr))) | ||
480 | return max_size; | ||
481 | |||
482 | /* access doff as a u8 to avoid unaligned access on ia64 */ | ||
483 | hlen = (network[12] & 0xF0) >> 2; | ||
484 | |||
485 | /* verify hlen meets minimum size requirements */ | ||
486 | if (hlen < sizeof(struct tcphdr)) | ||
487 | return network - data; | ||
488 | |||
489 | network += hlen; | ||
490 | } else if (hnae_get_field(flag, HNS_RXD_L4ID_M, HNS_RXD_L4ID_S) | ||
491 | == HNS_RX_FLAG_L4ID_UDP) { | ||
492 | if ((typeof(max_size))(network - data) > | ||
493 | (max_size - sizeof(struct udphdr))) | ||
494 | return max_size; | ||
495 | |||
496 | network += sizeof(struct udphdr); | ||
497 | } | ||
498 | |||
499 | /* If everything has gone correctly network should be the | ||
500 | * data section of the packet and will be the end of the header. | ||
501 | * If not then it probably represents the end of the last recognized | ||
502 | * header. | ||
503 | */ | ||
504 | if ((typeof(max_size))(network - data) < max_size) | ||
505 | return network - data; | ||
506 | else | ||
507 | return max_size; | ||
508 | } | ||
509 | |||
510 | static void hns_nic_reuse_page(struct sk_buff *skb, int i, | 409 | static void hns_nic_reuse_page(struct sk_buff *skb, int i, |
511 | struct hnae_ring *ring, int pull_len, | 410 | struct hnae_ring *ring, int pull_len, |
512 | struct hnae_desc_cb *desc_cb) | 411 | struct hnae_desc_cb *desc_cb) |
513 | { | 412 | { |
514 | struct hnae_desc *desc; | 413 | struct hnae_desc *desc; |
515 | int truesize, size; | 414 | u32 truesize; |
415 | int size; | ||
516 | int last_offset; | 416 | int last_offset; |
517 | bool twobufs; | 417 | bool twobufs; |
518 | 418 | ||
@@ -530,7 +430,7 @@ static void hns_nic_reuse_page(struct sk_buff *skb, int i, | |||
530 | } | 430 | } |
531 | 431 | ||
532 | skb_add_rx_frag(skb, i, desc_cb->priv, desc_cb->page_offset + pull_len, | 432 | skb_add_rx_frag(skb, i, desc_cb->priv, desc_cb->page_offset + pull_len, |
533 | size - pull_len, truesize - pull_len); | 433 | size - pull_len, truesize); |
534 | 434 | ||
535 | /* avoid re-using remote pages,flag default unreuse */ | 435 | /* avoid re-using remote pages,flag default unreuse */ |
536 | if (unlikely(page_to_nid(desc_cb->priv) != numa_node_id())) | 436 | if (unlikely(page_to_nid(desc_cb->priv) != numa_node_id())) |
@@ -695,7 +595,7 @@ static int hns_nic_poll_rx_skb(struct hns_nic_ring_data *ring_data, | |||
695 | } else { | 595 | } else { |
696 | ring->stats.seg_pkt_cnt++; | 596 | ring->stats.seg_pkt_cnt++; |
697 | 597 | ||
698 | pull_len = hns_nic_get_headlen(va, bnum_flag, HNS_RX_HEAD_SIZE); | 598 | pull_len = eth_get_headlen(va, HNS_RX_HEAD_SIZE); |
699 | memcpy(__skb_put(skb, pull_len), va, | 599 | memcpy(__skb_put(skb, pull_len), va, |
700 | ALIGN(pull_len, sizeof(long))); | 600 | ALIGN(pull_len, sizeof(long))); |
701 | 601 | ||