aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/net')
-rw-r--r--drivers/s390/net/qeth_core.h1
-rw-r--r--drivers/s390/net/qeth_core_main.c104
-rw-r--r--drivers/s390/net/qeth_l2_main.c7
-rw-r--r--drivers/s390/net/qeth_l3_main.c26
4 files changed, 65 insertions, 73 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 0b4250d3a25d..d79892782a2b 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -869,6 +869,7 @@ void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
869void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...); 869void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
870int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); 870int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *);
871int qeth_set_access_ctrl_online(struct qeth_card *card); 871int qeth_set_access_ctrl_online(struct qeth_card *card);
872int qeth_hdr_chk_and_bounce(struct sk_buff *, int);
872 873
873/* exports for OSN */ 874/* exports for OSN */
874int qeth_osn_assist(struct net_device *, void *, int); 875int qeth_osn_assist(struct net_device *, void *, int);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 3cdd2705b75a..656a6e78a2ee 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -57,48 +57,6 @@ static void qeth_free_buffer_pool(struct qeth_card *);
57static int qeth_qdio_establish(struct qeth_card *); 57static int qeth_qdio_establish(struct qeth_card *);
58 58
59 59
60static inline void __qeth_fill_buffer_frag(struct sk_buff *skb,
61 struct qdio_buffer *buffer, int is_tso,
62 int *next_element_to_fill)
63{
64 struct skb_frag_struct *frag;
65 int fragno;
66 unsigned long addr;
67 int element, cnt, dlen;
68
69 fragno = skb_shinfo(skb)->nr_frags;
70 element = *next_element_to_fill;
71 dlen = 0;
72
73 if (is_tso)
74 buffer->element[element].flags =
75 SBAL_FLAGS_MIDDLE_FRAG;
76 else
77 buffer->element[element].flags =
78 SBAL_FLAGS_FIRST_FRAG;
79 dlen = skb->len - skb->data_len;
80 if (dlen) {
81 buffer->element[element].addr = skb->data;
82 buffer->element[element].length = dlen;
83 element++;
84 }
85 for (cnt = 0; cnt < fragno; cnt++) {
86 frag = &skb_shinfo(skb)->frags[cnt];
87 addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
88 frag->page_offset;
89 buffer->element[element].addr = (char *)addr;
90 buffer->element[element].length = frag->size;
91 if (cnt < (fragno - 1))
92 buffer->element[element].flags =
93 SBAL_FLAGS_MIDDLE_FRAG;
94 else
95 buffer->element[element].flags =
96 SBAL_FLAGS_LAST_FRAG;
97 element++;
98 }
99 *next_element_to_fill = element;
100}
101
102static inline const char *qeth_get_cardname(struct qeth_card *card) 60static inline const char *qeth_get_cardname(struct qeth_card *card)
103{ 61{
104 if (card->info.guestlan) { 62 if (card->info.guestlan) {
@@ -3020,13 +2978,11 @@ EXPORT_SYMBOL_GPL(qeth_get_priority_queue);
3020int qeth_get_elements_no(struct qeth_card *card, void *hdr, 2978int qeth_get_elements_no(struct qeth_card *card, void *hdr,
3021 struct sk_buff *skb, int elems) 2979 struct sk_buff *skb, int elems)
3022{ 2980{
3023 int elements_needed = 0; 2981 int dlen = skb->len - skb->data_len;
2982 int elements_needed = PFN_UP((unsigned long)skb->data + dlen - 1) -
2983 PFN_DOWN((unsigned long)skb->data);
3024 2984
3025 if (skb_shinfo(skb)->nr_frags > 0) 2985 elements_needed += skb_shinfo(skb)->nr_frags;
3026 elements_needed = (skb_shinfo(skb)->nr_frags + 1);
3027 if (elements_needed == 0)
3028 elements_needed = 1 + (((((unsigned long) skb->data) %
3029 PAGE_SIZE) + skb->len) >> PAGE_SHIFT);
3030 if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) { 2986 if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) {
3031 QETH_DBF_MESSAGE(2, "Invalid size of IP packet " 2987 QETH_DBF_MESSAGE(2, "Invalid size of IP packet "
3032 "(Number=%d / Length=%d). Discarded.\n", 2988 "(Number=%d / Length=%d). Discarded.\n",
@@ -3037,15 +2993,35 @@ int qeth_get_elements_no(struct qeth_card *card, void *hdr,
3037} 2993}
3038EXPORT_SYMBOL_GPL(qeth_get_elements_no); 2994EXPORT_SYMBOL_GPL(qeth_get_elements_no);
3039 2995
2996int qeth_hdr_chk_and_bounce(struct sk_buff *skb, int len)
2997{
2998 int hroom, inpage, rest;
2999
3000 if (((unsigned long)skb->data & PAGE_MASK) !=
3001 (((unsigned long)skb->data + len - 1) & PAGE_MASK)) {
3002 hroom = skb_headroom(skb);
3003 inpage = PAGE_SIZE - ((unsigned long) skb->data % PAGE_SIZE);
3004 rest = len - inpage;
3005 if (rest > hroom)
3006 return 1;
3007 memmove(skb->data - rest, skb->data, skb->len - skb->data_len);
3008 skb->data -= rest;
3009 QETH_DBF_MESSAGE(2, "skb bounce len: %d rest: %d\n", len, rest);
3010 }
3011 return 0;
3012}
3013EXPORT_SYMBOL_GPL(qeth_hdr_chk_and_bounce);
3014
3040static inline void __qeth_fill_buffer(struct sk_buff *skb, 3015static inline void __qeth_fill_buffer(struct sk_buff *skb,
3041 struct qdio_buffer *buffer, int is_tso, int *next_element_to_fill, 3016 struct qdio_buffer *buffer, int is_tso, int *next_element_to_fill,
3042 int offset) 3017 int offset)
3043{ 3018{
3044 int length = skb->len; 3019 int length = skb->len - skb->data_len;
3045 int length_here; 3020 int length_here;
3046 int element; 3021 int element;
3047 char *data; 3022 char *data;
3048 int first_lap ; 3023 int first_lap, cnt;
3024 struct skb_frag_struct *frag;
3049 3025
3050 element = *next_element_to_fill; 3026 element = *next_element_to_fill;
3051 data = skb->data; 3027 data = skb->data;
@@ -3068,10 +3044,14 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb,
3068 length -= length_here; 3044 length -= length_here;
3069 if (!length) { 3045 if (!length) {
3070 if (first_lap) 3046 if (first_lap)
3071 buffer->element[element].flags = 0; 3047 if (skb_shinfo(skb)->nr_frags)
3048 buffer->element[element].flags =
3049 SBAL_FLAGS_FIRST_FRAG;
3050 else
3051 buffer->element[element].flags = 0;
3072 else 3052 else
3073 buffer->element[element].flags = 3053 buffer->element[element].flags =
3074 SBAL_FLAGS_LAST_FRAG; 3054 SBAL_FLAGS_MIDDLE_FRAG;
3075 } else { 3055 } else {
3076 if (first_lap) 3056 if (first_lap)
3077 buffer->element[element].flags = 3057 buffer->element[element].flags =
@@ -3084,6 +3064,18 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb,
3084 element++; 3064 element++;
3085 first_lap = 0; 3065 first_lap = 0;
3086 } 3066 }
3067
3068 for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) {
3069 frag = &skb_shinfo(skb)->frags[cnt];
3070 buffer->element[element].addr = (char *)page_to_phys(frag->page)
3071 + frag->page_offset;
3072 buffer->element[element].length = frag->size;
3073 buffer->element[element].flags = SBAL_FLAGS_MIDDLE_FRAG;
3074 element++;
3075 }
3076
3077 if (buffer->element[element - 1].flags)
3078 buffer->element[element - 1].flags = SBAL_FLAGS_LAST_FRAG;
3087 *next_element_to_fill = element; 3079 *next_element_to_fill = element;
3088} 3080}
3089 3081
@@ -3124,12 +3116,8 @@ static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
3124 buf->next_element_to_fill++; 3116 buf->next_element_to_fill++;
3125 } 3117 }
3126 3118
3127 if (skb_shinfo(skb)->nr_frags == 0) 3119 __qeth_fill_buffer(skb, buffer, large_send,
3128 __qeth_fill_buffer(skb, buffer, large_send, 3120 (int *)&buf->next_element_to_fill, offset);
3129 (int *)&buf->next_element_to_fill, offset);
3130 else
3131 __qeth_fill_buffer_frag(skb, buffer, large_send,
3132 (int *)&buf->next_element_to_fill);
3133 3121
3134 if (!queue->do_pack) { 3122 if (!queue->do_pack) {
3135 QETH_CARD_TEXT(queue->card, 6, "fillbfnp"); 3123 QETH_CARD_TEXT(queue->card, 6, "fillbfnp");
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index e7942ccab987..32d07c2dcc67 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -712,10 +712,13 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
712 goto tx_drop; 712 goto tx_drop;
713 } 713 }
714 714
715 if (card->info.type != QETH_CARD_TYPE_IQD) 715 if (card->info.type != QETH_CARD_TYPE_IQD) {
716 if (qeth_hdr_chk_and_bounce(new_skb,
717 sizeof(struct qeth_hdr_layer2)))
718 goto tx_drop;
716 rc = qeth_do_send_packet(card, queue, new_skb, hdr, 719 rc = qeth_do_send_packet(card, queue, new_skb, hdr,
717 elements); 720 elements);
718 else 721 } else
719 rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr, 722 rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
720 elements, data_offset, hd_len); 723 elements, data_offset, hd_len);
721 if (!rc) { 724 if (!rc) {
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index b5733e405ed9..61d348e51920 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2904,19 +2904,11 @@ static inline int qeth_l3_tso_elements(struct sk_buff *skb)
2904 unsigned long tcpd = (unsigned long)tcp_hdr(skb) + 2904 unsigned long tcpd = (unsigned long)tcp_hdr(skb) +
2905 tcp_hdr(skb)->doff * 4; 2905 tcp_hdr(skb)->doff * 4;
2906 int tcpd_len = skb->len - (tcpd - (unsigned long)skb->data); 2906 int tcpd_len = skb->len - (tcpd - (unsigned long)skb->data);
2907 int elements = PFN_UP(tcpd + tcpd_len) - PFN_DOWN(tcpd); 2907 int elements = PFN_UP(tcpd + tcpd_len - 1) - PFN_DOWN(tcpd);
2908 elements += skb_shinfo(skb)->nr_frags; 2908 elements += skb_shinfo(skb)->nr_frags;
2909 return elements; 2909 return elements;
2910} 2910}
2911 2911
2912static inline int qeth_l3_tso_check(struct sk_buff *skb)
2913{
2914 int len = ((unsigned long)tcp_hdr(skb) + tcp_hdr(skb)->doff * 4) -
2915 (unsigned long)skb->data;
2916 return (((unsigned long)skb->data & PAGE_MASK) !=
2917 (((unsigned long)skb->data + len) & PAGE_MASK));
2918}
2919
2920static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) 2912static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2921{ 2913{
2922 int rc; 2914 int rc;
@@ -3016,8 +3008,6 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
3016 (cast_type == RTN_UNSPEC)) { 3008 (cast_type == RTN_UNSPEC)) {
3017 hdr = (struct qeth_hdr *)skb_push(new_skb, 3009 hdr = (struct qeth_hdr *)skb_push(new_skb,
3018 sizeof(struct qeth_hdr_tso)); 3010 sizeof(struct qeth_hdr_tso));
3019 if (qeth_l3_tso_check(new_skb))
3020 QETH_DBF_MESSAGE(2, "tso skb misaligned\n");
3021 memset(hdr, 0, sizeof(struct qeth_hdr_tso)); 3011 memset(hdr, 0, sizeof(struct qeth_hdr_tso));
3022 qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type); 3012 qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type);
3023 qeth_tso_fill_header(card, hdr, new_skb); 3013 qeth_tso_fill_header(card, hdr, new_skb);
@@ -3048,10 +3038,20 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
3048 elements_needed += elems; 3038 elements_needed += elems;
3049 nr_frags = skb_shinfo(new_skb)->nr_frags; 3039 nr_frags = skb_shinfo(new_skb)->nr_frags;
3050 3040
3051 if (card->info.type != QETH_CARD_TYPE_IQD) 3041 if (card->info.type != QETH_CARD_TYPE_IQD) {
3042 int len;
3043 if (large_send == QETH_LARGE_SEND_TSO)
3044 len = ((unsigned long)tcp_hdr(new_skb) +
3045 tcp_hdr(new_skb)->doff * 4) -
3046 (unsigned long)new_skb->data;
3047 else
3048 len = sizeof(struct qeth_hdr_layer3);
3049
3050 if (qeth_hdr_chk_and_bounce(new_skb, len))
3051 goto tx_drop;
3052 rc = qeth_do_send_packet(card, queue, new_skb, hdr, 3052 rc = qeth_do_send_packet(card, queue, new_skb, hdr,
3053 elements_needed); 3053 elements_needed);
3054 else 3054 } else
3055 rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr, 3055 rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
3056 elements_needed, data_offset, 0); 3056 elements_needed, data_offset, 0);
3057 3057