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 | ||
