diff options
author | David S. Miller <davem@davemloft.net> | 2008-05-29 06:31:03 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-05-29 06:31:03 -0400 |
commit | a5b17df04c4ad8f25fc598fce37fccb4b387c94c (patch) | |
tree | 2d0084f6db86362eb067b617ff8470f255ba37e7 /drivers/net/cxgb3/sge.c | |
parent | b79eeeb9e48457579cb742cd02e162fcd673c4a3 (diff) | |
parent | c03571a3e22b821e5be7bda7b166c4554770f489 (diff) |
Merge branch 'upstream-next-davem' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
Diffstat (limited to 'drivers/net/cxgb3/sge.c')
-rw-r--r-- | drivers/net/cxgb3/sge.c | 391 |
1 files changed, 337 insertions, 54 deletions
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 796eb305cdc3..a96331c875e6 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c | |||
@@ -55,6 +55,9 @@ | |||
55 | * directly. | 55 | * directly. |
56 | */ | 56 | */ |
57 | #define FL0_PG_CHUNK_SIZE 2048 | 57 | #define FL0_PG_CHUNK_SIZE 2048 |
58 | #define FL0_PG_ORDER 0 | ||
59 | #define FL1_PG_CHUNK_SIZE (PAGE_SIZE > 8192 ? 16384 : 8192) | ||
60 | #define FL1_PG_ORDER (PAGE_SIZE > 8192 ? 0 : 1) | ||
58 | 61 | ||
59 | #define SGE_RX_DROP_THRES 16 | 62 | #define SGE_RX_DROP_THRES 16 |
60 | 63 | ||
@@ -359,7 +362,7 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q) | |||
359 | } | 362 | } |
360 | 363 | ||
361 | if (q->pg_chunk.page) { | 364 | if (q->pg_chunk.page) { |
362 | __free_page(q->pg_chunk.page); | 365 | __free_pages(q->pg_chunk.page, q->order); |
363 | q->pg_chunk.page = NULL; | 366 | q->pg_chunk.page = NULL; |
364 | } | 367 | } |
365 | } | 368 | } |
@@ -376,13 +379,16 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q) | |||
376 | * Add a buffer of the given length to the supplied HW and SW Rx | 379 | * Add a buffer of the given length to the supplied HW and SW Rx |
377 | * descriptors. | 380 | * descriptors. |
378 | */ | 381 | */ |
379 | static inline void add_one_rx_buf(void *va, unsigned int len, | 382 | static inline int add_one_rx_buf(void *va, unsigned int len, |
380 | struct rx_desc *d, struct rx_sw_desc *sd, | 383 | struct rx_desc *d, struct rx_sw_desc *sd, |
381 | unsigned int gen, struct pci_dev *pdev) | 384 | unsigned int gen, struct pci_dev *pdev) |
382 | { | 385 | { |
383 | dma_addr_t mapping; | 386 | dma_addr_t mapping; |
384 | 387 | ||
385 | mapping = pci_map_single(pdev, va, len, PCI_DMA_FROMDEVICE); | 388 | mapping = pci_map_single(pdev, va, len, PCI_DMA_FROMDEVICE); |
389 | if (unlikely(pci_dma_mapping_error(mapping))) | ||
390 | return -ENOMEM; | ||
391 | |||
386 | pci_unmap_addr_set(sd, dma_addr, mapping); | 392 | pci_unmap_addr_set(sd, dma_addr, mapping); |
387 | 393 | ||
388 | d->addr_lo = cpu_to_be32(mapping); | 394 | d->addr_lo = cpu_to_be32(mapping); |
@@ -390,12 +396,14 @@ static inline void add_one_rx_buf(void *va, unsigned int len, | |||
390 | wmb(); | 396 | wmb(); |
391 | d->len_gen = cpu_to_be32(V_FLD_GEN1(gen)); | 397 | d->len_gen = cpu_to_be32(V_FLD_GEN1(gen)); |
392 | d->gen2 = cpu_to_be32(V_FLD_GEN2(gen)); | 398 | d->gen2 = cpu_to_be32(V_FLD_GEN2(gen)); |
399 | return 0; | ||
393 | } | 400 | } |
394 | 401 | ||
395 | static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp) | 402 | static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp, |
403 | unsigned int order) | ||
396 | { | 404 | { |
397 | if (!q->pg_chunk.page) { | 405 | if (!q->pg_chunk.page) { |
398 | q->pg_chunk.page = alloc_page(gfp); | 406 | q->pg_chunk.page = alloc_pages(gfp, order); |
399 | if (unlikely(!q->pg_chunk.page)) | 407 | if (unlikely(!q->pg_chunk.page)) |
400 | return -ENOMEM; | 408 | return -ENOMEM; |
401 | q->pg_chunk.va = page_address(q->pg_chunk.page); | 409 | q->pg_chunk.va = page_address(q->pg_chunk.page); |
@@ -404,7 +412,7 @@ static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp) | |||
404 | sd->pg_chunk = q->pg_chunk; | 412 | sd->pg_chunk = q->pg_chunk; |
405 | 413 | ||
406 | q->pg_chunk.offset += q->buf_size; | 414 | q->pg_chunk.offset += q->buf_size; |
407 | if (q->pg_chunk.offset == PAGE_SIZE) | 415 | if (q->pg_chunk.offset == (PAGE_SIZE << order)) |
408 | q->pg_chunk.page = NULL; | 416 | q->pg_chunk.page = NULL; |
409 | else { | 417 | else { |
410 | q->pg_chunk.va += q->buf_size; | 418 | q->pg_chunk.va += q->buf_size; |
@@ -424,15 +432,18 @@ static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp) | |||
424 | * allocated with the supplied gfp flags. The caller must assure that | 432 | * allocated with the supplied gfp flags. The caller must assure that |
425 | * @n does not exceed the queue's capacity. | 433 | * @n does not exceed the queue's capacity. |
426 | */ | 434 | */ |
427 | static void refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp) | 435 | static int refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp) |
428 | { | 436 | { |
429 | void *buf_start; | 437 | void *buf_start; |
430 | struct rx_sw_desc *sd = &q->sdesc[q->pidx]; | 438 | struct rx_sw_desc *sd = &q->sdesc[q->pidx]; |
431 | struct rx_desc *d = &q->desc[q->pidx]; | 439 | struct rx_desc *d = &q->desc[q->pidx]; |
440 | unsigned int count = 0; | ||
432 | 441 | ||
433 | while (n--) { | 442 | while (n--) { |
443 | int err; | ||
444 | |||
434 | if (q->use_pages) { | 445 | if (q->use_pages) { |
435 | if (unlikely(alloc_pg_chunk(q, sd, gfp))) { | 446 | if (unlikely(alloc_pg_chunk(q, sd, gfp, q->order))) { |
436 | nomem: q->alloc_failed++; | 447 | nomem: q->alloc_failed++; |
437 | break; | 448 | break; |
438 | } | 449 | } |
@@ -447,8 +458,16 @@ nomem: q->alloc_failed++; | |||
447 | buf_start = skb->data; | 458 | buf_start = skb->data; |
448 | } | 459 | } |
449 | 460 | ||
450 | add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen, | 461 | err = add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen, |
451 | adap->pdev); | 462 | adap->pdev); |
463 | if (unlikely(err)) { | ||
464 | if (!q->use_pages) { | ||
465 | kfree_skb(sd->skb); | ||
466 | sd->skb = NULL; | ||
467 | } | ||
468 | break; | ||
469 | } | ||
470 | |||
452 | d++; | 471 | d++; |
453 | sd++; | 472 | sd++; |
454 | if (++q->pidx == q->size) { | 473 | if (++q->pidx == q->size) { |
@@ -458,14 +477,19 @@ nomem: q->alloc_failed++; | |||
458 | d = q->desc; | 477 | d = q->desc; |
459 | } | 478 | } |
460 | q->credits++; | 479 | q->credits++; |
480 | count++; | ||
461 | } | 481 | } |
462 | wmb(); | 482 | wmb(); |
463 | t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id)); | 483 | if (likely(count)) |
484 | t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id)); | ||
485 | |||
486 | return count; | ||
464 | } | 487 | } |
465 | 488 | ||
466 | static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl) | 489 | static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl) |
467 | { | 490 | { |
468 | refill_fl(adap, fl, min(16U, fl->size - fl->credits), GFP_ATOMIC); | 491 | refill_fl(adap, fl, min(16U, fl->size - fl->credits), |
492 | GFP_ATOMIC | __GFP_COMP); | ||
469 | } | 493 | } |
470 | 494 | ||
471 | /** | 495 | /** |
@@ -560,6 +584,8 @@ static void t3_reset_qset(struct sge_qset *q) | |||
560 | memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET); | 584 | memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET); |
561 | q->txq_stopped = 0; | 585 | q->txq_stopped = 0; |
562 | memset(&q->tx_reclaim_timer, 0, sizeof(q->tx_reclaim_timer)); | 586 | memset(&q->tx_reclaim_timer, 0, sizeof(q->tx_reclaim_timer)); |
587 | kfree(q->lro_frag_tbl); | ||
588 | q->lro_nfrags = q->lro_frag_len = 0; | ||
563 | } | 589 | } |
564 | 590 | ||
565 | 591 | ||
@@ -740,19 +766,22 @@ use_orig_buf: | |||
740 | * that are page chunks rather than sk_buffs. | 766 | * that are page chunks rather than sk_buffs. |
741 | */ | 767 | */ |
742 | static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl, | 768 | static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl, |
743 | unsigned int len, unsigned int drop_thres) | 769 | struct sge_rspq *q, unsigned int len, |
770 | unsigned int drop_thres) | ||
744 | { | 771 | { |
745 | struct sk_buff *skb = NULL; | 772 | struct sk_buff *newskb, *skb; |
746 | struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; | 773 | struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; |
747 | 774 | ||
748 | if (len <= SGE_RX_COPY_THRES) { | 775 | newskb = skb = q->pg_skb; |
749 | skb = alloc_skb(len, GFP_ATOMIC); | 776 | |
750 | if (likely(skb != NULL)) { | 777 | if (!skb && (len <= SGE_RX_COPY_THRES)) { |
751 | __skb_put(skb, len); | 778 | newskb = alloc_skb(len, GFP_ATOMIC); |
779 | if (likely(newskb != NULL)) { | ||
780 | __skb_put(newskb, len); | ||
752 | pci_dma_sync_single_for_cpu(adap->pdev, | 781 | pci_dma_sync_single_for_cpu(adap->pdev, |
753 | pci_unmap_addr(sd, dma_addr), len, | 782 | pci_unmap_addr(sd, dma_addr), len, |
754 | PCI_DMA_FROMDEVICE); | 783 | PCI_DMA_FROMDEVICE); |
755 | memcpy(skb->data, sd->pg_chunk.va, len); | 784 | memcpy(newskb->data, sd->pg_chunk.va, len); |
756 | pci_dma_sync_single_for_device(adap->pdev, | 785 | pci_dma_sync_single_for_device(adap->pdev, |
757 | pci_unmap_addr(sd, dma_addr), len, | 786 | pci_unmap_addr(sd, dma_addr), len, |
758 | PCI_DMA_FROMDEVICE); | 787 | PCI_DMA_FROMDEVICE); |
@@ -761,14 +790,16 @@ static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl, | |||
761 | recycle: | 790 | recycle: |
762 | fl->credits--; | 791 | fl->credits--; |
763 | recycle_rx_buf(adap, fl, fl->cidx); | 792 | recycle_rx_buf(adap, fl, fl->cidx); |
764 | return skb; | 793 | q->rx_recycle_buf++; |
794 | return newskb; | ||
765 | } | 795 | } |
766 | 796 | ||
767 | if (unlikely(fl->credits <= drop_thres)) | 797 | if (unlikely(q->rx_recycle_buf || (!skb && fl->credits <= drop_thres))) |
768 | goto recycle; | 798 | goto recycle; |
769 | 799 | ||
770 | skb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC); | 800 | if (!skb) |
771 | if (unlikely(!skb)) { | 801 | newskb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC); |
802 | if (unlikely(!newskb)) { | ||
772 | if (!drop_thres) | 803 | if (!drop_thres) |
773 | return NULL; | 804 | return NULL; |
774 | goto recycle; | 805 | goto recycle; |
@@ -776,21 +807,29 @@ recycle: | |||
776 | 807 | ||
777 | pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), | 808 | pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), |
778 | fl->buf_size, PCI_DMA_FROMDEVICE); | 809 | fl->buf_size, PCI_DMA_FROMDEVICE); |
779 | __skb_put(skb, SGE_RX_PULL_LEN); | 810 | if (!skb) { |
780 | memcpy(skb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN); | 811 | __skb_put(newskb, SGE_RX_PULL_LEN); |
781 | skb_fill_page_desc(skb, 0, sd->pg_chunk.page, | 812 | memcpy(newskb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN); |
782 | sd->pg_chunk.offset + SGE_RX_PULL_LEN, | 813 | skb_fill_page_desc(newskb, 0, sd->pg_chunk.page, |
783 | len - SGE_RX_PULL_LEN); | 814 | sd->pg_chunk.offset + SGE_RX_PULL_LEN, |
784 | skb->len = len; | 815 | len - SGE_RX_PULL_LEN); |
785 | skb->data_len = len - SGE_RX_PULL_LEN; | 816 | newskb->len = len; |
786 | skb->truesize += skb->data_len; | 817 | newskb->data_len = len - SGE_RX_PULL_LEN; |
818 | } else { | ||
819 | skb_fill_page_desc(newskb, skb_shinfo(newskb)->nr_frags, | ||
820 | sd->pg_chunk.page, | ||
821 | sd->pg_chunk.offset, len); | ||
822 | newskb->len += len; | ||
823 | newskb->data_len += len; | ||
824 | } | ||
825 | newskb->truesize += newskb->data_len; | ||
787 | 826 | ||
788 | fl->credits--; | 827 | fl->credits--; |
789 | /* | 828 | /* |
790 | * We do not refill FLs here, we let the caller do it to overlap a | 829 | * We do not refill FLs here, we let the caller do it to overlap a |
791 | * prefetch. | 830 | * prefetch. |
792 | */ | 831 | */ |
793 | return skb; | 832 | return newskb; |
794 | } | 833 | } |
795 | 834 | ||
796 | /** | 835 | /** |
@@ -1831,9 +1870,10 @@ static void restart_tx(struct sge_qset *qs) | |||
1831 | * if it was immediate data in a response. | 1870 | * if it was immediate data in a response. |
1832 | */ | 1871 | */ |
1833 | static void rx_eth(struct adapter *adap, struct sge_rspq *rq, | 1872 | static void rx_eth(struct adapter *adap, struct sge_rspq *rq, |
1834 | struct sk_buff *skb, int pad) | 1873 | struct sk_buff *skb, int pad, int lro) |
1835 | { | 1874 | { |
1836 | struct cpl_rx_pkt *p = (struct cpl_rx_pkt *)(skb->data + pad); | 1875 | struct cpl_rx_pkt *p = (struct cpl_rx_pkt *)(skb->data + pad); |
1876 | struct sge_qset *qs = rspq_to_qset(rq); | ||
1837 | struct port_info *pi; | 1877 | struct port_info *pi; |
1838 | 1878 | ||
1839 | skb_pull(skb, sizeof(*p) + pad); | 1879 | skb_pull(skb, sizeof(*p) + pad); |
@@ -1850,18 +1890,202 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq, | |||
1850 | if (unlikely(p->vlan_valid)) { | 1890 | if (unlikely(p->vlan_valid)) { |
1851 | struct vlan_group *grp = pi->vlan_grp; | 1891 | struct vlan_group *grp = pi->vlan_grp; |
1852 | 1892 | ||
1853 | rspq_to_qset(rq)->port_stats[SGE_PSTAT_VLANEX]++; | 1893 | qs->port_stats[SGE_PSTAT_VLANEX]++; |
1854 | if (likely(grp)) | 1894 | if (likely(grp)) |
1855 | __vlan_hwaccel_rx(skb, grp, ntohs(p->vlan), | 1895 | if (lro) |
1856 | rq->polling); | 1896 | lro_vlan_hwaccel_receive_skb(&qs->lro_mgr, skb, |
1897 | grp, | ||
1898 | ntohs(p->vlan), | ||
1899 | p); | ||
1900 | else | ||
1901 | __vlan_hwaccel_rx(skb, grp, ntohs(p->vlan), | ||
1902 | rq->polling); | ||
1857 | else | 1903 | else |
1858 | dev_kfree_skb_any(skb); | 1904 | dev_kfree_skb_any(skb); |
1859 | } else if (rq->polling) | 1905 | } else if (rq->polling) { |
1860 | netif_receive_skb(skb); | 1906 | if (lro) |
1861 | else | 1907 | lro_receive_skb(&qs->lro_mgr, skb, p); |
1908 | else | ||
1909 | netif_receive_skb(skb); | ||
1910 | } else | ||
1862 | netif_rx(skb); | 1911 | netif_rx(skb); |
1863 | } | 1912 | } |
1864 | 1913 | ||
1914 | static inline int is_eth_tcp(u32 rss) | ||
1915 | { | ||
1916 | return G_HASHTYPE(ntohl(rss)) == RSS_HASH_4_TUPLE; | ||
1917 | } | ||
1918 | |||
1919 | /** | ||
1920 | * lro_frame_ok - check if an ingress packet is eligible for LRO | ||
1921 | * @p: the CPL header of the packet | ||
1922 | * | ||
1923 | * Returns true if a received packet is eligible for LRO. | ||
1924 | * The following conditions must be true: | ||
1925 | * - packet is TCP/IP Ethernet II (checked elsewhere) | ||
1926 | * - not an IP fragment | ||
1927 | * - no IP options | ||
1928 | * - TCP/IP checksums are correct | ||
1929 | * - the packet is for this host | ||
1930 | */ | ||
1931 | static inline int lro_frame_ok(const struct cpl_rx_pkt *p) | ||
1932 | { | ||
1933 | const struct ethhdr *eh = (struct ethhdr *)(p + 1); | ||
1934 | const struct iphdr *ih = (struct iphdr *)(eh + 1); | ||
1935 | |||
1936 | return (*((u8 *)p + 1) & 0x90) == 0x10 && p->csum == htons(0xffff) && | ||
1937 | eh->h_proto == htons(ETH_P_IP) && ih->ihl == (sizeof(*ih) >> 2); | ||
1938 | } | ||
1939 | |||
1940 | #define TCP_FLAG_MASK (TCP_FLAG_CWR | TCP_FLAG_ECE | TCP_FLAG_URG |\ | ||
1941 | TCP_FLAG_ACK | TCP_FLAG_PSH | TCP_FLAG_RST |\ | ||
1942 | TCP_FLAG_SYN | TCP_FLAG_FIN) | ||
1943 | #define TSTAMP_WORD ((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |\ | ||
1944 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP) | ||
1945 | |||
1946 | /** | ||
1947 | * lro_segment_ok - check if a TCP segment is eligible for LRO | ||
1948 | * @tcph: the TCP header of the packet | ||
1949 | * | ||
1950 | * Returns true if a TCP packet is eligible for LRO. This requires that | ||
1951 | * the packet have only the ACK flag set and no TCP options besides | ||
1952 | * time stamps. | ||
1953 | */ | ||
1954 | static inline int lro_segment_ok(const struct tcphdr *tcph) | ||
1955 | { | ||
1956 | int optlen; | ||
1957 | |||
1958 | if (unlikely((tcp_flag_word(tcph) & TCP_FLAG_MASK) != TCP_FLAG_ACK)) | ||
1959 | return 0; | ||
1960 | |||
1961 | optlen = (tcph->doff << 2) - sizeof(*tcph); | ||
1962 | if (optlen) { | ||
1963 | const u32 *opt = (const u32 *)(tcph + 1); | ||
1964 | |||
1965 | if (optlen != TCPOLEN_TSTAMP_ALIGNED || | ||
1966 | *opt != htonl(TSTAMP_WORD) || !opt[2]) | ||
1967 | return 0; | ||
1968 | } | ||
1969 | return 1; | ||
1970 | } | ||
1971 | |||
1972 | static int t3_get_lro_header(void **eh, void **iph, void **tcph, | ||
1973 | u64 *hdr_flags, void *priv) | ||
1974 | { | ||
1975 | const struct cpl_rx_pkt *cpl = priv; | ||
1976 | |||
1977 | if (!lro_frame_ok(cpl)) | ||
1978 | return -1; | ||
1979 | |||
1980 | *eh = (struct ethhdr *)(cpl + 1); | ||
1981 | *iph = (struct iphdr *)((struct ethhdr *)*eh + 1); | ||
1982 | *tcph = (struct tcphdr *)((struct iphdr *)*iph + 1); | ||
1983 | |||
1984 | if (!lro_segment_ok(*tcph)) | ||
1985 | return -1; | ||
1986 | |||
1987 | *hdr_flags = LRO_IPV4 | LRO_TCP; | ||
1988 | return 0; | ||
1989 | } | ||
1990 | |||
1991 | static int t3_get_skb_header(struct sk_buff *skb, | ||
1992 | void **iph, void **tcph, u64 *hdr_flags, | ||
1993 | void *priv) | ||
1994 | { | ||
1995 | void *eh; | ||
1996 | |||
1997 | return t3_get_lro_header(&eh, iph, tcph, hdr_flags, priv); | ||
1998 | } | ||
1999 | |||
2000 | static int t3_get_frag_header(struct skb_frag_struct *frag, void **eh, | ||
2001 | void **iph, void **tcph, u64 *hdr_flags, | ||
2002 | void *priv) | ||
2003 | { | ||
2004 | return t3_get_lro_header(eh, iph, tcph, hdr_flags, priv); | ||
2005 | } | ||
2006 | |||
2007 | /** | ||
2008 | * lro_add_page - add a page chunk to an LRO session | ||
2009 | * @adap: the adapter | ||
2010 | * @qs: the associated queue set | ||
2011 | * @fl: the free list containing the page chunk to add | ||
2012 | * @len: packet length | ||
2013 | * @complete: Indicates the last fragment of a frame | ||
2014 | * | ||
2015 | * Add a received packet contained in a page chunk to an existing LRO | ||
2016 | * session. | ||
2017 | */ | ||
2018 | static void lro_add_page(struct adapter *adap, struct sge_qset *qs, | ||
2019 | struct sge_fl *fl, int len, int complete) | ||
2020 | { | ||
2021 | struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; | ||
2022 | struct cpl_rx_pkt *cpl; | ||
2023 | struct skb_frag_struct *rx_frag = qs->lro_frag_tbl; | ||
2024 | int nr_frags = qs->lro_nfrags, frag_len = qs->lro_frag_len; | ||
2025 | int offset = 0; | ||
2026 | |||
2027 | if (!nr_frags) { | ||
2028 | offset = 2 + sizeof(struct cpl_rx_pkt); | ||
2029 | qs->lro_va = cpl = sd->pg_chunk.va + 2; | ||
2030 | } | ||
2031 | |||
2032 | fl->credits--; | ||
2033 | |||
2034 | len -= offset; | ||
2035 | pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), | ||
2036 | fl->buf_size, PCI_DMA_FROMDEVICE); | ||
2037 | |||
2038 | rx_frag += nr_frags; | ||
2039 | rx_frag->page = sd->pg_chunk.page; | ||
2040 | rx_frag->page_offset = sd->pg_chunk.offset + offset; | ||
2041 | rx_frag->size = len; | ||
2042 | frag_len += len; | ||
2043 | qs->lro_nfrags++; | ||
2044 | qs->lro_frag_len = frag_len; | ||
2045 | |||
2046 | if (!complete) | ||
2047 | return; | ||
2048 | |||
2049 | qs->lro_nfrags = qs->lro_frag_len = 0; | ||
2050 | cpl = qs->lro_va; | ||
2051 | |||
2052 | if (unlikely(cpl->vlan_valid)) { | ||
2053 | struct net_device *dev = qs->netdev; | ||
2054 | struct port_info *pi = netdev_priv(dev); | ||
2055 | struct vlan_group *grp = pi->vlan_grp; | ||
2056 | |||
2057 | if (likely(grp != NULL)) { | ||
2058 | lro_vlan_hwaccel_receive_frags(&qs->lro_mgr, | ||
2059 | qs->lro_frag_tbl, | ||
2060 | frag_len, frag_len, | ||
2061 | grp, ntohs(cpl->vlan), | ||
2062 | cpl, 0); | ||
2063 | return; | ||
2064 | } | ||
2065 | } | ||
2066 | lro_receive_frags(&qs->lro_mgr, qs->lro_frag_tbl, | ||
2067 | frag_len, frag_len, cpl, 0); | ||
2068 | } | ||
2069 | |||
2070 | /** | ||
2071 | * init_lro_mgr - initialize a LRO manager object | ||
2072 | * @lro_mgr: the LRO manager object | ||
2073 | */ | ||
2074 | static void init_lro_mgr(struct sge_qset *qs, struct net_lro_mgr *lro_mgr) | ||
2075 | { | ||
2076 | lro_mgr->dev = qs->netdev; | ||
2077 | lro_mgr->features = LRO_F_NAPI; | ||
2078 | lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; | ||
2079 | lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; | ||
2080 | lro_mgr->max_desc = T3_MAX_LRO_SES; | ||
2081 | lro_mgr->lro_arr = qs->lro_desc; | ||
2082 | lro_mgr->get_frag_header = t3_get_frag_header; | ||
2083 | lro_mgr->get_skb_header = t3_get_skb_header; | ||
2084 | lro_mgr->max_aggr = T3_MAX_LRO_MAX_PKTS; | ||
2085 | if (lro_mgr->max_aggr > MAX_SKB_FRAGS) | ||
2086 | lro_mgr->max_aggr = MAX_SKB_FRAGS; | ||
2087 | } | ||
2088 | |||
1865 | /** | 2089 | /** |
1866 | * handle_rsp_cntrl_info - handles control information in a response | 2090 | * handle_rsp_cntrl_info - handles control information in a response |
1867 | * @qs: the queue set corresponding to the response | 2091 | * @qs: the queue set corresponding to the response |
@@ -1947,6 +2171,12 @@ static inline int is_new_response(const struct rsp_desc *r, | |||
1947 | return (r->intr_gen & F_RSPD_GEN2) == q->gen; | 2171 | return (r->intr_gen & F_RSPD_GEN2) == q->gen; |
1948 | } | 2172 | } |
1949 | 2173 | ||
2174 | static inline void clear_rspq_bufstate(struct sge_rspq * const q) | ||
2175 | { | ||
2176 | q->pg_skb = NULL; | ||
2177 | q->rx_recycle_buf = 0; | ||
2178 | } | ||
2179 | |||
1950 | #define RSPD_GTS_MASK (F_RSPD_TXQ0_GTS | F_RSPD_TXQ1_GTS) | 2180 | #define RSPD_GTS_MASK (F_RSPD_TXQ0_GTS | F_RSPD_TXQ1_GTS) |
1951 | #define RSPD_CTRL_MASK (RSPD_GTS_MASK | \ | 2181 | #define RSPD_CTRL_MASK (RSPD_GTS_MASK | \ |
1952 | V_RSPD_TXQ0_CR(M_RSPD_TXQ0_CR) | \ | 2182 | V_RSPD_TXQ0_CR(M_RSPD_TXQ0_CR) | \ |
@@ -1984,10 +2214,11 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs, | |||
1984 | q->next_holdoff = q->holdoff_tmr; | 2214 | q->next_holdoff = q->holdoff_tmr; |
1985 | 2215 | ||
1986 | while (likely(budget_left && is_new_response(r, q))) { | 2216 | while (likely(budget_left && is_new_response(r, q))) { |
1987 | int eth, ethpad = 2; | 2217 | int packet_complete, eth, ethpad = 2, lro = qs->lro_enabled; |
1988 | struct sk_buff *skb = NULL; | 2218 | struct sk_buff *skb = NULL; |
1989 | u32 len, flags = ntohl(r->flags); | 2219 | u32 len, flags = ntohl(r->flags); |
1990 | __be32 rss_hi = *(const __be32 *)r, rss_lo = r->rss_hdr.rss_hash_val; | 2220 | __be32 rss_hi = *(const __be32 *)r, |
2221 | rss_lo = r->rss_hdr.rss_hash_val; | ||
1991 | 2222 | ||
1992 | eth = r->rss_hdr.opcode == CPL_RX_PKT; | 2223 | eth = r->rss_hdr.opcode == CPL_RX_PKT; |
1993 | 2224 | ||
@@ -2015,6 +2246,9 @@ no_mem: | |||
2015 | } else if ((len = ntohl(r->len_cq)) != 0) { | 2246 | } else if ((len = ntohl(r->len_cq)) != 0) { |
2016 | struct sge_fl *fl; | 2247 | struct sge_fl *fl; |
2017 | 2248 | ||
2249 | if (eth) | ||
2250 | lro = qs->lro_enabled && is_eth_tcp(rss_hi); | ||
2251 | |||
2018 | fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0]; | 2252 | fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0]; |
2019 | if (fl->use_pages) { | 2253 | if (fl->use_pages) { |
2020 | void *addr = fl->sdesc[fl->cidx].pg_chunk.va; | 2254 | void *addr = fl->sdesc[fl->cidx].pg_chunk.va; |
@@ -2024,9 +2258,18 @@ no_mem: | |||
2024 | prefetch(addr + L1_CACHE_BYTES); | 2258 | prefetch(addr + L1_CACHE_BYTES); |
2025 | #endif | 2259 | #endif |
2026 | __refill_fl(adap, fl); | 2260 | __refill_fl(adap, fl); |
2261 | if (lro > 0) { | ||
2262 | lro_add_page(adap, qs, fl, | ||
2263 | G_RSPD_LEN(len), | ||
2264 | flags & F_RSPD_EOP); | ||
2265 | goto next_fl; | ||
2266 | } | ||
2027 | 2267 | ||
2028 | skb = get_packet_pg(adap, fl, G_RSPD_LEN(len), | 2268 | skb = get_packet_pg(adap, fl, q, |
2029 | eth ? SGE_RX_DROP_THRES : 0); | 2269 | G_RSPD_LEN(len), |
2270 | eth ? | ||
2271 | SGE_RX_DROP_THRES : 0); | ||
2272 | q->pg_skb = skb; | ||
2030 | } else | 2273 | } else |
2031 | skb = get_packet(adap, fl, G_RSPD_LEN(len), | 2274 | skb = get_packet(adap, fl, G_RSPD_LEN(len), |
2032 | eth ? SGE_RX_DROP_THRES : 0); | 2275 | eth ? SGE_RX_DROP_THRES : 0); |
@@ -2036,7 +2279,7 @@ no_mem: | |||
2036 | q->rx_drops++; | 2279 | q->rx_drops++; |
2037 | } else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT)) | 2280 | } else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT)) |
2038 | __skb_pull(skb, 2); | 2281 | __skb_pull(skb, 2); |
2039 | 2282 | next_fl: | |
2040 | if (++fl->cidx == fl->size) | 2283 | if (++fl->cidx == fl->size) |
2041 | fl->cidx = 0; | 2284 | fl->cidx = 0; |
2042 | } else | 2285 | } else |
@@ -2060,9 +2303,13 @@ no_mem: | |||
2060 | q->credits = 0; | 2303 | q->credits = 0; |
2061 | } | 2304 | } |
2062 | 2305 | ||
2063 | if (likely(skb != NULL)) { | 2306 | packet_complete = flags & |
2307 | (F_RSPD_EOP | F_RSPD_IMM_DATA_VALID | | ||
2308 | F_RSPD_ASYNC_NOTIF); | ||
2309 | |||
2310 | if (skb != NULL && packet_complete) { | ||
2064 | if (eth) | 2311 | if (eth) |
2065 | rx_eth(adap, q, skb, ethpad); | 2312 | rx_eth(adap, q, skb, ethpad, lro); |
2066 | else { | 2313 | else { |
2067 | q->offload_pkts++; | 2314 | q->offload_pkts++; |
2068 | /* Preserve the RSS info in csum & priority */ | 2315 | /* Preserve the RSS info in csum & priority */ |
@@ -2072,11 +2319,19 @@ no_mem: | |||
2072 | offload_skbs, | 2319 | offload_skbs, |
2073 | ngathered); | 2320 | ngathered); |
2074 | } | 2321 | } |
2322 | |||
2323 | if (flags & F_RSPD_EOP) | ||
2324 | clear_rspq_bufstate(q); | ||
2075 | } | 2325 | } |
2076 | --budget_left; | 2326 | --budget_left; |
2077 | } | 2327 | } |
2078 | 2328 | ||
2079 | deliver_partial_bundle(&adap->tdev, q, offload_skbs, ngathered); | 2329 | deliver_partial_bundle(&adap->tdev, q, offload_skbs, ngathered); |
2330 | lro_flush_all(&qs->lro_mgr); | ||
2331 | qs->port_stats[SGE_PSTAT_LRO_AGGR] = qs->lro_mgr.stats.aggregated; | ||
2332 | qs->port_stats[SGE_PSTAT_LRO_FLUSHED] = qs->lro_mgr.stats.flushed; | ||
2333 | qs->port_stats[SGE_PSTAT_LRO_NO_DESC] = qs->lro_mgr.stats.no_desc; | ||
2334 | |||
2080 | if (sleeping) | 2335 | if (sleeping) |
2081 | check_ring_db(adap, qs, sleeping); | 2336 | check_ring_db(adap, qs, sleeping); |
2082 | 2337 | ||
@@ -2618,8 +2873,9 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, | |||
2618 | int irq_vec_idx, const struct qset_params *p, | 2873 | int irq_vec_idx, const struct qset_params *p, |
2619 | int ntxq, struct net_device *dev) | 2874 | int ntxq, struct net_device *dev) |
2620 | { | 2875 | { |
2621 | int i, ret = -ENOMEM; | 2876 | int i, avail, ret = -ENOMEM; |
2622 | struct sge_qset *q = &adapter->sge.qs[id]; | 2877 | struct sge_qset *q = &adapter->sge.qs[id]; |
2878 | struct net_lro_mgr *lro_mgr = &q->lro_mgr; | ||
2623 | 2879 | ||
2624 | init_qset_cntxt(q, id); | 2880 | init_qset_cntxt(q, id); |
2625 | init_timer(&q->tx_reclaim_timer); | 2881 | init_timer(&q->tx_reclaim_timer); |
@@ -2687,11 +2943,23 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, | |||
2687 | #else | 2943 | #else |
2688 | q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data); | 2944 | q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data); |
2689 | #endif | 2945 | #endif |
2690 | q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0; | 2946 | #if FL1_PG_CHUNK_SIZE > 0 |
2947 | q->fl[1].buf_size = FL1_PG_CHUNK_SIZE; | ||
2948 | #else | ||
2691 | q->fl[1].buf_size = is_offload(adapter) ? | 2949 | q->fl[1].buf_size = is_offload(adapter) ? |
2692 | (16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) : | 2950 | (16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) : |
2693 | MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt); | 2951 | MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt); |
2952 | #endif | ||
2694 | 2953 | ||
2954 | q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0; | ||
2955 | q->fl[1].use_pages = FL1_PG_CHUNK_SIZE > 0; | ||
2956 | q->fl[0].order = FL0_PG_ORDER; | ||
2957 | q->fl[1].order = FL1_PG_ORDER; | ||
2958 | |||
2959 | q->lro_frag_tbl = kcalloc(MAX_FRAME_SIZE / FL1_PG_CHUNK_SIZE + 1, | ||
2960 | sizeof(struct skb_frag_struct), | ||
2961 | GFP_KERNEL); | ||
2962 | q->lro_nfrags = q->lro_frag_len = 0; | ||
2695 | spin_lock_irq(&adapter->sge.reg_lock); | 2963 | spin_lock_irq(&adapter->sge.reg_lock); |
2696 | 2964 | ||
2697 | /* FL threshold comparison uses < */ | 2965 | /* FL threshold comparison uses < */ |
@@ -2742,8 +3010,23 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, | |||
2742 | q->netdev = dev; | 3010 | q->netdev = dev; |
2743 | t3_update_qset_coalesce(q, p); | 3011 | t3_update_qset_coalesce(q, p); |
2744 | 3012 | ||
2745 | refill_fl(adapter, &q->fl[0], q->fl[0].size, GFP_KERNEL); | 3013 | init_lro_mgr(q, lro_mgr); |
2746 | refill_fl(adapter, &q->fl[1], q->fl[1].size, GFP_KERNEL); | 3014 | |
3015 | avail = refill_fl(adapter, &q->fl[0], q->fl[0].size, | ||
3016 | GFP_KERNEL | __GFP_COMP); | ||
3017 | if (!avail) { | ||
3018 | CH_ALERT(adapter, "free list queue 0 initialization failed\n"); | ||
3019 | goto err; | ||
3020 | } | ||
3021 | if (avail < q->fl[0].size) | ||
3022 | CH_WARN(adapter, "free list queue 0 enabled with %d credits\n", | ||
3023 | avail); | ||
3024 | |||
3025 | avail = refill_fl(adapter, &q->fl[1], q->fl[1].size, | ||
3026 | GFP_KERNEL | __GFP_COMP); | ||
3027 | if (avail < q->fl[1].size) | ||
3028 | CH_WARN(adapter, "free list queue 1 enabled with %d credits\n", | ||
3029 | avail); | ||
2747 | refill_rspq(adapter, &q->rspq, q->rspq.size - 1); | 3030 | refill_rspq(adapter, &q->rspq, q->rspq.size - 1); |
2748 | 3031 | ||
2749 | t3_write_reg(adapter, A_SG_GTS, V_RSPQ(q->rspq.cntxt_id) | | 3032 | t3_write_reg(adapter, A_SG_GTS, V_RSPQ(q->rspq.cntxt_id) | |
@@ -2752,9 +3035,9 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, | |||
2752 | mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); | 3035 | mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); |
2753 | return 0; | 3036 | return 0; |
2754 | 3037 | ||
2755 | err_unlock: | 3038 | err_unlock: |
2756 | spin_unlock_irq(&adapter->sge.reg_lock); | 3039 | spin_unlock_irq(&adapter->sge.reg_lock); |
2757 | err: | 3040 | err: |
2758 | t3_free_qset(adapter, q); | 3041 | t3_free_qset(adapter, q); |
2759 | return ret; | 3042 | return ret; |
2760 | } | 3043 | } |
@@ -2876,7 +3159,7 @@ void t3_sge_prep(struct adapter *adap, struct sge_params *p) | |||
2876 | q->coalesce_usecs = 5; | 3159 | q->coalesce_usecs = 5; |
2877 | q->rspq_size = 1024; | 3160 | q->rspq_size = 1024; |
2878 | q->fl_size = 1024; | 3161 | q->fl_size = 1024; |
2879 | q->jumbo_size = 512; | 3162 | q->jumbo_size = 512; |
2880 | q->txq_size[TXQ_ETH] = 1024; | 3163 | q->txq_size[TXQ_ETH] = 1024; |
2881 | q->txq_size[TXQ_OFLD] = 1024; | 3164 | q->txq_size[TXQ_OFLD] = 1024; |
2882 | q->txq_size[TXQ_CTRL] = 256; | 3165 | q->txq_size[TXQ_CTRL] = 256; |