diff options
author | <jgarzik@pretzel.yyz.us> | 2005-05-27 22:07:02 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-05-27 22:07:02 -0400 |
commit | 1f15d694522af9cd7492695f11dd2dc77b6cf098 (patch) | |
tree | 7f67a4c38456ec73359d576a5c602d18c3c3ef72 /drivers/s390/net/qeth_tso.c | |
parent | fff9cfd99c0f88645c3f50d7476d6c8cef99f140 (diff) | |
parent | 254feb882a7c6e4e51416dff6a97d847fbbba551 (diff) |
Automatic merge of /spare/repo/netdev-2.6 branch master
Diffstat (limited to 'drivers/s390/net/qeth_tso.c')
-rw-r--r-- | drivers/s390/net/qeth_tso.c | 285 |
1 files changed, 0 insertions, 285 deletions
diff --git a/drivers/s390/net/qeth_tso.c b/drivers/s390/net/qeth_tso.c deleted file mode 100644 index c91976274e7..00000000000 --- a/drivers/s390/net/qeth_tso.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * linux/drivers/s390/net/qeth_tso.c ($Revision: 1.6 $) - * - * Header file for qeth TCP Segmentation Offload support. - * - * Copyright 2004 IBM Corporation - * - * Author(s): Frank Pavlic <pavlic@de.ibm.com> - * - * $Revision: 1.6 $ $Date: 2005/03/24 09:04:18 $ - * - */ - -#include <linux/skbuff.h> -#include <linux/tcp.h> -#include <linux/ip.h> -#include <linux/ipv6.h> -#include <net/ip6_checksum.h> -#include "qeth.h" -#include "qeth_mpc.h" -#include "qeth_tso.h" - -/** - * skb already partially prepared - * classic qdio header in skb->data - * */ -static inline struct qeth_hdr_tso * -qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb) -{ - int rc = 0; - - QETH_DBF_TEXT(trace, 5, "tsoprsk"); - rc = qeth_realloc_headroom(card, skb,sizeof(struct qeth_hdr_ext_tso)); - if (rc) - return NULL; - - return qeth_push_skb(card, skb, sizeof(struct qeth_hdr_ext_tso)); -} - -/** - * fill header for a TSO packet - */ -static inline void -qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb) -{ - struct qeth_hdr_tso *hdr; - struct tcphdr *tcph; - struct iphdr *iph; - - QETH_DBF_TEXT(trace, 5, "tsofhdr"); - - hdr = (struct qeth_hdr_tso *) skb->data; - iph = skb->nh.iph; - tcph = skb->h.th; - /*fix header to TSO values ...*/ - hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO; - /*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)->tso_size; - hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4); - hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len - - sizeof(struct qeth_hdr_tso)); -} - -/** - * change some header values as requested by hardware - */ -static inline void -qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb) -{ - struct iphdr *iph; - struct ipv6hdr *ip6h; - struct tcphdr *tcph; - - iph = skb->nh.iph; - ip6h = skb->nh.ipv6h; - tcph = skb->h.th; - - tcph->check = 0; - if (skb->protocol == ETH_P_IPV6) { - ip6h->payload_len = 0; - tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, - 0, IPPROTO_TCP, 0); - return; - } - /*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; -} - -static inline struct qeth_hdr_tso * -qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb, - int ipv, int cast_type) -{ - struct qeth_hdr_tso *hdr; - int rc = 0; - - QETH_DBF_TEXT(trace, 5, "tsoprep"); - - /*get headroom for tso qdio header */ - hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb); - if (hdr == NULL) { - QETH_DBF_TEXT_(trace, 4, "2err%d", rc); - return NULL; - } - memset(hdr, 0, sizeof(struct qeth_hdr_tso)); - /*fill first 32 bytes of qdio header as used - *FIXME: TSO has two struct members - * with different names but same size - * */ - qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type); - qeth_tso_fill_header(card, skb); - qeth_tso_set_tcpip_header(card, skb); - return hdr; -} - -static inline int -qeth_tso_get_queue_buffer(struct qeth_qdio_out_q *queue) -{ - struct qeth_qdio_out_buffer *buffer; - int flush_cnt = 0; - - QETH_DBF_TEXT(trace, 5, "tsobuf"); - - /* force to non-packing*/ - if (queue->do_pack) - queue->do_pack = 0; - buffer = &queue->bufs[queue->next_buf_to_fill]; - /* get a new buffer if current is already in use*/ - if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) && - (buffer->next_element_to_fill > 0)) { - atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED); - queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % - QDIO_MAX_BUFFERS_PER_Q; - flush_cnt++; - } - return flush_cnt; -} - -static inline void -__qeth_tso_fill_buffer_frag(struct qeth_qdio_out_buffer *buf, - struct sk_buff *skb) -{ - struct skb_frag_struct *frag; - struct qdio_buffer *buffer; - int fragno, cnt, element; - unsigned long addr; - - QETH_DBF_TEXT(trace, 6, "tsfilfrg"); - - /*initialize variables ...*/ - fragno = skb_shinfo(skb)->nr_frags; - buffer = buf->buffer; - element = buf->next_element_to_fill; - /*fill buffer elements .....*/ - for (cnt = 0; cnt < fragno; cnt++) { - frag = &skb_shinfo(skb)->frags[cnt]; - addr = (page_to_pfn(frag->page) << PAGE_SHIFT) + - frag->page_offset; - buffer->element[element].addr = (char *)addr; - buffer->element[element].length = frag->size; - if (cnt < (fragno - 1)) - buffer->element[element].flags = - SBAL_FLAGS_MIDDLE_FRAG; - else - buffer->element[element].flags = - SBAL_FLAGS_LAST_FRAG; - element++; - } - buf->next_element_to_fill = element; -} - -static inline int -qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf, - struct sk_buff *skb) -{ - int length, length_here, element; - int hdr_len; - struct qdio_buffer *buffer; - struct qeth_hdr_tso *hdr; - char *data; - - QETH_DBF_TEXT(trace, 3, "tsfilbuf"); - - /*increment user count and queue skb ...*/ - atomic_inc(&skb->users); - skb_queue_tail(&buf->skb_list, skb); - - /*initialize all variables...*/ - buffer = buf->buffer; - hdr = (struct qeth_hdr_tso *)skb->data; - hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len; - data = skb->data + hdr_len; - length = skb->len - hdr_len; - element = buf->next_element_to_fill; - /*fill first buffer entry only with header information */ - buffer->element[element].addr = skb->data; - buffer->element[element].length = hdr_len; - buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG; - buf->next_element_to_fill++; - - if (skb_shinfo(skb)->nr_frags > 0) { - __qeth_tso_fill_buffer_frag(buf, skb); - goto out; - } - - /*start filling buffer entries ...*/ - element++; - while (length > 0) { - /* length_here is the remaining amount of data in this page */ - length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE); - if (length < length_here) - length_here = length; - buffer->element[element].addr = data; - buffer->element[element].length = length_here; - length -= length_here; - if (!length) - buffer->element[element].flags = - SBAL_FLAGS_LAST_FRAG; - else - buffer->element[element].flags = - SBAL_FLAGS_MIDDLE_FRAG; - data += length_here; - element++; - } - /*set the buffer to primed ...*/ - buf->next_element_to_fill = element; -out: - atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED); - return 1; -} - -int -qeth_tso_send_packet(struct qeth_card *card, struct sk_buff *skb, - struct qeth_qdio_out_q *queue, int ipv, int cast_type) -{ - int flush_cnt = 0; - struct qeth_hdr_tso *hdr; - struct qeth_qdio_out_buffer *buffer; - int start_index; - - QETH_DBF_TEXT(trace, 3, "tsosend"); - - if (!(hdr = qeth_tso_prepare_packet(card, skb, ipv, cast_type))) - return -ENOMEM; - /*check if skb fits in one SBAL ...*/ - if (!(qeth_get_elements_no(card, (void*)hdr, skb))) - return -EINVAL; - /*lock queue, force switching to non-packing and send it ...*/ - while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED, - QETH_OUT_Q_LOCKED, - &queue->state)); - start_index = queue->next_buf_to_fill; - buffer = &queue->bufs[queue->next_buf_to_fill]; - /*check if card is too busy ...*/ - if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){ - card->stats.tx_dropped++; - goto out; - } - /*let's force to non-packing and get a new SBAL*/ - flush_cnt += qeth_tso_get_queue_buffer(queue); - buffer = &queue->bufs[queue->next_buf_to_fill]; - if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) { - card->stats.tx_dropped++; - goto out; - } - flush_cnt += qeth_tso_fill_buffer(buffer, skb); - queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % - QDIO_MAX_BUFFERS_PER_Q; -out: - atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); - if (flush_cnt) - qeth_flush_buffers(queue, 0, start_index, flush_cnt); - /*do some statistics */ - card->stats.tx_packets++; - card->stats.tx_bytes += skb->len; - return 0; -} |