Loading drivers/s390/net/qeth_core.h +0 −1 Original line number Diff line number Diff line Loading @@ -1004,7 +1004,6 @@ int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *, int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long), void *reply_param); unsigned int qeth_count_elements(struct sk_buff *skb, unsigned int data_offset); int qeth_get_elements_for_frags(struct sk_buff *); int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, struct sk_buff *skb, struct qeth_hdr *hdr, unsigned int offset, unsigned int hd_len); Loading drivers/s390/net/qeth_core_main.c +1 −2 Original line number Diff line number Diff line Loading @@ -3788,7 +3788,7 @@ EXPORT_SYMBOL_GPL(qeth_get_priority_queue); * Returns the number of pages, and thus QDIO buffer elements, needed to cover * fragmented part of the SKB. Returns zero for linear SKB. */ int qeth_get_elements_for_frags(struct sk_buff *skb) static int qeth_get_elements_for_frags(struct sk_buff *skb) { int cnt, elements = 0; Loading @@ -3801,7 +3801,6 @@ int qeth_get_elements_for_frags(struct sk_buff *skb) } return elements; } EXPORT_SYMBOL_GPL(qeth_get_elements_for_frags); /** * qeth_count_elements() - Counts the number of QDIO buffer elements needed Loading drivers/s390/net/qeth_l3_main.c +5 −146 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ #include <net/ipv6.h> #include <net/ip6_route.h> #include <net/ip6_fib.h> #include <net/ip6_checksum.h> #include <net/iucv/af_iucv.h> #include <linux/hashtable.h> Loading Loading @@ -2118,70 +2117,6 @@ static void qeth_l3_fill_tso_ext(struct qeth_hdr_tso *hdr, ext->dg_hdr_len = proto_len; } static void qeth_tso_fill_header(struct qeth_card *card, struct qeth_hdr *qhdr, struct sk_buff *skb) { struct qeth_hdr_tso *hdr = (struct qeth_hdr_tso *)qhdr; struct tcphdr *tcph = tcp_hdr(skb); struct iphdr *iph = ip_hdr(skb); struct ipv6hdr *ip6h = ipv6_hdr(skb); /*set values which are fix for the first approach ...*/ hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso); hdr->ext.imb_hdr_no = 1; hdr->ext.hdr_type = 1; hdr->ext.hdr_version = 1; hdr->ext.hdr_len = 28; /*insert non-fix values */ hdr->ext.mss = skb_shinfo(skb)->gso_size; hdr->ext.dg_hdr_len = (__u16)(ip_hdrlen(skb) + tcp_hdrlen(skb)); hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len - sizeof(struct qeth_hdr_tso)); tcph->check = 0; if (be16_to_cpu(skb->protocol) == ETH_P_IPV6) { ip6h->payload_len = 0; tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, 0, IPPROTO_TCP, 0); } else { /*OSA want us to set these values ...*/ tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, 0, IPPROTO_TCP, 0); iph->tot_len = 0; iph->check = 0; } } /** * qeth_l3_get_elements_no_tso() - find number of SBALEs for skb data for tso * @card: qeth card structure, to check max. elems. * @skb: SKB address * @extra_elems: extra elems needed, to check against max. * * Returns the number of pages, and thus QDIO buffer elements, needed to cover * skb data, including linear part and fragments, but excluding TCP header. * Checks if the result plus extra_elems fits under the limit for the card. * Returns 0 if it does not. * Note: extra_elems is not included in the returned result. */ static int qeth_l3_get_elements_no_tso(struct qeth_card *card, struct sk_buff *skb, int extra_elems) { addr_t start = (addr_t)tcp_hdr(skb) + tcp_hdrlen(skb); addr_t end = (addr_t)skb->data + skb_headlen(skb); int elements = qeth_get_elements_for_frags(skb); if (start != end) elements += qeth_get_elements_for_range(start, end); if ((elements + extra_elems) > QETH_MAX_BUFFER_ELEMENTS(card)) { QETH_DBF_MESSAGE(2, "Invalid size of TSO IP packet (Number=%d / Length=%d). Discarded.\n", elements + extra_elems, skb->len); return 0; } return elements; } static void qeth_l3_fixup_headers(struct sk_buff *skb) { struct iphdr *iph = ip_hdr(skb); Loading @@ -2196,9 +2131,8 @@ static void qeth_l3_fixup_headers(struct sk_buff *skb) } } static int qeth_l3_xmit_offload(struct qeth_card *card, struct sk_buff *skb, struct qeth_qdio_out_q *queue, int ipv, int cast_type) static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb, struct qeth_qdio_out_q *queue, int ipv, int cast_type) { unsigned int hw_hdr_len, proto_len, frame_len, elements; unsigned char eth_hdr[ETH_HLEN]; Loading Loading @@ -2282,81 +2216,6 @@ static int qeth_l3_xmit_offload(struct qeth_card *card, struct sk_buff *skb, return rc; } static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb, struct qeth_qdio_out_q *queue, int ipv, int cast_type) { struct qeth_hdr *hdr = NULL; struct sk_buff *new_skb = NULL; int tx_bytes = skb->len; unsigned int hd_len; int elements, rc; bool is_sg; /* create a clone with writeable headroom */ new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr_tso)); if (!new_skb) return -ENOMEM; skb_pull(new_skb, ETH_HLEN); /* fix hardware limitation: as long as we do not have sbal * chaining we can not send long frag lists */ if (!qeth_l3_get_elements_no_tso(card, new_skb, 1)) { rc = skb_linearize(new_skb); if (card->options.performance_stats) { if (rc) card->perf_stats.tx_linfail++; else card->perf_stats.tx_lin++; } if (rc) goto out; } hdr = skb_push(new_skb, sizeof(struct qeth_hdr_tso)); memset(hdr, 0, sizeof(struct qeth_hdr_tso)); qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type, new_skb->len - sizeof(struct qeth_hdr_tso)); qeth_tso_fill_header(card, hdr, new_skb); elements = qeth_l3_get_elements_no_tso(card, new_skb, 1); if (!elements) { rc = -E2BIG; goto out; } elements++; hd_len = sizeof(struct qeth_hdr_tso) + ip_hdrlen(new_skb) + tcp_hdrlen(new_skb); if (qeth_hdr_chk_and_bounce(new_skb, &hdr, hd_len)) { rc = -EINVAL; goto out; } is_sg = skb_is_nonlinear(new_skb); rc = qeth_do_send_packet(card, queue, new_skb, hdr, hd_len, hd_len, elements); out: if (!rc) { if (new_skb != skb) dev_kfree_skb_any(skb); if (card->options.performance_stats) { card->perf_stats.buf_elements_sent += elements; if (is_sg) card->perf_stats.sg_skbs_sent++; card->perf_stats.large_send_bytes += tx_bytes; card->perf_stats.large_send_cnt++; } } else { if (new_skb != skb) dev_kfree_skb_any(new_skb); } return rc; } static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { Loading Loading @@ -2392,9 +2251,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, } netif_stop_queue(dev); if (IS_IQD(card) || (!skb_is_gso(skb) && ipv == 4)) rc = qeth_l3_xmit_offload(card, skb, queue, ipv, cast_type); else if (skb_is_gso(skb)) if (ipv == 4 || IS_IQD(card)) rc = qeth_l3_xmit(card, skb, queue, ipv, cast_type); else rc = qeth_xmit(card, skb, queue, ipv, cast_type, Loading Loading @@ -2560,6 +2417,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) card->dev->needed_headroom = sizeof(struct qeth_hdr); /* allow for de-acceleration of NETIF_F_HW_VLAN_CTAG_TX: */ card->dev->needed_headroom += VLAN_HLEN; if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) card->dev->needed_headroom = sizeof(struct qeth_hdr_tso); /*IPv6 address autoconfiguration stuff*/ qeth_l3_get_unique_id(card); Loading Loading
drivers/s390/net/qeth_core.h +0 −1 Original line number Diff line number Diff line Loading @@ -1004,7 +1004,6 @@ int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *, int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long), void *reply_param); unsigned int qeth_count_elements(struct sk_buff *skb, unsigned int data_offset); int qeth_get_elements_for_frags(struct sk_buff *); int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, struct sk_buff *skb, struct qeth_hdr *hdr, unsigned int offset, unsigned int hd_len); Loading
drivers/s390/net/qeth_core_main.c +1 −2 Original line number Diff line number Diff line Loading @@ -3788,7 +3788,7 @@ EXPORT_SYMBOL_GPL(qeth_get_priority_queue); * Returns the number of pages, and thus QDIO buffer elements, needed to cover * fragmented part of the SKB. Returns zero for linear SKB. */ int qeth_get_elements_for_frags(struct sk_buff *skb) static int qeth_get_elements_for_frags(struct sk_buff *skb) { int cnt, elements = 0; Loading @@ -3801,7 +3801,6 @@ int qeth_get_elements_for_frags(struct sk_buff *skb) } return elements; } EXPORT_SYMBOL_GPL(qeth_get_elements_for_frags); /** * qeth_count_elements() - Counts the number of QDIO buffer elements needed Loading
drivers/s390/net/qeth_l3_main.c +5 −146 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ #include <net/ipv6.h> #include <net/ip6_route.h> #include <net/ip6_fib.h> #include <net/ip6_checksum.h> #include <net/iucv/af_iucv.h> #include <linux/hashtable.h> Loading Loading @@ -2118,70 +2117,6 @@ static void qeth_l3_fill_tso_ext(struct qeth_hdr_tso *hdr, ext->dg_hdr_len = proto_len; } static void qeth_tso_fill_header(struct qeth_card *card, struct qeth_hdr *qhdr, struct sk_buff *skb) { struct qeth_hdr_tso *hdr = (struct qeth_hdr_tso *)qhdr; struct tcphdr *tcph = tcp_hdr(skb); struct iphdr *iph = ip_hdr(skb); struct ipv6hdr *ip6h = ipv6_hdr(skb); /*set values which are fix for the first approach ...*/ hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso); hdr->ext.imb_hdr_no = 1; hdr->ext.hdr_type = 1; hdr->ext.hdr_version = 1; hdr->ext.hdr_len = 28; /*insert non-fix values */ hdr->ext.mss = skb_shinfo(skb)->gso_size; hdr->ext.dg_hdr_len = (__u16)(ip_hdrlen(skb) + tcp_hdrlen(skb)); hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len - sizeof(struct qeth_hdr_tso)); tcph->check = 0; if (be16_to_cpu(skb->protocol) == ETH_P_IPV6) { ip6h->payload_len = 0; tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, 0, IPPROTO_TCP, 0); } else { /*OSA want us to set these values ...*/ tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, 0, IPPROTO_TCP, 0); iph->tot_len = 0; iph->check = 0; } } /** * qeth_l3_get_elements_no_tso() - find number of SBALEs for skb data for tso * @card: qeth card structure, to check max. elems. * @skb: SKB address * @extra_elems: extra elems needed, to check against max. * * Returns the number of pages, and thus QDIO buffer elements, needed to cover * skb data, including linear part and fragments, but excluding TCP header. * Checks if the result plus extra_elems fits under the limit for the card. * Returns 0 if it does not. * Note: extra_elems is not included in the returned result. */ static int qeth_l3_get_elements_no_tso(struct qeth_card *card, struct sk_buff *skb, int extra_elems) { addr_t start = (addr_t)tcp_hdr(skb) + tcp_hdrlen(skb); addr_t end = (addr_t)skb->data + skb_headlen(skb); int elements = qeth_get_elements_for_frags(skb); if (start != end) elements += qeth_get_elements_for_range(start, end); if ((elements + extra_elems) > QETH_MAX_BUFFER_ELEMENTS(card)) { QETH_DBF_MESSAGE(2, "Invalid size of TSO IP packet (Number=%d / Length=%d). Discarded.\n", elements + extra_elems, skb->len); return 0; } return elements; } static void qeth_l3_fixup_headers(struct sk_buff *skb) { struct iphdr *iph = ip_hdr(skb); Loading @@ -2196,9 +2131,8 @@ static void qeth_l3_fixup_headers(struct sk_buff *skb) } } static int qeth_l3_xmit_offload(struct qeth_card *card, struct sk_buff *skb, struct qeth_qdio_out_q *queue, int ipv, int cast_type) static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb, struct qeth_qdio_out_q *queue, int ipv, int cast_type) { unsigned int hw_hdr_len, proto_len, frame_len, elements; unsigned char eth_hdr[ETH_HLEN]; Loading Loading @@ -2282,81 +2216,6 @@ static int qeth_l3_xmit_offload(struct qeth_card *card, struct sk_buff *skb, return rc; } static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb, struct qeth_qdio_out_q *queue, int ipv, int cast_type) { struct qeth_hdr *hdr = NULL; struct sk_buff *new_skb = NULL; int tx_bytes = skb->len; unsigned int hd_len; int elements, rc; bool is_sg; /* create a clone with writeable headroom */ new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr_tso)); if (!new_skb) return -ENOMEM; skb_pull(new_skb, ETH_HLEN); /* fix hardware limitation: as long as we do not have sbal * chaining we can not send long frag lists */ if (!qeth_l3_get_elements_no_tso(card, new_skb, 1)) { rc = skb_linearize(new_skb); if (card->options.performance_stats) { if (rc) card->perf_stats.tx_linfail++; else card->perf_stats.tx_lin++; } if (rc) goto out; } hdr = skb_push(new_skb, sizeof(struct qeth_hdr_tso)); memset(hdr, 0, sizeof(struct qeth_hdr_tso)); qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type, new_skb->len - sizeof(struct qeth_hdr_tso)); qeth_tso_fill_header(card, hdr, new_skb); elements = qeth_l3_get_elements_no_tso(card, new_skb, 1); if (!elements) { rc = -E2BIG; goto out; } elements++; hd_len = sizeof(struct qeth_hdr_tso) + ip_hdrlen(new_skb) + tcp_hdrlen(new_skb); if (qeth_hdr_chk_and_bounce(new_skb, &hdr, hd_len)) { rc = -EINVAL; goto out; } is_sg = skb_is_nonlinear(new_skb); rc = qeth_do_send_packet(card, queue, new_skb, hdr, hd_len, hd_len, elements); out: if (!rc) { if (new_skb != skb) dev_kfree_skb_any(skb); if (card->options.performance_stats) { card->perf_stats.buf_elements_sent += elements; if (is_sg) card->perf_stats.sg_skbs_sent++; card->perf_stats.large_send_bytes += tx_bytes; card->perf_stats.large_send_cnt++; } } else { if (new_skb != skb) dev_kfree_skb_any(new_skb); } return rc; } static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { Loading Loading @@ -2392,9 +2251,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, } netif_stop_queue(dev); if (IS_IQD(card) || (!skb_is_gso(skb) && ipv == 4)) rc = qeth_l3_xmit_offload(card, skb, queue, ipv, cast_type); else if (skb_is_gso(skb)) if (ipv == 4 || IS_IQD(card)) rc = qeth_l3_xmit(card, skb, queue, ipv, cast_type); else rc = qeth_xmit(card, skb, queue, ipv, cast_type, Loading Loading @@ -2560,6 +2417,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) card->dev->needed_headroom = sizeof(struct qeth_hdr); /* allow for de-acceleration of NETIF_F_HW_VLAN_CTAG_TX: */ card->dev->needed_headroom += VLAN_HLEN; if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) card->dev->needed_headroom = sizeof(struct qeth_hdr_tso); /*IPv6 address autoconfiguration stuff*/ qeth_l3_get_unique_id(card); Loading