aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
author <jgarzik@pretzel.yyz.us>2005-05-25 22:11:06 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-05-25 22:11:06 -0400
commit8a75e7d644b373f86c8c2316392cb7374fc4e063 (patch)
treec2beb29f8e4f5c1ea246d792693f8af4f7f03fef /drivers/s390
parentf5a702b26a0cd6052f0bae2bc3f0548538d3909c (diff)
parent05e08a2a297371564020f76d1bf8b3a931d5e1ed (diff)
Automatic merge of /spare/repo/netdev-2.6 branch qeth
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/net/Makefile3
-rw-r--r--drivers/s390/net/ctcdbug.h12
-rw-r--r--drivers/s390/net/ctcmain.c616
-rw-r--r--drivers/s390/net/ctcmain.h276
-rw-r--r--drivers/s390/net/ctctty.c5
-rw-r--r--drivers/s390/net/cu3088.c4
-rw-r--r--drivers/s390/net/cu3088.h3
-rw-r--r--drivers/s390/net/iucv.c10
-rw-r--r--drivers/s390/net/lcs.c33
-rw-r--r--drivers/s390/net/qeth.h35
-rw-r--r--drivers/s390/net/qeth_eddp.c51
-rw-r--r--drivers/s390/net/qeth_main.c316
-rw-r--r--drivers/s390/net/qeth_tso.c285
-rw-r--r--drivers/s390/net/qeth_tso.h166
14 files changed, 914 insertions, 901 deletions
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index 7cabb80a2e41..90d4d0ef3dd4 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
9obj-$(CONFIG_SMSGIUCV) += smsgiucv.o 9obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
10obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o 10obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
11obj-$(CONFIG_LCS) += lcs.o cu3088.o 11obj-$(CONFIG_LCS) += lcs.o cu3088.o
12qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o qeth_tso.o 12obj-$(CONFIG_CLAW) += claw.o cu3088.o
13qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o
13qeth-$(CONFIG_PROC_FS) += qeth_proc.o 14qeth-$(CONFIG_PROC_FS) += qeth_proc.o
14obj-$(CONFIG_QETH) += qeth.o 15obj-$(CONFIG_QETH) += qeth.o
diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h
index ef8883951720..7fe2ebd1792d 100644
--- a/drivers/s390/net/ctcdbug.h
+++ b/drivers/s390/net/ctcdbug.h
@@ -1,6 +1,6 @@
1/* 1/*
2 * 2 *
3 * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.4 $) 3 * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.5 $)
4 * 4 *
5 * CTC / ESCON network driver - s390 dbf exploit. 5 * CTC / ESCON network driver - s390 dbf exploit.
6 * 6 *
@@ -9,7 +9,7 @@
9 * Author(s): Original Code written by 9 * Author(s): Original Code written by
10 * Peter Tiedemann (ptiedem@de.ibm.com) 10 * Peter Tiedemann (ptiedem@de.ibm.com)
11 * 11 *
12 * $Revision: 1.4 $ $Date: 2004/10/15 09:26:58 $ 12 * $Revision: 1.5 $ $Date: 2005/02/27 19:46:44 $
13 * 13 *
14 * This program is free software; you can redistribute it and/or modify 14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by 15 * it under the terms of the GNU General Public License as published by
@@ -25,9 +25,11 @@
25 * along with this program; if not, write to the Free Software 25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */ 27 */
28 28#ifndef _CTCDBUG_H_
29#define _CTCDBUG_H_
29 30
30#include <asm/debug.h> 31#include <asm/debug.h>
32#include "ctcmain.h"
31/** 33/**
32 * Debug Facility stuff 34 * Debug Facility stuff
33 */ 35 */
@@ -41,7 +43,7 @@
41#define CTC_DBF_DATA_LEN 128 43#define CTC_DBF_DATA_LEN 128
42#define CTC_DBF_DATA_INDEX 3 44#define CTC_DBF_DATA_INDEX 3
43#define CTC_DBF_DATA_NR_AREAS 1 45#define CTC_DBF_DATA_NR_AREAS 1
44#define CTC_DBF_DATA_LEVEL 2 46#define CTC_DBF_DATA_LEVEL 3
45 47
46#define CTC_DBF_TRACE_NAME "ctc_trace" 48#define CTC_DBF_TRACE_NAME "ctc_trace"
47#define CTC_DBF_TRACE_LEN 16 49#define CTC_DBF_TRACE_LEN 16
@@ -121,3 +123,5 @@ hex_dump(unsigned char *buf, size_t len)
121 printk("\n"); 123 printk("\n");
122} 124}
123 125
126
127#endif
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 7266bf5ea659..ff3e95e07e89 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: ctcmain.c,v 1.72 2005/03/17 10:51:52 ptiedem Exp $ 2 * $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $
3 * 3 *
4 * CTC / ESCON network driver 4 * CTC / ESCON network driver
5 * 5 *
@@ -37,12 +37,11 @@
37 * along with this program; if not, write to the Free Software 37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 38 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
39 * 39 *
40 * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.72 $ 40 * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $
41 * 41 *
42 */ 42 */
43 43
44#undef DEBUG 44#undef DEBUG
45
46#include <linux/module.h> 45#include <linux/module.h>
47#include <linux/init.h> 46#include <linux/init.h>
48#include <linux/kernel.h> 47#include <linux/kernel.h>
@@ -74,288 +73,13 @@
74#include "ctctty.h" 73#include "ctctty.h"
75#include "fsm.h" 74#include "fsm.h"
76#include "cu3088.h" 75#include "cu3088.h"
76
77#include "ctcdbug.h" 77#include "ctcdbug.h"
78#include "ctcmain.h"
78 79
79MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@millenux.com)"); 80MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
80MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver"); 81MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver");
81MODULE_LICENSE("GPL"); 82MODULE_LICENSE("GPL");
82
83/**
84 * CCW commands, used in this driver.
85 */
86#define CCW_CMD_WRITE 0x01
87#define CCW_CMD_READ 0x02
88#define CCW_CMD_SET_EXTENDED 0xc3
89#define CCW_CMD_PREPARE 0xe3
90
91#define CTC_PROTO_S390 0
92#define CTC_PROTO_LINUX 1
93#define CTC_PROTO_LINUX_TTY 2
94#define CTC_PROTO_OS390 3
95#define CTC_PROTO_MAX 3
96
97#define CTC_BUFSIZE_LIMIT 65535
98#define CTC_BUFSIZE_DEFAULT 32768
99
100#define CTC_TIMEOUT_5SEC 5000
101
102#define CTC_INITIAL_BLOCKLEN 2
103
104#define READ 0
105#define WRITE 1
106
107#define CTC_ID_SIZE BUS_ID_SIZE+3
108
109
110struct ctc_profile {
111 unsigned long maxmulti;
112 unsigned long maxcqueue;
113 unsigned long doios_single;
114 unsigned long doios_multi;
115 unsigned long txlen;
116 unsigned long tx_time;
117 struct timespec send_stamp;
118};
119
120/**
121 * Definition of one channel
122 */
123struct channel {
124
125 /**
126 * Pointer to next channel in list.
127 */
128 struct channel *next;
129 char id[CTC_ID_SIZE];
130 struct ccw_device *cdev;
131
132 /**
133 * Type of this channel.
134 * CTC/A or Escon for valid channels.
135 */
136 enum channel_types type;
137
138 /**
139 * Misc. flags. See CHANNEL_FLAGS_... below
140 */
141 __u32 flags;
142
143 /**
144 * The protocol of this channel
145 */
146 __u16 protocol;
147
148 /**
149 * I/O and irq related stuff
150 */
151 struct ccw1 *ccw;
152 struct irb *irb;
153
154 /**
155 * RX/TX buffer size
156 */
157 int max_bufsize;
158
159 /**
160 * Transmit/Receive buffer.
161 */
162 struct sk_buff *trans_skb;
163
164 /**
165 * Universal I/O queue.
166 */
167 struct sk_buff_head io_queue;
168
169 /**
170 * TX queue for collecting skb's during busy.
171 */
172 struct sk_buff_head collect_queue;
173
174 /**
175 * Amount of data in collect_queue.
176 */
177 int collect_len;
178
179 /**
180 * spinlock for collect_queue and collect_len
181 */
182 spinlock_t collect_lock;
183
184 /**
185 * Timer for detecting unresposive
186 * I/O operations.
187 */
188 fsm_timer timer;
189
190 /**
191 * Retry counter for misc. operations.
192 */
193 int retry;
194
195 /**
196 * The finite state machine of this channel
197 */
198 fsm_instance *fsm;
199
200 /**
201 * The corresponding net_device this channel
202 * belongs to.
203 */
204 struct net_device *netdev;
205
206 struct ctc_profile prof;
207
208 unsigned char *trans_skb_data;
209
210 __u16 logflags;
211};
212
213#define CHANNEL_FLAGS_READ 0
214#define CHANNEL_FLAGS_WRITE 1
215#define CHANNEL_FLAGS_INUSE 2
216#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4
217#define CHANNEL_FLAGS_FAILED 8
218#define CHANNEL_FLAGS_WAITIRQ 16
219#define CHANNEL_FLAGS_RWMASK 1
220#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
221
222#define LOG_FLAG_ILLEGALPKT 1
223#define LOG_FLAG_ILLEGALSIZE 2
224#define LOG_FLAG_OVERRUN 4
225#define LOG_FLAG_NOMEM 8
226
227#define CTC_LOGLEVEL_INFO 1
228#define CTC_LOGLEVEL_NOTICE 2
229#define CTC_LOGLEVEL_WARN 4
230#define CTC_LOGLEVEL_EMERG 8
231#define CTC_LOGLEVEL_ERR 16
232#define CTC_LOGLEVEL_DEBUG 32
233#define CTC_LOGLEVEL_CRIT 64
234
235#define CTC_LOGLEVEL_DEFAULT \
236(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT)
237
238#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1)
239
240static int loglevel = CTC_LOGLEVEL_DEFAULT;
241
242#define ctc_pr_debug(fmt, arg...) \
243do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0)
244
245#define ctc_pr_info(fmt, arg...) \
246do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0)
247
248#define ctc_pr_notice(fmt, arg...) \
249do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0)
250
251#define ctc_pr_warn(fmt, arg...) \
252do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0)
253
254#define ctc_pr_emerg(fmt, arg...) \
255do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0)
256
257#define ctc_pr_err(fmt, arg...) \
258do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0)
259
260#define ctc_pr_crit(fmt, arg...) \
261do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0)
262
263/**
264 * Linked list of all detected channels.
265 */
266static struct channel *channels = NULL;
267
268struct ctc_priv {
269 struct net_device_stats stats;
270 unsigned long tbusy;
271 /**
272 * The finite state machine of this interface.
273 */
274 fsm_instance *fsm;
275 /**
276 * The protocol of this device
277 */
278 __u16 protocol;
279 /**
280 * Timer for restarting after I/O Errors
281 */
282 fsm_timer restart_timer;
283
284 int buffer_size;
285
286 struct channel *channel[2];
287};
288
289/**
290 * Definition of our link level header.
291 */
292struct ll_header {
293 __u16 length;
294 __u16 type;
295 __u16 unused;
296};
297#define LL_HEADER_LENGTH (sizeof(struct ll_header))
298
299/**
300 * Compatibility macros for busy handling
301 * of network devices.
302 */
303static __inline__ void
304ctc_clear_busy(struct net_device * dev)
305{
306 clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
307 if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
308 netif_wake_queue(dev);
309}
310
311static __inline__ int
312ctc_test_and_set_busy(struct net_device * dev)
313{
314 if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
315 netif_stop_queue(dev);
316 return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
317}
318
319/**
320 * Print Banner.
321 */
322static void
323print_banner(void)
324{
325 static int printed = 0;
326 char vbuf[] = "$Revision: 1.72 $";
327 char *version = vbuf;
328
329 if (printed)
330 return;
331 if ((version = strchr(version, ':'))) {
332 char *p = strchr(version + 1, '$');
333 if (p)
334 *p = '\0';
335 } else
336 version = " ??? ";
337 printk(KERN_INFO "CTC driver Version%s"
338#ifdef DEBUG
339 " (DEBUG-VERSION, " __DATE__ __TIME__ ")"
340#endif
341 " initialized\n", version);
342 printed = 1;
343}
344
345/**
346 * Return type of a detected device.
347 */
348static enum channel_types
349get_channel_type(struct ccw_device_id *id)
350{
351 enum channel_types type = (enum channel_types) id->driver_info;
352
353 if (type == channel_type_ficon)
354 type = channel_type_escon;
355
356 return type;
357}
358
359/** 83/**
360 * States of the interface statemachine. 84 * States of the interface statemachine.
361 */ 85 */
@@ -371,7 +95,7 @@ enum dev_states {
371 /** 95 /**
372 * MUST be always the last element!! 96 * MUST be always the last element!!
373 */ 97 */
374 NR_DEV_STATES 98 CTC_NR_DEV_STATES
375}; 99};
376 100
377static const char *dev_state_names[] = { 101static const char *dev_state_names[] = {
@@ -399,7 +123,7 @@ enum dev_events {
399 /** 123 /**
400 * MUST be always the last element!! 124 * MUST be always the last element!!
401 */ 125 */
402 NR_DEV_EVENTS 126 CTC_NR_DEV_EVENTS
403}; 127};
404 128
405static const char *dev_event_names[] = { 129static const char *dev_event_names[] = {
@@ -476,40 +200,6 @@ enum ch_events {
476 NR_CH_EVENTS, 200 NR_CH_EVENTS,
477}; 201};
478 202
479static const char *ch_event_names[] = {
480 "ccw_device success",
481 "ccw_device busy",
482 "ccw_device enodev",
483 "ccw_device ioerr",
484 "ccw_device unknown",
485
486 "Status ATTN & BUSY",
487 "Status ATTN",
488 "Status BUSY",
489
490 "Unit check remote reset",
491 "Unit check remote system reset",
492 "Unit check TX timeout",
493 "Unit check TX parity",
494 "Unit check Hardware failure",
495 "Unit check RX parity",
496 "Unit check ZERO",
497 "Unit check Unknown",
498
499 "SubChannel check Unknown",
500
501 "Machine check failure",
502 "Machine check operational",
503
504 "IRQ normal",
505 "IRQ final",
506
507 "Timer",
508
509 "Start",
510 "Stop",
511};
512
513/** 203/**
514 * States of the channel statemachine. 204 * States of the channel statemachine.
515 */ 205 */
@@ -545,6 +235,87 @@ enum ch_states {
545 NR_CH_STATES, 235 NR_CH_STATES,
546}; 236};
547 237
238static int loglevel = CTC_LOGLEVEL_DEFAULT;
239
240/**
241 * Linked list of all detected channels.
242 */
243static struct channel *channels = NULL;
244
245/**
246 * Print Banner.
247 */
248static void
249print_banner(void)
250{
251 static int printed = 0;
252 char vbuf[] = "$Revision: 1.74 $";
253 char *version = vbuf;
254
255 if (printed)
256 return;
257 if ((version = strchr(version, ':'))) {
258 char *p = strchr(version + 1, '$');
259 if (p)
260 *p = '\0';
261 } else
262 version = " ??? ";
263 printk(KERN_INFO "CTC driver Version%s"
264#ifdef DEBUG
265 " (DEBUG-VERSION, " __DATE__ __TIME__ ")"
266#endif
267 " initialized\n", version);
268 printed = 1;
269}
270
271/**
272 * Return type of a detected device.
273 */
274static enum channel_types
275get_channel_type(struct ccw_device_id *id)
276{
277 enum channel_types type = (enum channel_types) id->driver_info;
278
279 if (type == channel_type_ficon)
280 type = channel_type_escon;
281
282 return type;
283}
284
285static const char *ch_event_names[] = {
286 "ccw_device success",
287 "ccw_device busy",
288 "ccw_device enodev",
289 "ccw_device ioerr",
290 "ccw_device unknown",
291
292 "Status ATTN & BUSY",
293 "Status ATTN",
294 "Status BUSY",
295
296 "Unit check remote reset",
297 "Unit check remote system reset",
298 "Unit check TX timeout",
299 "Unit check TX parity",
300 "Unit check Hardware failure",
301 "Unit check RX parity",
302 "Unit check ZERO",
303 "Unit check Unknown",
304
305 "SubChannel check Unknown",
306
307 "Machine check failure",
308 "Machine check operational",
309
310 "IRQ normal",
311 "IRQ final",
312
313 "Timer",
314
315 "Start",
316 "Stop",
317};
318
548static const char *ch_state_names[] = { 319static const char *ch_state_names[] = {
549 "Idle", 320 "Idle",
550 "Stopped", 321 "Stopped",
@@ -1934,7 +1705,6 @@ add_channel(struct ccw_device *cdev, enum channel_types type)
1934 ch->cdev = cdev; 1705 ch->cdev = cdev;
1935 snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id); 1706 snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id);
1936 ch->type = type; 1707 ch->type = type;
1937 loglevel = CTC_LOGLEVEL_DEFAULT;
1938 ch->fsm = init_fsm(ch->id, ch_state_names, 1708 ch->fsm = init_fsm(ch->id, ch_state_names,
1939 ch_event_names, NR_CH_STATES, NR_CH_EVENTS, 1709 ch_event_names, NR_CH_STATES, NR_CH_EVENTS,
1940 ch_fsm, CH_FSM_LEN, GFP_KERNEL); 1710 ch_fsm, CH_FSM_LEN, GFP_KERNEL);
@@ -2697,6 +2467,7 @@ ctc_stats(struct net_device * dev)
2697/* 2467/*
2698 * sysfs attributes 2468 * sysfs attributes
2699 */ 2469 */
2470
2700static ssize_t 2471static ssize_t
2701buffer_show(struct device *dev, char *buf) 2472buffer_show(struct device *dev, char *buf)
2702{ 2473{
@@ -2715,57 +2486,61 @@ buffer_write(struct device *dev, const char *buf, size_t count)
2715 struct ctc_priv *priv; 2486 struct ctc_priv *priv;
2716 struct net_device *ndev; 2487 struct net_device *ndev;
2717 int bs1; 2488 int bs1;
2489 char buffer[16];
2718 2490
2719 DBF_TEXT(trace, 3, __FUNCTION__); 2491 DBF_TEXT(trace, 3, __FUNCTION__);
2492 DBF_TEXT(trace, 3, buf);
2720 priv = dev->driver_data; 2493 priv = dev->driver_data;
2721 if (!priv) 2494 if (!priv) {
2495 DBF_TEXT(trace, 3, "bfnopriv");
2722 return -ENODEV; 2496 return -ENODEV;
2497 }
2498
2499 sscanf(buf, "%u", &bs1);
2500 if (bs1 > CTC_BUFSIZE_LIMIT)
2501 goto einval;
2502 if (bs1 < (576 + LL_HEADER_LENGTH + 2))
2503 goto einval;
2504 priv->buffer_size = bs1; // just to overwrite the default
2505
2723 ndev = priv->channel[READ]->netdev; 2506 ndev = priv->channel[READ]->netdev;
2724 if (!ndev) 2507 if (!ndev) {
2508 DBF_TEXT(trace, 3, "bfnondev");
2725 return -ENODEV; 2509 return -ENODEV;
2726 sscanf(buf, "%u", &bs1); 2510 }
2727 2511
2728 if (bs1 > CTC_BUFSIZE_LIMIT)
2729 return -EINVAL;
2730 if ((ndev->flags & IFF_RUNNING) && 2512 if ((ndev->flags & IFF_RUNNING) &&
2731 (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2))) 2513 (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
2732 return -EINVAL; 2514 goto einval;
2733 if (bs1 < (576 + LL_HEADER_LENGTH + 2))
2734 return -EINVAL;
2735 2515
2736 priv->buffer_size = bs1; 2516 priv->channel[READ]->max_bufsize = bs1;
2737 priv->channel[READ]->max_bufsize = 2517 priv->channel[WRITE]->max_bufsize = bs1;
2738 priv->channel[WRITE]->max_bufsize = bs1;
2739 if (!(ndev->flags & IFF_RUNNING)) 2518 if (!(ndev->flags & IFF_RUNNING))
2740 ndev->mtu = bs1 - LL_HEADER_LENGTH - 2; 2519 ndev->mtu = bs1 - LL_HEADER_LENGTH - 2;
2741 priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED; 2520 priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
2742 priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED; 2521 priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
2743 2522
2523 sprintf(buffer, "%d",priv->buffer_size);
2524 DBF_TEXT(trace, 3, buffer);
2744 return count; 2525 return count;
2745 2526
2527einval:
2528 DBF_TEXT(trace, 3, "buff_err");
2529 return -EINVAL;
2746} 2530}
2747 2531
2748static ssize_t 2532static ssize_t
2749loglevel_show(struct device *dev, char *buf) 2533loglevel_show(struct device *dev, char *buf)
2750{ 2534{
2751 struct ctc_priv *priv;
2752
2753 priv = dev->driver_data;
2754 if (!priv)
2755 return -ENODEV;
2756 return sprintf(buf, "%d\n", loglevel); 2535 return sprintf(buf, "%d\n", loglevel);
2757} 2536}
2758 2537
2759static ssize_t 2538static ssize_t
2760loglevel_write(struct device *dev, const char *buf, size_t count) 2539loglevel_write(struct device *dev, const char *buf, size_t count)
2761{ 2540{
2762 struct ctc_priv *priv;
2763 int ll1; 2541 int ll1;
2764 2542
2765 DBF_TEXT(trace, 5, __FUNCTION__); 2543 DBF_TEXT(trace, 5, __FUNCTION__);
2766 priv = dev->driver_data;
2767 if (!priv)
2768 return -ENODEV;
2769 sscanf(buf, "%i", &ll1); 2544 sscanf(buf, "%i", &ll1);
2770 2545
2771 if ((ll1 > CTC_LOGLEVEL_MAX) || (ll1 < 0)) 2546 if ((ll1 > CTC_LOGLEVEL_MAX) || (ll1 < 0))
@@ -2835,27 +2610,6 @@ stats_write(struct device *dev, const char *buf, size_t count)
2835 return count; 2610 return count;
2836} 2611}
2837 2612
2838static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
2839static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write);
2840static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
2841
2842static int
2843ctc_add_attributes(struct device *dev)
2844{
2845// device_create_file(dev, &dev_attr_buffer);
2846 device_create_file(dev, &dev_attr_loglevel);
2847 device_create_file(dev, &dev_attr_stats);
2848 return 0;
2849}
2850
2851static void
2852ctc_remove_attributes(struct device *dev)
2853{
2854 device_remove_file(dev, &dev_attr_stats);
2855 device_remove_file(dev, &dev_attr_loglevel);
2856// device_remove_file(dev, &dev_attr_buffer);
2857}
2858
2859 2613
2860static void 2614static void
2861ctc_netdev_unregister(struct net_device * dev) 2615ctc_netdev_unregister(struct net_device * dev)
@@ -2899,52 +2653,6 @@ ctc_free_netdevice(struct net_device * dev, int free_dev)
2899#endif 2653#endif
2900} 2654}
2901 2655
2902/**
2903 * Initialize everything of the net device except the name and the
2904 * channel structs.
2905 */
2906static struct net_device *
2907ctc_init_netdevice(struct net_device * dev, int alloc_device,
2908 struct ctc_priv *privptr)
2909{
2910 if (!privptr)
2911 return NULL;
2912
2913 DBF_TEXT(setup, 3, __FUNCTION__);
2914 if (alloc_device) {
2915 dev = kmalloc(sizeof (struct net_device), GFP_KERNEL);
2916 if (!dev)
2917 return NULL;
2918 memset(dev, 0, sizeof (struct net_device));
2919 }
2920
2921 dev->priv = privptr;
2922 privptr->fsm = init_fsm("ctcdev", dev_state_names,
2923 dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS,
2924 dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
2925 if (privptr->fsm == NULL) {
2926 if (alloc_device)
2927 kfree(dev);
2928 return NULL;
2929 }
2930 fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
2931 fsm_settimer(privptr->fsm, &privptr->restart_timer);
2932 if (dev->mtu == 0)
2933 dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
2934 dev->hard_start_xmit = ctc_tx;
2935 dev->open = ctc_open;
2936 dev->stop = ctc_close;
2937 dev->get_stats = ctc_stats;
2938 dev->change_mtu = ctc_change_mtu;
2939 dev->hard_header_len = LL_HEADER_LENGTH + 2;
2940 dev->addr_len = 0;
2941 dev->type = ARPHRD_SLIP;
2942 dev->tx_queue_len = 100;
2943 dev->flags = IFF_POINTOPOINT | IFF_NOARP;
2944 SET_MODULE_OWNER(dev);
2945 return dev;
2946}
2947
2948static ssize_t 2656static ssize_t
2949ctc_proto_show(struct device *dev, char *buf) 2657ctc_proto_show(struct device *dev, char *buf)
2950{ 2658{
@@ -2977,7 +2685,6 @@ ctc_proto_store(struct device *dev, const char *buf, size_t count)
2977 return count; 2685 return count;
2978} 2686}
2979 2687
2980static DEVICE_ATTR(protocol, 0644, ctc_proto_show, ctc_proto_store);
2981 2688
2982static ssize_t 2689static ssize_t
2983ctc_type_show(struct device *dev, char *buf) 2690ctc_type_show(struct device *dev, char *buf)
@@ -2991,8 +2698,13 @@ ctc_type_show(struct device *dev, char *buf)
2991 return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]); 2698 return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]);
2992} 2699}
2993 2700
2701static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
2702static DEVICE_ATTR(protocol, 0644, ctc_proto_show, ctc_proto_store);
2994static DEVICE_ATTR(type, 0444, ctc_type_show, NULL); 2703static DEVICE_ATTR(type, 0444, ctc_type_show, NULL);
2995 2704
2705static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write);
2706static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
2707
2996static struct attribute *ctc_attr[] = { 2708static struct attribute *ctc_attr[] = {
2997 &dev_attr_protocol.attr, 2709 &dev_attr_protocol.attr,
2998 &dev_attr_type.attr, 2710 &dev_attr_type.attr,
@@ -3005,6 +2717,21 @@ static struct attribute_group ctc_attr_group = {
3005}; 2717};
3006 2718
3007static int 2719static int
2720ctc_add_attributes(struct device *dev)
2721{
2722 device_create_file(dev, &dev_attr_loglevel);
2723 device_create_file(dev, &dev_attr_stats);
2724 return 0;
2725}
2726
2727static void
2728ctc_remove_attributes(struct device *dev)
2729{
2730 device_remove_file(dev, &dev_attr_stats);
2731 device_remove_file(dev, &dev_attr_loglevel);
2732}
2733
2734static int
3008ctc_add_files(struct device *dev) 2735ctc_add_files(struct device *dev)
3009{ 2736{
3010 pr_debug("%s() called\n", __FUNCTION__); 2737 pr_debug("%s() called\n", __FUNCTION__);
@@ -3028,15 +2755,15 @@ ctc_remove_files(struct device *dev)
3028 * 2755 *
3029 * @returns 0 on success, !0 on failure. 2756 * @returns 0 on success, !0 on failure.
3030 */ 2757 */
3031
3032static int 2758static int
3033ctc_probe_device(struct ccwgroup_device *cgdev) 2759ctc_probe_device(struct ccwgroup_device *cgdev)
3034{ 2760{
3035 struct ctc_priv *priv; 2761 struct ctc_priv *priv;
3036 int rc; 2762 int rc;
2763 char buffer[16];
3037 2764
3038 pr_debug("%s() called\n", __FUNCTION__); 2765 pr_debug("%s() called\n", __FUNCTION__);
3039 DBF_TEXT(trace, 3, __FUNCTION__); 2766 DBF_TEXT(setup, 3, __FUNCTION__);
3040 2767
3041 if (!get_device(&cgdev->dev)) 2768 if (!get_device(&cgdev->dev))
3042 return -ENODEV; 2769 return -ENODEV;
@@ -3060,10 +2787,70 @@ ctc_probe_device(struct ccwgroup_device *cgdev)
3060 cgdev->cdev[1]->handler = ctc_irq_handler; 2787 cgdev->cdev[1]->handler = ctc_irq_handler;
3061 cgdev->dev.driver_data = priv; 2788 cgdev->dev.driver_data = priv;
3062 2789
2790 sprintf(buffer, "%p", priv);
2791 DBF_TEXT(data, 3, buffer);
2792
2793 sprintf(buffer, "%u", (unsigned int)sizeof(struct ctc_priv));
2794 DBF_TEXT(data, 3, buffer);
2795
2796 sprintf(buffer, "%p", &channels);
2797 DBF_TEXT(data, 3, buffer);
2798
2799 sprintf(buffer, "%u", (unsigned int)sizeof(struct channel));
2800 DBF_TEXT(data, 3, buffer);
2801
3063 return 0; 2802 return 0;
3064} 2803}
3065 2804
3066/** 2805/**
2806 * Initialize everything of the net device except the name and the
2807 * channel structs.
2808 */
2809static struct net_device *
2810ctc_init_netdevice(struct net_device * dev, int alloc_device,
2811 struct ctc_priv *privptr)
2812{
2813 if (!privptr)
2814 return NULL;
2815
2816 DBF_TEXT(setup, 3, __FUNCTION__);
2817
2818 if (alloc_device) {
2819 dev = kmalloc(sizeof (struct net_device), GFP_KERNEL);
2820 if (!dev)
2821 return NULL;
2822 memset(dev, 0, sizeof (struct net_device));
2823 }
2824
2825 dev->priv = privptr;
2826 privptr->fsm = init_fsm("ctcdev", dev_state_names,
2827 dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS,
2828 dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
2829 if (privptr->fsm == NULL) {
2830 if (alloc_device)
2831 kfree(dev);
2832 return NULL;
2833 }
2834 fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
2835 fsm_settimer(privptr->fsm, &privptr->restart_timer);
2836 if (dev->mtu == 0)
2837 dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
2838 dev->hard_start_xmit = ctc_tx;
2839 dev->open = ctc_open;
2840 dev->stop = ctc_close;
2841 dev->get_stats = ctc_stats;
2842 dev->change_mtu = ctc_change_mtu;
2843 dev->hard_header_len = LL_HEADER_LENGTH + 2;
2844 dev->addr_len = 0;
2845 dev->type = ARPHRD_SLIP;
2846 dev->tx_queue_len = 100;
2847 dev->flags = IFF_POINTOPOINT | IFF_NOARP;
2848 SET_MODULE_OWNER(dev);
2849 return dev;
2850}
2851
2852
2853/**
3067 * 2854 *
3068 * Setup an interface. 2855 * Setup an interface.
3069 * 2856 *
@@ -3081,6 +2868,7 @@ ctc_new_device(struct ccwgroup_device *cgdev)
3081 struct ctc_priv *privptr; 2868 struct ctc_priv *privptr;
3082 struct net_device *dev; 2869 struct net_device *dev;
3083 int ret; 2870 int ret;
2871 char buffer[16];
3084 2872
3085 pr_debug("%s() called\n", __FUNCTION__); 2873 pr_debug("%s() called\n", __FUNCTION__);
3086 DBF_TEXT(setup, 3, __FUNCTION__); 2874 DBF_TEXT(setup, 3, __FUNCTION__);
@@ -3089,6 +2877,9 @@ ctc_new_device(struct ccwgroup_device *cgdev)
3089 if (!privptr) 2877 if (!privptr)
3090 return -ENODEV; 2878 return -ENODEV;
3091 2879
2880 sprintf(buffer, "%d", privptr->buffer_size);
2881 DBF_TEXT(setup, 3, buffer);
2882
3092 type = get_channel_type(&cgdev->cdev[0]->id); 2883 type = get_channel_type(&cgdev->cdev[0]->id);
3093 2884
3094 snprintf(read_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id); 2885 snprintf(read_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
@@ -3177,9 +2968,10 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev)
3177 struct ctc_priv *priv; 2968 struct ctc_priv *priv;
3178 struct net_device *ndev; 2969 struct net_device *ndev;
3179 2970
3180 DBF_TEXT(trace, 3, __FUNCTION__); 2971 DBF_TEXT(setup, 3, __FUNCTION__);
3181 pr_debug("%s() called\n", __FUNCTION__); 2972 pr_debug("%s() called\n", __FUNCTION__);
3182 2973
2974
3183 priv = cgdev->dev.driver_data; 2975 priv = cgdev->dev.driver_data;
3184 ndev = NULL; 2976 ndev = NULL;
3185 if (!priv) 2977 if (!priv)
@@ -3215,7 +3007,6 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev)
3215 channel_remove(priv->channel[READ]); 3007 channel_remove(priv->channel[READ]);
3216 if (priv->channel[WRITE]) 3008 if (priv->channel[WRITE])
3217 channel_remove(priv->channel[WRITE]); 3009 channel_remove(priv->channel[WRITE]);
3218
3219 priv->channel[READ] = priv->channel[WRITE] = NULL; 3010 priv->channel[READ] = priv->channel[WRITE] = NULL;
3220 3011
3221 return 0; 3012 return 0;
@@ -3228,7 +3019,7 @@ ctc_remove_device(struct ccwgroup_device *cgdev)
3228 struct ctc_priv *priv; 3019 struct ctc_priv *priv;
3229 3020
3230 pr_debug("%s() called\n", __FUNCTION__); 3021 pr_debug("%s() called\n", __FUNCTION__);
3231 DBF_TEXT(trace, 3, __FUNCTION__); 3022 DBF_TEXT(setup, 3, __FUNCTION__);
3232 3023
3233 priv = cgdev->dev.driver_data; 3024 priv = cgdev->dev.driver_data;
3234 if (!priv) 3025 if (!priv)
@@ -3265,6 +3056,7 @@ static struct ccwgroup_driver ctc_group_driver = {
3265static void __exit 3056static void __exit
3266ctc_exit(void) 3057ctc_exit(void)
3267{ 3058{
3059 DBF_TEXT(setup, 3, __FUNCTION__);
3268 unregister_cu3088_discipline(&ctc_group_driver); 3060 unregister_cu3088_discipline(&ctc_group_driver);
3269 ctc_tty_cleanup(); 3061 ctc_tty_cleanup();
3270 ctc_unregister_dbf_views(); 3062 ctc_unregister_dbf_views();
@@ -3282,6 +3074,10 @@ ctc_init(void)
3282{ 3074{
3283 int ret = 0; 3075 int ret = 0;
3284 3076
3077 loglevel = CTC_LOGLEVEL_DEFAULT;
3078
3079 DBF_TEXT(setup, 3, __FUNCTION__);
3080
3285 print_banner(); 3081 print_banner();
3286 3082
3287 ret = ctc_register_dbf_views(); 3083 ret = ctc_register_dbf_views();
diff --git a/drivers/s390/net/ctcmain.h b/drivers/s390/net/ctcmain.h
new file mode 100644
index 000000000000..ba3605f16335
--- /dev/null
+++ b/drivers/s390/net/ctcmain.h
@@ -0,0 +1,276 @@
1/*
2 * $Id: ctcmain.h,v 1.4 2005/03/24 09:04:17 mschwide Exp $
3 *
4 * CTC / ESCON network driver
5 *
6 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
8 Peter Tiedemann (ptiedem@de.ibm.com)
9 *
10 *
11 * Documentation used:
12 * - Principles of Operation (IBM doc#: SA22-7201-06)
13 * - Common IO/-Device Commands and Self Description (IBM doc#: SA22-7204-02)
14 * - Common IO/-Device Commands and Self Description (IBM doc#: SN22-5535)
15 * - ESCON Channel-to-Channel Adapter (IBM doc#: SA22-7203-00)
16 * - ESCON I/O Interface (IBM doc#: SA22-7202-029
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2, or (at your option)
21 * any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 *
32 * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.4 $
33 *
34 */
35
36#ifndef _CTCMAIN_H_
37#define _CTCMAIN_H_
38
39#include <asm/ccwdev.h>
40#include <asm/ccwgroup.h>
41
42#include "ctctty.h"
43#include "fsm.h"
44#include "cu3088.h"
45
46
47/**
48 * CCW commands, used in this driver.
49 */
50#define CCW_CMD_WRITE 0x01
51#define CCW_CMD_READ 0x02
52#define CCW_CMD_SET_EXTENDED 0xc3
53#define CCW_CMD_PREPARE 0xe3
54
55#define CTC_PROTO_S390 0
56#define CTC_PROTO_LINUX 1
57#define CTC_PROTO_LINUX_TTY 2
58#define CTC_PROTO_OS390 3
59#define CTC_PROTO_MAX 3
60
61#define CTC_BUFSIZE_LIMIT 65535
62#define CTC_BUFSIZE_DEFAULT 32768
63
64#define CTC_TIMEOUT_5SEC 5000
65
66#define CTC_INITIAL_BLOCKLEN 2
67
68#define READ 0
69#define WRITE 1
70
71#define CTC_ID_SIZE BUS_ID_SIZE+3
72
73
74struct ctc_profile {
75 unsigned long maxmulti;
76 unsigned long maxcqueue;
77 unsigned long doios_single;
78 unsigned long doios_multi;
79 unsigned long txlen;
80 unsigned long tx_time;
81 struct timespec send_stamp;
82};
83
84/**
85 * Definition of one channel
86 */
87struct channel {
88
89 /**
90 * Pointer to next channel in list.
91 */
92 struct channel *next;
93 char id[CTC_ID_SIZE];
94 struct ccw_device *cdev;
95
96 /**
97 * Type of this channel.
98 * CTC/A or Escon for valid channels.
99 */
100 enum channel_types type;
101
102 /**
103 * Misc. flags. See CHANNEL_FLAGS_... below
104 */
105 __u32 flags;
106
107 /**
108 * The protocol of this channel
109 */
110 __u16 protocol;
111
112 /**
113 * I/O and irq related stuff
114 */
115 struct ccw1 *ccw;
116 struct irb *irb;
117
118 /**
119 * RX/TX buffer size
120 */
121 int max_bufsize;
122
123 /**
124 * Transmit/Receive buffer.
125 */
126 struct sk_buff *trans_skb;
127
128 /**
129 * Universal I/O queue.
130 */
131 struct sk_buff_head io_queue;
132
133 /**
134 * TX queue for collecting skb's during busy.
135 */
136 struct sk_buff_head collect_queue;
137
138 /**
139 * Amount of data in collect_queue.
140 */
141 int collect_len;
142
143 /**
144 * spinlock for collect_queue and collect_len
145 */
146 spinlock_t collect_lock;
147
148 /**
149 * Timer for detecting unresposive
150 * I/O operations.
151 */
152 fsm_timer timer;
153
154 /**
155 * Retry counter for misc. operations.
156 */
157 int retry;
158
159 /**
160 * The finite state machine of this channel
161 */
162 fsm_instance *fsm;
163
164 /**
165 * The corresponding net_device this channel
166 * belongs to.
167 */
168 struct net_device *netdev;
169
170 struct ctc_profile prof;
171
172 unsigned char *trans_skb_data;
173
174 __u16 logflags;
175};
176
177#define CHANNEL_FLAGS_READ 0
178#define CHANNEL_FLAGS_WRITE 1
179#define CHANNEL_FLAGS_INUSE 2
180#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4
181#define CHANNEL_FLAGS_FAILED 8
182#define CHANNEL_FLAGS_WAITIRQ 16
183#define CHANNEL_FLAGS_RWMASK 1
184#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
185
186#define LOG_FLAG_ILLEGALPKT 1
187#define LOG_FLAG_ILLEGALSIZE 2
188#define LOG_FLAG_OVERRUN 4
189#define LOG_FLAG_NOMEM 8
190
191#define CTC_LOGLEVEL_INFO 1
192#define CTC_LOGLEVEL_NOTICE 2
193#define CTC_LOGLEVEL_WARN 4
194#define CTC_LOGLEVEL_EMERG 8
195#define CTC_LOGLEVEL_ERR 16
196#define CTC_LOGLEVEL_DEBUG 32
197#define CTC_LOGLEVEL_CRIT 64
198
199#define CTC_LOGLEVEL_DEFAULT \
200(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT)
201
202#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1)
203
204#define ctc_pr_debug(fmt, arg...) \
205do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0)
206
207#define ctc_pr_info(fmt, arg...) \
208do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0)
209
210#define ctc_pr_notice(fmt, arg...) \
211do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0)
212
213#define ctc_pr_warn(fmt, arg...) \
214do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0)
215
216#define ctc_pr_emerg(fmt, arg...) \
217do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0)
218
219#define ctc_pr_err(fmt, arg...) \
220do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0)
221
222#define ctc_pr_crit(fmt, arg...) \
223do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0)
224
225struct ctc_priv {
226 struct net_device_stats stats;
227 unsigned long tbusy;
228 /**
229 * The finite state machine of this interface.
230 */
231 fsm_instance *fsm;
232 /**
233 * The protocol of this device
234 */
235 __u16 protocol;
236 /**
237 * Timer for restarting after I/O Errors
238 */
239 fsm_timer restart_timer;
240
241 int buffer_size;
242
243 struct channel *channel[2];
244};
245
246/**
247 * Definition of our link level header.
248 */
249struct ll_header {
250 __u16 length;
251 __u16 type;
252 __u16 unused;
253};
254#define LL_HEADER_LENGTH (sizeof(struct ll_header))
255
256/**
257 * Compatibility macros for busy handling
258 * of network devices.
259 */
260static __inline__ void
261ctc_clear_busy(struct net_device * dev)
262{
263 clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
264 if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
265 netif_wake_queue(dev);
266}
267
268static __inline__ int
269ctc_test_and_set_busy(struct net_device * dev)
270{
271 if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
272 netif_stop_queue(dev);
273 return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
274}
275
276#endif
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
index 9257d60c7833..3080393e823d 100644
--- a/drivers/s390/net/ctctty.c
+++ b/drivers/s390/net/ctctty.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: ctctty.c,v 1.26 2004/08/04 11:06:55 mschwide Exp $ 2 * $Id: ctctty.c,v 1.29 2005/04/05 08:50:44 mschwide Exp $
3 * 3 *
4 * CTC / ESCON network driver, tty interface. 4 * CTC / ESCON network driver, tty interface.
5 * 5 *
@@ -1056,8 +1056,7 @@ ctc_tty_close(struct tty_struct *tty, struct file *filp)
1056 info->tty = 0; 1056 info->tty = 0;
1057 tty->closing = 0; 1057 tty->closing = 0;
1058 if (info->blocked_open) { 1058 if (info->blocked_open) {
1059 set_current_state(TASK_INTERRUPTIBLE); 1059 msleep_interruptible(500);
1060 schedule_timeout(HZ/2);
1061 wake_up_interruptible(&info->open_wait); 1060 wake_up_interruptible(&info->open_wait);
1062 } 1061 }
1063 info->flags &= ~(CTC_ASYNC_NORMAL_ACTIVE | CTC_ASYNC_CLOSING); 1062 info->flags &= ~(CTC_ASYNC_NORMAL_ACTIVE | CTC_ASYNC_CLOSING);
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
index 1b0a9f16024c..0075894c71db 100644
--- a/drivers/s390/net/cu3088.c
+++ b/drivers/s390/net/cu3088.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: cu3088.c,v 1.34 2004/06/15 13:16:27 pavlic Exp $ 2 * $Id: cu3088.c,v 1.35 2005/03/30 19:28:52 richtera Exp $
3 * 3 *
4 * CTC / LCS ccw_device driver 4 * CTC / LCS ccw_device driver
5 * 5 *
@@ -39,6 +39,7 @@ const char *cu3088_type[] = {
39 "FICON channel", 39 "FICON channel",
40 "P390 LCS card", 40 "P390 LCS card",
41 "OSA LCS card", 41 "OSA LCS card",
42 "CLAW channel device",
42 "unknown channel type", 43 "unknown channel type",
43 "unsupported channel type", 44 "unsupported channel type",
44}; 45};
@@ -51,6 +52,7 @@ static struct ccw_device_id cu3088_ids[] = {
51 { CCW_DEVICE(0x3088, 0x1e), .driver_info = channel_type_ficon }, 52 { CCW_DEVICE(0x3088, 0x1e), .driver_info = channel_type_ficon },
52 { CCW_DEVICE(0x3088, 0x01), .driver_info = channel_type_p390 }, 53 { CCW_DEVICE(0x3088, 0x01), .driver_info = channel_type_p390 },
53 { CCW_DEVICE(0x3088, 0x60), .driver_info = channel_type_osa2 }, 54 { CCW_DEVICE(0x3088, 0x60), .driver_info = channel_type_osa2 },
55 { CCW_DEVICE(0x3088, 0x61), .driver_info = channel_type_claw },
54 { /* end of list */ } 56 { /* end of list */ }
55}; 57};
56 58
diff --git a/drivers/s390/net/cu3088.h b/drivers/s390/net/cu3088.h
index 0ec49a8b3adc..1753661f702a 100644
--- a/drivers/s390/net/cu3088.h
+++ b/drivers/s390/net/cu3088.h
@@ -23,6 +23,9 @@ enum channel_types {
23 /* Device is a OSA2 card */ 23 /* Device is a OSA2 card */
24 channel_type_osa2, 24 channel_type_osa2,
25 25
26 /* Device is a CLAW channel device */
27 channel_type_claw,
28
26 /* Device is a channel, but we don't know 29 /* Device is a channel, but we don't know
27 * anything about it */ 30 * anything about it */
28 channel_type_unknown, 31 channel_type_unknown,
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index 1ac6563ee3e0..e08e74e16124 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: iucv.c,v 1.43 2005/02/09 14:47:43 braunu Exp $ 2 * $Id: iucv.c,v 1.45 2005/04/26 22:59:06 braunu Exp $
3 * 3 *
4 * IUCV network driver 4 * IUCV network driver
5 * 5 *
@@ -29,7 +29,7 @@
29 * along with this program; if not, write to the Free Software 29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 * 31 *
32 * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.43 $ 32 * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.45 $
33 * 33 *
34 */ 34 */
35 35
@@ -355,7 +355,7 @@ do { \
355static void 355static void
356iucv_banner(void) 356iucv_banner(void)
357{ 357{
358 char vbuf[] = "$Revision: 1.43 $"; 358 char vbuf[] = "$Revision: 1.45 $";
359 char *version = vbuf; 359 char *version = vbuf;
360 360
361 if ((version = strchr(version, ':'))) { 361 if ((version = strchr(version, ':'))) {
@@ -2553,12 +2553,12 @@ EXPORT_SYMBOL (iucv_resume);
2553#endif 2553#endif
2554EXPORT_SYMBOL (iucv_reply_prmmsg); 2554EXPORT_SYMBOL (iucv_reply_prmmsg);
2555EXPORT_SYMBOL (iucv_send); 2555EXPORT_SYMBOL (iucv_send);
2556#if 0
2557EXPORT_SYMBOL (iucv_send2way); 2556EXPORT_SYMBOL (iucv_send2way);
2558EXPORT_SYMBOL (iucv_send2way_array); 2557EXPORT_SYMBOL (iucv_send2way_array);
2559EXPORT_SYMBOL (iucv_send_array);
2560EXPORT_SYMBOL (iucv_send2way_prmmsg); 2558EXPORT_SYMBOL (iucv_send2way_prmmsg);
2561EXPORT_SYMBOL (iucv_send2way_prmmsg_array); 2559EXPORT_SYMBOL (iucv_send2way_prmmsg_array);
2560#if 0
2561EXPORT_SYMBOL (iucv_send_array);
2562EXPORT_SYMBOL (iucv_send_prmmsg); 2562EXPORT_SYMBOL (iucv_send_prmmsg);
2563EXPORT_SYMBOL (iucv_setmask); 2563EXPORT_SYMBOL (iucv_setmask);
2564#endif 2564#endif
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 0f76e945b984..cccfed248e70 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -11,7 +11,7 @@
11 * Frank Pavlic (pavlic@de.ibm.com) and 11 * Frank Pavlic (pavlic@de.ibm.com) and
12 * Martin Schwidefsky <schwidefsky@de.ibm.com> 12 * Martin Schwidefsky <schwidefsky@de.ibm.com>
13 * 13 *
14 * $Revision: 1.96 $ $Date: 2004/11/11 13:42:33 $ 14 * $Revision: 1.98 $ $Date: 2005/04/18 13:41:29 $
15 * 15 *
16 * This program is free software; you can redistribute it and/or modify 16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
@@ -59,7 +59,7 @@
59/** 59/**
60 * initialization string for output 60 * initialization string for output
61 */ 61 */
62#define VERSION_LCS_C "$Revision: 1.96 $" 62#define VERSION_LCS_C "$Revision: 1.98 $"
63 63
64static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")"; 64static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
65static char debug_buffer[255]; 65static char debug_buffer[255];
@@ -1098,14 +1098,6 @@ lcs_check_multicast_support(struct lcs_card *card)
1098 PRINT_ERR("Query IPAssist failed. Assuming unsupported!\n"); 1098 PRINT_ERR("Query IPAssist failed. Assuming unsupported!\n");
1099 return -EOPNOTSUPP; 1099 return -EOPNOTSUPP;
1100 } 1100 }
1101 /* Print out supported assists: IPv6 */
1102 PRINT_INFO("LCS device %s %s IPv6 support\n", card->dev->name,
1103 (card->ip_assists_supported & LCS_IPASS_IPV6_SUPPORT) ?
1104 "with" : "without");
1105 /* Print out supported assist: Multicast */
1106 PRINT_INFO("LCS device %s %s Multicast support\n", card->dev->name,
1107 (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT) ?
1108 "with" : "without");
1109 if (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT) 1101 if (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT)
1110 return 0; 1102 return 0;
1111 return -EOPNOTSUPP; 1103 return -EOPNOTSUPP;
@@ -1160,7 +1152,7 @@ list_modified:
1160 } 1152 }
1161 } 1153 }
1162 /* re-insert all entries from the failed_list into ipm_list */ 1154 /* re-insert all entries from the failed_list into ipm_list */
1163 list_for_each_entry(ipm, &failed_list, list) { 1155 list_for_each_entry_safe(ipm, tmp, &failed_list, list) {
1164 list_del_init(&ipm->list); 1156 list_del_init(&ipm->list);
1165 list_add_tail(&ipm->list, &card->ipm_list); 1157 list_add_tail(&ipm->list, &card->ipm_list);
1166 } 1158 }
@@ -2198,30 +2190,39 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
2198 if (!dev) 2190 if (!dev)
2199 goto out; 2191 goto out;
2200 card->dev = dev; 2192 card->dev = dev;
2201netdev_out:
2202 card->dev->priv = card; 2193 card->dev->priv = card;
2203 card->dev->open = lcs_open_device; 2194 card->dev->open = lcs_open_device;
2204 card->dev->stop = lcs_stop_device; 2195 card->dev->stop = lcs_stop_device;
2205 card->dev->hard_start_xmit = lcs_start_xmit; 2196 card->dev->hard_start_xmit = lcs_start_xmit;
2206 card->dev->get_stats = lcs_getstats; 2197 card->dev->get_stats = lcs_getstats;
2207 SET_MODULE_OWNER(dev); 2198 SET_MODULE_OWNER(dev);
2208 if (lcs_register_netdev(ccwgdev) != 0)
2209 goto out;
2210 memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH); 2199 memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH);
2211#ifdef CONFIG_IP_MULTICAST 2200#ifdef CONFIG_IP_MULTICAST
2212 if (!lcs_check_multicast_support(card)) 2201 if (!lcs_check_multicast_support(card))
2213 card->dev->set_multicast_list = lcs_set_multicast_list; 2202 card->dev->set_multicast_list = lcs_set_multicast_list;
2214#endif 2203#endif
2215 netif_stop_queue(card->dev); 2204netdev_out:
2216 lcs_set_allowed_threads(card,0xffffffff); 2205 lcs_set_allowed_threads(card,0xffffffff);
2217 if (recover_state == DEV_STATE_RECOVER) { 2206 if (recover_state == DEV_STATE_RECOVER) {
2218 lcs_set_multicast_list(card->dev); 2207 lcs_set_multicast_list(card->dev);
2219 card->dev->flags |= IFF_UP; 2208 card->dev->flags |= IFF_UP;
2220 netif_wake_queue(card->dev); 2209 netif_wake_queue(card->dev);
2221 card->state = DEV_STATE_UP; 2210 card->state = DEV_STATE_UP;
2222 } else 2211 } else {
2223 lcs_stopcard(card); 2212 lcs_stopcard(card);
2213 }
2224 2214
2215 if (lcs_register_netdev(ccwgdev) != 0)
2216 goto out;
2217
2218 /* Print out supported assists: IPv6 */
2219 PRINT_INFO("LCS device %s %s IPv6 support\n", card->dev->name,
2220 (card->ip_assists_supported & LCS_IPASS_IPV6_SUPPORT) ?
2221 "with" : "without");
2222 /* Print out supported assist: Multicast */
2223 PRINT_INFO("LCS device %s %s Multicast support\n", card->dev->name,
2224 (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT) ?
2225 "with" : "without");
2225 return 0; 2226 return 0;
2226out: 2227out:
2227 2228
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index a341041a6cf7..a755b57db46b 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -24,7 +24,7 @@
24 24
25#include "qeth_mpc.h" 25#include "qeth_mpc.h"
26 26
27#define VERSION_QETH_H "$Revision: 1.135 $" 27#define VERSION_QETH_H "$Revision: 1.139 $"
28 28
29#ifdef CONFIG_QETH_IPV6 29#ifdef CONFIG_QETH_IPV6
30#define QETH_VERSION_IPV6 ":IPv6" 30#define QETH_VERSION_IPV6 ":IPv6"
@@ -288,7 +288,8 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
288#define QETH_TX_TIMEOUT 100 * HZ 288#define QETH_TX_TIMEOUT 100 * HZ
289#define QETH_HEADER_SIZE 32 289#define QETH_HEADER_SIZE 32
290#define MAX_PORTNO 15 290#define MAX_PORTNO 15
291#define QETH_FAKE_LL_LEN ETH_HLEN 291#define QETH_FAKE_LL_LEN_ETH ETH_HLEN
292#define QETH_FAKE_LL_LEN_TR (sizeof(struct trh_hdr)-TR_MAXRIFLEN+sizeof(struct trllc))
292#define QETH_FAKE_LL_V6_ADDR_POS 24 293#define QETH_FAKE_LL_V6_ADDR_POS 24
293 294
294/*IPv6 address autoconfiguration stuff*/ 295/*IPv6 address autoconfiguration stuff*/
@@ -369,6 +370,25 @@ struct qeth_hdr {
369 } hdr; 370 } hdr;
370} __attribute__ ((packed)); 371} __attribute__ ((packed));
371 372
373/*TCP Segmentation Offload header*/
374struct qeth_hdr_ext_tso {
375 __u16 hdr_tot_len;
376 __u8 imb_hdr_no;
377 __u8 reserved;
378 __u8 hdr_type;
379 __u8 hdr_version;
380 __u16 hdr_len;
381 __u32 payload_len;
382 __u16 mss;
383 __u16 dg_hdr_len;
384 __u8 padding[16];
385} __attribute__ ((packed));
386
387struct qeth_hdr_tso {
388 struct qeth_hdr hdr; /*hdr->hdr.l3.xxx*/
389 struct qeth_hdr_ext_tso ext;
390} __attribute__ ((packed));
391
372 392
373/* flags for qeth_hdr.flags */ 393/* flags for qeth_hdr.flags */
374#define QETH_HDR_PASSTHRU 0x10 394#define QETH_HDR_PASSTHRU 0x10
@@ -866,6 +886,7 @@ qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size)
866 return hdr; 886 return hdr;
867} 887}
868 888
889
869inline static int 890inline static int
870qeth_get_hlen(__u8 link_type) 891qeth_get_hlen(__u8 link_type)
871{ 892{
@@ -873,19 +894,19 @@ qeth_get_hlen(__u8 link_type)
873 switch (link_type) { 894 switch (link_type) {
874 case QETH_LINK_TYPE_HSTR: 895 case QETH_LINK_TYPE_HSTR:
875 case QETH_LINK_TYPE_LANE_TR: 896 case QETH_LINK_TYPE_LANE_TR:
876 return sizeof(struct qeth_hdr) + TR_HLEN; 897 return sizeof(struct qeth_hdr_tso) + TR_HLEN;
877 default: 898 default:
878#ifdef CONFIG_QETH_VLAN 899#ifdef CONFIG_QETH_VLAN
879 return sizeof(struct qeth_hdr) + VLAN_ETH_HLEN; 900 return sizeof(struct qeth_hdr_tso) + VLAN_ETH_HLEN;
880#else 901#else
881 return sizeof(struct qeth_hdr) + ETH_HLEN; 902 return sizeof(struct qeth_hdr_tso) + ETH_HLEN;
882#endif 903#endif
883 } 904 }
884#else /* CONFIG_QETH_IPV6 */ 905#else /* CONFIG_QETH_IPV6 */
885#ifdef CONFIG_QETH_VLAN 906#ifdef CONFIG_QETH_VLAN
886 return sizeof(struct qeth_hdr) + VLAN_HLEN; 907 return sizeof(struct qeth_hdr_tso) + VLAN_HLEN;
887#else 908#else
888 return sizeof(struct qeth_hdr); 909 return sizeof(struct qeth_hdr_tso);
889#endif 910#endif
890#endif /* CONFIG_QETH_IPV6 */ 911#endif /* CONFIG_QETH_IPV6 */
891} 912}
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index 7ee1c06ed68a..f94f1f25eec6 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * 2 *
3 * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.11 $) 3 * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.13 $)
4 * 4 *
5 * Enhanced Device Driver Packing (EDDP) support for the qeth driver. 5 * Enhanced Device Driver Packing (EDDP) support for the qeth driver.
6 * 6 *
@@ -8,7 +8,7 @@
8 * 8 *
9 * Author(s): Thomas Spatzier <tspat@de.ibm.com> 9 * Author(s): Thomas Spatzier <tspat@de.ibm.com>
10 * 10 *
11 * $Revision: 1.11 $ $Date: 2005/03/24 09:04:18 $ 11 * $Revision: 1.13 $ $Date: 2005/05/04 20:19:18 $
12 * 12 *
13 */ 13 */
14#include <linux/config.h> 14#include <linux/config.h>
@@ -85,7 +85,7 @@ void
85qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf) 85qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
86{ 86{
87 struct qeth_eddp_context_reference *ref; 87 struct qeth_eddp_context_reference *ref;
88 88
89 QETH_DBF_TEXT(trace, 6, "eddprctx"); 89 QETH_DBF_TEXT(trace, 6, "eddprctx");
90 while (!list_empty(&buf->ctx_list)){ 90 while (!list_empty(&buf->ctx_list)){
91 ref = list_entry(buf->ctx_list.next, 91 ref = list_entry(buf->ctx_list.next,
@@ -139,7 +139,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
139 "buffer!\n"); 139 "buffer!\n");
140 goto out; 140 goto out;
141 } 141 }
142 } 142 }
143 /* check if the whole next skb fits into current buffer */ 143 /* check if the whole next skb fits into current buffer */
144 if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) - 144 if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) -
145 buf->next_element_to_fill) 145 buf->next_element_to_fill)
@@ -152,7 +152,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
152 * and increment ctx's refcnt */ 152 * and increment ctx's refcnt */
153 must_refcnt = 1; 153 must_refcnt = 1;
154 continue; 154 continue;
155 } 155 }
156 if (must_refcnt){ 156 if (must_refcnt){
157 must_refcnt = 0; 157 must_refcnt = 0;
158 if (qeth_eddp_buf_ref_context(buf, ctx)){ 158 if (qeth_eddp_buf_ref_context(buf, ctx)){
@@ -202,40 +202,29 @@ out:
202 return flush_cnt; 202 return flush_cnt;
203} 203}
204 204
205static inline int
206qeth_get_skb_data_len(struct sk_buff *skb)
207{
208 int len = skb->len;
209 int i;
210
211 for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i)
212 len -= skb_shinfo(skb)->frags[i].size;
213 return len;
214}
215
216static inline void 205static inline void
217qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, 206qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
218 struct qeth_eddp_data *eddp) 207 struct qeth_eddp_data *eddp, int data_len)
219{ 208{
220 u8 *page; 209 u8 *page;
221 int page_remainder; 210 int page_remainder;
222 int page_offset; 211 int page_offset;
223 int hdr_len; 212 int pkt_len;
224 struct qeth_eddp_element *element; 213 struct qeth_eddp_element *element;
225 214
226 QETH_DBF_TEXT(trace, 5, "eddpcrsh"); 215 QETH_DBF_TEXT(trace, 5, "eddpcrsh");
227 page = ctx->pages[ctx->offset >> PAGE_SHIFT]; 216 page = ctx->pages[ctx->offset >> PAGE_SHIFT];
228 page_offset = ctx->offset % PAGE_SIZE; 217 page_offset = ctx->offset % PAGE_SIZE;
229 element = &ctx->elements[ctx->num_elements]; 218 element = &ctx->elements[ctx->num_elements];
230 hdr_len = eddp->nhl + eddp->thl; 219 pkt_len = eddp->nhl + eddp->thl + data_len;
231 /* FIXME: layer2 and VLAN !!! */ 220 /* FIXME: layer2 and VLAN !!! */
232 if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) 221 if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
233 hdr_len += ETH_HLEN; 222 pkt_len += ETH_HLEN;
234 if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) 223 if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
235 hdr_len += VLAN_HLEN; 224 pkt_len += VLAN_HLEN;
236 /* does complete header fit in current page ? */ 225 /* does complete packet fit in current page ? */
237 page_remainder = PAGE_SIZE - page_offset; 226 page_remainder = PAGE_SIZE - page_offset;
238 if (page_remainder < (sizeof(struct qeth_hdr) + hdr_len)){ 227 if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)){
239 /* no -> go to start of next page */ 228 /* no -> go to start of next page */
240 ctx->offset += page_remainder; 229 ctx->offset += page_remainder;
241 page = ctx->pages[ctx->offset >> PAGE_SHIFT]; 230 page = ctx->pages[ctx->offset >> PAGE_SHIFT];
@@ -281,7 +270,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
281 int left_in_frag; 270 int left_in_frag;
282 int copy_len; 271 int copy_len;
283 u8 *src; 272 u8 *src;
284 273
285 QETH_DBF_TEXT(trace, 5, "eddpcdtc"); 274 QETH_DBF_TEXT(trace, 5, "eddpcdtc");
286 if (skb_shinfo(eddp->skb)->nr_frags == 0) { 275 if (skb_shinfo(eddp->skb)->nr_frags == 0) {
287 memcpy(dst, eddp->skb->data + eddp->skb_offset, len); 276 memcpy(dst, eddp->skb->data + eddp->skb_offset, len);
@@ -292,7 +281,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
292 while (len > 0) { 281 while (len > 0) {
293 if (eddp->frag < 0) { 282 if (eddp->frag < 0) {
294 /* we're in skb->data */ 283 /* we're in skb->data */
295 left_in_frag = qeth_get_skb_data_len(eddp->skb) 284 left_in_frag = (eddp->skb->len - eddp->skb->data_len)
296 - eddp->skb_offset; 285 - eddp->skb_offset;
297 src = eddp->skb->data + eddp->skb_offset; 286 src = eddp->skb->data + eddp->skb_offset;
298 } else { 287 } else {
@@ -424,7 +413,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
424 struct tcphdr *tcph; 413 struct tcphdr *tcph;
425 int data_len; 414 int data_len;
426 u32 hcsum; 415 u32 hcsum;
427 416
428 QETH_DBF_TEXT(trace, 5, "eddpftcp"); 417 QETH_DBF_TEXT(trace, 5, "eddpftcp");
429 eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl; 418 eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
430 tcph = eddp->skb->h.th; 419 tcph = eddp->skb->h.th;
@@ -464,7 +453,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
464 else 453 else
465 hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len); 454 hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len);
466 /* fill the next segment into the context */ 455 /* fill the next segment into the context */
467 qeth_eddp_create_segment_hdrs(ctx, eddp); 456 qeth_eddp_create_segment_hdrs(ctx, eddp, data_len);
468 qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum); 457 qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum);
469 if (eddp->skb_offset >= eddp->skb->len) 458 if (eddp->skb_offset >= eddp->skb->len)
470 break; 459 break;
@@ -474,13 +463,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
474 eddp->th.tcp.h.seq += data_len; 463 eddp->th.tcp.h.seq += data_len;
475 } 464 }
476} 465}
477 466
478static inline int 467static inline int
479qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, 468qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
480 struct sk_buff *skb, struct qeth_hdr *qhdr) 469 struct sk_buff *skb, struct qeth_hdr *qhdr)
481{ 470{
482 struct qeth_eddp_data *eddp = NULL; 471 struct qeth_eddp_data *eddp = NULL;
483 472
484 QETH_DBF_TEXT(trace, 5, "eddpficx"); 473 QETH_DBF_TEXT(trace, 5, "eddpficx");
485 /* create our segmentation headers and copy original headers */ 474 /* create our segmentation headers and copy original headers */
486 if (skb->protocol == ETH_P_IP) 475 if (skb->protocol == ETH_P_IP)
@@ -520,7 +509,7 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
520 int hdr_len) 509 int hdr_len)
521{ 510{
522 int skbs_per_page; 511 int skbs_per_page;
523 512
524 QETH_DBF_TEXT(trace, 5, "eddpcanp"); 513 QETH_DBF_TEXT(trace, 5, "eddpcanp");
525 /* can we put multiple skbs in one page? */ 514 /* can we put multiple skbs in one page? */
526 skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len); 515 skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
@@ -600,7 +589,7 @@ qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
600 struct qeth_hdr *qhdr) 589 struct qeth_hdr *qhdr)
601{ 590{
602 struct qeth_eddp_context *ctx = NULL; 591 struct qeth_eddp_context *ctx = NULL;
603 592
604 QETH_DBF_TEXT(trace, 5, "creddpct"); 593 QETH_DBF_TEXT(trace, 5, "creddpct");
605 if (skb->protocol == ETH_P_IP) 594 if (skb->protocol == ETH_P_IP)
606 ctx = qeth_eddp_create_context_generic(card, skb, 595 ctx = qeth_eddp_create_context_generic(card, skb,
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 607b92542df6..208127a5033a 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * 2 *
3 * linux/drivers/s390/net/qeth_main.c ($Revision: 1.206 $) 3 * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $)
4 * 4 *
5 * Linux on zSeries OSA Express and HiperSockets support 5 * Linux on zSeries OSA Express and HiperSockets support
6 * 6 *
@@ -12,7 +12,7 @@
12 * Frank Pavlic (pavlic@de.ibm.com) and 12 * Frank Pavlic (pavlic@de.ibm.com) and
13 * Thomas Spatzier <tspat@de.ibm.com> 13 * Thomas Spatzier <tspat@de.ibm.com>
14 * 14 *
15 * $Revision: 1.206 $ $Date: 2005/03/24 09:04:18 $ 15 * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $
16 * 16 *
17 * This program is free software; you can redistribute it and/or modify 17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by 18 * it under the terms of the GNU General Public License as published by
@@ -80,7 +80,7 @@ qeth_eyecatcher(void)
80#include "qeth_eddp.h" 80#include "qeth_eddp.h"
81#include "qeth_tso.h" 81#include "qeth_tso.h"
82 82
83#define VERSION_QETH_C "$Revision: 1.206 $" 83#define VERSION_QETH_C "$Revision: 1.214 $"
84static const char *version = "qeth S/390 OSA-Express driver"; 84static const char *version = "qeth S/390 OSA-Express driver";
85 85
86/** 86/**
@@ -158,6 +158,9 @@ qeth_irq_tasklet(unsigned long);
158static int 158static int
159qeth_set_online(struct ccwgroup_device *); 159qeth_set_online(struct ccwgroup_device *);
160 160
161static int
162__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode);
163
161static struct qeth_ipaddr * 164static struct qeth_ipaddr *
162qeth_get_addr_buffer(enum qeth_prot_versions); 165qeth_get_addr_buffer(enum qeth_prot_versions);
163 166
@@ -510,10 +513,10 @@ qeth_irq_tasklet(unsigned long data)
510 wake_up(&card->wait_q); 513 wake_up(&card->wait_q);
511} 514}
512 515
513static int qeth_stop_card(struct qeth_card *); 516static int qeth_stop_card(struct qeth_card *, int);
514 517
515static int 518static int
516qeth_set_offline(struct ccwgroup_device *cgdev) 519__qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
517{ 520{
518 struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data; 521 struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
519 int rc = 0; 522 int rc = 0;
@@ -523,7 +526,7 @@ qeth_set_offline(struct ccwgroup_device *cgdev)
523 QETH_DBF_HEX(setup, 3, &card, sizeof(void *)); 526 QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
524 527
525 recover_flag = card->state; 528 recover_flag = card->state;
526 if (qeth_stop_card(card) == -ERESTARTSYS){ 529 if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){
527 PRINT_WARN("Stopping card %s interrupted by user!\n", 530 PRINT_WARN("Stopping card %s interrupted by user!\n",
528 CARD_BUS_ID(card)); 531 CARD_BUS_ID(card));
529 return -ERESTARTSYS; 532 return -ERESTARTSYS;
@@ -540,6 +543,12 @@ qeth_set_offline(struct ccwgroup_device *cgdev)
540} 543}
541 544
542static int 545static int
546qeth_set_offline(struct ccwgroup_device *cgdev)
547{
548 return __qeth_set_offline(cgdev, 0);
549}
550
551static int
543qeth_wait_for_threads(struct qeth_card *card, unsigned long threads); 552qeth_wait_for_threads(struct qeth_card *card, unsigned long threads);
544 553
545 554
@@ -953,8 +962,8 @@ qeth_recover(void *ptr)
953 PRINT_WARN("Recovery of device %s started ...\n", 962 PRINT_WARN("Recovery of device %s started ...\n",
954 CARD_BUS_ID(card)); 963 CARD_BUS_ID(card));
955 card->use_hard_stop = 1; 964 card->use_hard_stop = 1;
956 qeth_set_offline(card->gdev); 965 __qeth_set_offline(card->gdev,1);
957 rc = qeth_set_online(card->gdev); 966 rc = __qeth_set_online(card->gdev,1);
958 if (!rc) 967 if (!rc)
959 PRINT_INFO("Device %s successfully recovered!\n", 968 PRINT_INFO("Device %s successfully recovered!\n",
960 CARD_BUS_ID(card)); 969 CARD_BUS_ID(card));
@@ -2152,9 +2161,15 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
2152 if (!skb_len) 2161 if (!skb_len)
2153 return NULL; 2162 return NULL;
2154 if (card->options.fake_ll){ 2163 if (card->options.fake_ll){
2155 if (!(skb = qeth_get_skb(skb_len + QETH_FAKE_LL_LEN))) 2164 if(card->dev->type == ARPHRD_IEEE802_TR){
2156 goto no_mem; 2165 if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR)))
2157 skb_pull(skb, QETH_FAKE_LL_LEN); 2166 goto no_mem;
2167 skb_reserve(skb,QETH_FAKE_LL_LEN_TR);
2168 } else {
2169 if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH)))
2170 goto no_mem;
2171 skb_reserve(skb,QETH_FAKE_LL_LEN_ETH);
2172 }
2158 } else if (!(skb = qeth_get_skb(skb_len))) 2173 } else if (!(skb = qeth_get_skb(skb_len)))
2159 goto no_mem; 2174 goto no_mem;
2160 data_ptr = element->addr + offset; 2175 data_ptr = element->addr + offset;
@@ -2229,14 +2244,68 @@ qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
2229} 2244}
2230 2245
2231static inline void 2246static inline void
2232qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, 2247qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb,
2248 struct qeth_hdr *hdr)
2249{
2250 struct trh_hdr *fake_hdr;
2251 struct trllc *fake_llc;
2252 struct iphdr *ip_hdr;
2253
2254 QETH_DBF_TEXT(trace,5,"skbfktr");
2255 skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_TR;
2256 /* this is a fake ethernet header */
2257 fake_hdr = (struct trh_hdr *) skb->mac.raw;
2258
2259 /* the destination MAC address */
2260 switch (skb->pkt_type){
2261 case PACKET_MULTICAST:
2262 switch (skb->protocol){
2263#ifdef CONFIG_QETH_IPV6
2264 case __constant_htons(ETH_P_IPV6):
2265 ndisc_mc_map((struct in6_addr *)
2266 skb->data + QETH_FAKE_LL_V6_ADDR_POS,
2267 fake_hdr->daddr, card->dev, 0);
2268 break;
2269#endif /* CONFIG_QETH_IPV6 */
2270 case __constant_htons(ETH_P_IP):
2271 ip_hdr = (struct iphdr *)skb->data;
2272 ip_tr_mc_map(ip_hdr->daddr, fake_hdr->daddr);
2273 break;
2274 default:
2275 memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
2276 }
2277 break;
2278 case PACKET_BROADCAST:
2279 memset(fake_hdr->daddr, 0xff, TR_ALEN);
2280 break;
2281 default:
2282 memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
2283 }
2284 /* the source MAC address */
2285 if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
2286 memcpy(fake_hdr->saddr, &hdr->hdr.l3.dest_addr[2], TR_ALEN);
2287 else
2288 memset(fake_hdr->saddr, 0, TR_ALEN);
2289 fake_hdr->rcf=0;
2290 fake_llc = (struct trllc*)&(fake_hdr->rcf);
2291 fake_llc->dsap = EXTENDED_SAP;
2292 fake_llc->ssap = EXTENDED_SAP;
2293 fake_llc->llc = UI_CMD;
2294 fake_llc->protid[0] = 0;
2295 fake_llc->protid[1] = 0;
2296 fake_llc->protid[2] = 0;
2297 fake_llc->ethertype = ETH_P_IP;
2298}
2299
2300static inline void
2301qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb,
2233 struct qeth_hdr *hdr) 2302 struct qeth_hdr *hdr)
2234{ 2303{
2235 struct ethhdr *fake_hdr; 2304 struct ethhdr *fake_hdr;
2236 struct iphdr *ip_hdr; 2305 struct iphdr *ip_hdr;
2237 2306
2238 QETH_DBF_TEXT(trace,5,"skbfake"); 2307 QETH_DBF_TEXT(trace,5,"skbfketh");
2239 skb->mac.raw = skb->data - QETH_FAKE_LL_LEN; 2308 skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_ETH;
2240 /* this is a fake ethernet header */ 2309 /* this is a fake ethernet header */
2241 fake_hdr = (struct ethhdr *) skb->mac.raw; 2310 fake_hdr = (struct ethhdr *) skb->mac.raw;
2242 2311
@@ -2253,10 +2322,7 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
2253#endif /* CONFIG_QETH_IPV6 */ 2322#endif /* CONFIG_QETH_IPV6 */
2254 case __constant_htons(ETH_P_IP): 2323 case __constant_htons(ETH_P_IP):
2255 ip_hdr = (struct iphdr *)skb->data; 2324 ip_hdr = (struct iphdr *)skb->data;
2256 if (card->dev->type == ARPHRD_IEEE802_TR) 2325 ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest);
2257 ip_tr_mc_map(ip_hdr->daddr, fake_hdr->h_dest);
2258 else
2259 ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest);
2260 break; 2326 break;
2261 default: 2327 default:
2262 memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN); 2328 memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN);
@@ -2278,6 +2344,16 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
2278} 2344}
2279 2345
2280static inline void 2346static inline void
2347qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
2348 struct qeth_hdr *hdr)
2349{
2350 if (card->dev->type == ARPHRD_IEEE802_TR)
2351 qeth_rebuild_skb_fake_ll_tr(card, skb, hdr);
2352 else
2353 qeth_rebuild_skb_fake_ll_eth(card, skb, hdr);
2354}
2355
2356static inline void
2281qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb, 2357qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb,
2282 struct qeth_hdr *hdr) 2358 struct qeth_hdr *hdr)
2283{ 2359{
@@ -3440,16 +3516,25 @@ qeth_fake_header(struct sk_buff *skb, struct net_device *dev,
3440 unsigned short type, void *daddr, void *saddr, 3516 unsigned short type, void *daddr, void *saddr,
3441 unsigned len) 3517 unsigned len)
3442{ 3518{
3443 struct ethhdr *hdr; 3519 if(dev->type == ARPHRD_IEEE802_TR){
3520 struct trh_hdr *hdr;
3521 hdr = (struct trh_hdr *)skb_push(skb, QETH_FAKE_LL_LEN_TR);
3522 memcpy(hdr->saddr, dev->dev_addr, TR_ALEN);
3523 memcpy(hdr->daddr, "FAKELL", TR_ALEN);
3524 return QETH_FAKE_LL_LEN_TR;
3525
3526 } else {
3527 struct ethhdr *hdr;
3528 hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN_ETH);
3529 memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN);
3530 memcpy(hdr->h_dest, "FAKELL", ETH_ALEN);
3531 if (type != ETH_P_802_3)
3532 hdr->h_proto = htons(type);
3533 else
3534 hdr->h_proto = htons(len);
3535 return QETH_FAKE_LL_LEN_ETH;
3444 3536
3445 hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN); 3537 }
3446 memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN);
3447 memcpy(hdr->h_dest, "FAKELL", ETH_ALEN);
3448 if (type != ETH_P_802_3)
3449 hdr->h_proto = htons(type);
3450 else
3451 hdr->h_proto = htons(len);
3452 return QETH_FAKE_LL_LEN;
3453} 3538}
3454 3539
3455static inline int 3540static inline int
@@ -3710,16 +3795,12 @@ static inline int
3710qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, 3795qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
3711 struct qeth_hdr **hdr, int ipv) 3796 struct qeth_hdr **hdr, int ipv)
3712{ 3797{
3713 int rc = 0;
3714#ifdef CONFIG_QETH_VLAN 3798#ifdef CONFIG_QETH_VLAN
3715 u16 *tag; 3799 u16 *tag;
3716#endif 3800#endif
3717 3801
3718 QETH_DBF_TEXT(trace, 6, "prepskb"); 3802 QETH_DBF_TEXT(trace, 6, "prepskb");
3719 3803
3720 rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
3721 if (rc)
3722 return rc;
3723#ifdef CONFIG_QETH_VLAN 3804#ifdef CONFIG_QETH_VLAN
3724 if (card->vlangrp && vlan_tx_tag_present(*skb) && 3805 if (card->vlangrp && vlan_tx_tag_present(*skb) &&
3725 ((ipv == 6) || card->options.layer2) ) { 3806 ((ipv == 6) || card->options.layer2) ) {
@@ -3882,9 +3963,15 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
3882 memcpy(hdr->hdr.l3.dest_addr, &skb->nh.ipv6h->daddr, 16); 3963 memcpy(hdr->hdr.l3.dest_addr, &skb->nh.ipv6h->daddr, 16);
3883 } 3964 }
3884 } else { /* passthrough */ 3965 } else { /* passthrough */
3885 if (!memcmp(skb->data + sizeof(struct qeth_hdr), 3966 if((skb->dev->type == ARPHRD_IEEE802_TR) &&
3967 !memcmp(skb->data + sizeof(struct qeth_hdr) +
3968 sizeof(__u16), skb->dev->broadcast, 6)) {
3969 hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
3970 QETH_HDR_PASSTHRU;
3971 } else if (!memcmp(skb->data + sizeof(struct qeth_hdr),
3886 skb->dev->broadcast, 6)) { /* broadcast? */ 3972 skb->dev->broadcast, 6)) { /* broadcast? */
3887 hdr->hdr.l3.flags = QETH_CAST_BROADCAST | QETH_HDR_PASSTHRU; 3973 hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
3974 QETH_HDR_PASSTHRU;
3888 } else { 3975 } else {
3889 hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ? 3976 hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ?
3890 QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU : 3977 QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU :
@@ -3894,67 +3981,29 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
3894} 3981}
3895 3982
3896static inline void 3983static inline void
3897__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
3898 int *next_element_to_fill)
3899{
3900 int length = skb->len;
3901 struct skb_frag_struct *frag;
3902 int fragno;
3903 unsigned long addr;
3904 int element;
3905 int first_lap = 1;
3906
3907 fragno = skb_shinfo(skb)->nr_frags; /* start with last frag */
3908 element = *next_element_to_fill + fragno;
3909 while (length > 0) {
3910 if (fragno > 0) {
3911 frag = &skb_shinfo(skb)->frags[fragno - 1];
3912 addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
3913 frag->page_offset;
3914 buffer->element[element].addr = (char *)addr;
3915 buffer->element[element].length = frag->size;
3916 length -= frag->size;
3917 if (first_lap)
3918 buffer->element[element].flags =
3919 SBAL_FLAGS_LAST_FRAG;
3920 else
3921 buffer->element[element].flags =
3922 SBAL_FLAGS_MIDDLE_FRAG;
3923 } else {
3924 buffer->element[element].addr = skb->data;
3925 buffer->element[element].length = length;
3926 length = 0;
3927 buffer->element[element].flags =
3928 SBAL_FLAGS_FIRST_FRAG;
3929 }
3930 element--;
3931 fragno--;
3932 first_lap = 0;
3933 }
3934 *next_element_to_fill += skb_shinfo(skb)->nr_frags + 1;
3935}
3936
3937static inline void
3938__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, 3984__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
3939 int *next_element_to_fill) 3985 int is_tso, int *next_element_to_fill)
3940{ 3986{
3941 int length = skb->len; 3987 int length = skb->len;
3942 int length_here; 3988 int length_here;
3943 int element; 3989 int element;
3944 char *data; 3990 char *data;
3945 int first_lap = 1; 3991 int first_lap ;
3946 3992
3947 element = *next_element_to_fill; 3993 element = *next_element_to_fill;
3948 data = skb->data; 3994 data = skb->data;
3995 first_lap = (is_tso == 0 ? 1 : 0);
3996
3949 while (length > 0) { 3997 while (length > 0) {
3950 /* length_here is the remaining amount of data in this page */ 3998 /* length_here is the remaining amount of data in this page */
3951 length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE); 3999 length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
3952 if (length < length_here) 4000 if (length < length_here)
3953 length_here = length; 4001 length_here = length;
4002
3954 buffer->element[element].addr = data; 4003 buffer->element[element].addr = data;
3955 buffer->element[element].length = length_here; 4004 buffer->element[element].length = length_here;
3956 length -= length_here; 4005 length -= length_here;
3957 if (!length){ 4006 if (!length) {
3958 if (first_lap) 4007 if (first_lap)
3959 buffer->element[element].flags = 0; 4008 buffer->element[element].flags = 0;
3960 else 4009 else
@@ -3981,17 +4030,35 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue,
3981 struct sk_buff *skb) 4030 struct sk_buff *skb)
3982{ 4031{
3983 struct qdio_buffer *buffer; 4032 struct qdio_buffer *buffer;
3984 int flush_cnt = 0; 4033 struct qeth_hdr_tso *hdr;
4034 int flush_cnt = 0, hdr_len, large_send = 0;
3985 4035
3986 QETH_DBF_TEXT(trace, 6, "qdfillbf"); 4036 QETH_DBF_TEXT(trace, 6, "qdfillbf");
4037
3987 buffer = buf->buffer; 4038 buffer = buf->buffer;
3988 atomic_inc(&skb->users); 4039 atomic_inc(&skb->users);
3989 skb_queue_tail(&buf->skb_list, skb); 4040 skb_queue_tail(&buf->skb_list, skb);
4041
4042 hdr = (struct qeth_hdr_tso *) skb->data;
4043 /*check first on TSO ....*/
4044 if (hdr->hdr.hdr.l3.id == QETH_HEADER_TYPE_TSO) {
4045 int element = buf->next_element_to_fill;
4046
4047 hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
4048 /*fill first buffer entry only with header information */
4049 buffer->element[element].addr = skb->data;
4050 buffer->element[element].length = hdr_len;
4051 buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
4052 buf->next_element_to_fill++;
4053 skb->data += hdr_len;
4054 skb->len -= hdr_len;
4055 large_send = 1;
4056 }
3990 if (skb_shinfo(skb)->nr_frags == 0) 4057 if (skb_shinfo(skb)->nr_frags == 0)
3991 __qeth_fill_buffer(skb, buffer, 4058 __qeth_fill_buffer(skb, buffer, large_send,
3992 (int *)&buf->next_element_to_fill); 4059 (int *)&buf->next_element_to_fill);
3993 else 4060 else
3994 __qeth_fill_buffer_frag(skb, buffer, 4061 __qeth_fill_buffer_frag(skb, buffer, large_send,
3995 (int *)&buf->next_element_to_fill); 4062 (int *)&buf->next_element_to_fill);
3996 4063
3997 if (!queue->do_pack) { 4064 if (!queue->do_pack) {
@@ -4184,6 +4251,25 @@ out:
4184} 4251}
4185 4252
4186static inline int 4253static inline int
4254qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
4255{
4256 int elements_needed = 0;
4257
4258 if (skb_shinfo(skb)->nr_frags > 0) {
4259 elements_needed = (skb_shinfo(skb)->nr_frags + 1);
4260 }
4261 if (elements_needed == 0 )
4262 elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
4263 + skb->len) >> PAGE_SHIFT);
4264 if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
4265 PRINT_ERR("qeth_do_send_packet: invalid size of "
4266 "IP packet. Discarded.");
4267 return 0;
4268 }
4269 return elements_needed;
4270}
4271
4272static inline int
4187qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) 4273qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
4188{ 4274{
4189 int ipv = 0; 4275 int ipv = 0;
@@ -4205,7 +4291,11 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
4205 dev_kfree_skb_irq(skb); 4291 dev_kfree_skb_irq(skb);
4206 return 0; 4292 return 0;
4207 } 4293 }
4208 skb_pull(skb, QETH_FAKE_LL_LEN); 4294 if(card->dev->type == ARPHRD_IEEE802_TR){
4295 skb_pull(skb, QETH_FAKE_LL_LEN_TR);
4296 } else {
4297 skb_pull(skb, QETH_FAKE_LL_LEN_ETH);
4298 }
4209 } 4299 }
4210 } 4300 }
4211 cast_type = qeth_get_cast_type(card, skb); 4301 cast_type = qeth_get_cast_type(card, skb);
@@ -4221,19 +4311,25 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
4221 if (skb_shinfo(skb)->tso_size) 4311 if (skb_shinfo(skb)->tso_size)
4222 large_send = card->options.large_send; 4312 large_send = card->options.large_send;
4223 4313
4224 if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))){
4225 QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc);
4226 return rc;
4227 }
4228 /*are we able to do TSO ? If so ,prepare and send it from here */ 4314 /*are we able to do TSO ? If so ,prepare and send it from here */
4229 if ((large_send == QETH_LARGE_SEND_TSO) && 4315 if ((large_send == QETH_LARGE_SEND_TSO) &&
4230 (cast_type == RTN_UNSPEC)) { 4316 (cast_type == RTN_UNSPEC)) {
4231 rc = qeth_tso_send_packet(card, skb, queue, 4317 rc = qeth_tso_prepare_packet(card, skb, ipv, cast_type);
4232 ipv, cast_type); 4318 if (rc) {
4233 goto do_statistics; 4319 card->stats.tx_dropped++;
4320 card->stats.tx_errors++;
4321 dev_kfree_skb_any(skb);
4322 return NETDEV_TX_OK;
4323 }
4324 elements_needed++;
4325 } else {
4326 if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))) {
4327 QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc);
4328 return rc;
4329 }
4330 qeth_fill_header(card, hdr, skb, ipv, cast_type);
4234 } 4331 }
4235 4332
4236 qeth_fill_header(card, hdr, skb, ipv, cast_type);
4237 if (large_send == QETH_LARGE_SEND_EDDP) { 4333 if (large_send == QETH_LARGE_SEND_EDDP) {
4238 ctx = qeth_eddp_create_context(card, skb, hdr); 4334 ctx = qeth_eddp_create_context(card, skb, hdr);
4239 if (ctx == NULL) { 4335 if (ctx == NULL) {
@@ -4241,7 +4337,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
4241 return -EINVAL; 4337 return -EINVAL;
4242 } 4338 }
4243 } else { 4339 } else {
4244 elements_needed = qeth_get_elements_no(card,(void*) hdr, skb); 4340 elements_needed += qeth_get_elements_no(card,(void*) hdr, skb);
4245 if (!elements_needed) 4341 if (!elements_needed)
4246 return -EINVAL; 4342 return -EINVAL;
4247 } 4343 }
@@ -4252,12 +4348,12 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
4252 else 4348 else
4253 rc = qeth_do_send_packet_fast(card, queue, skb, hdr, 4349 rc = qeth_do_send_packet_fast(card, queue, skb, hdr,
4254 elements_needed, ctx); 4350 elements_needed, ctx);
4255do_statistics:
4256 if (!rc){ 4351 if (!rc){
4257 card->stats.tx_packets++; 4352 card->stats.tx_packets++;
4258 card->stats.tx_bytes += skb->len; 4353 card->stats.tx_bytes += skb->len;
4259#ifdef CONFIG_QETH_PERF_STATS 4354#ifdef CONFIG_QETH_PERF_STATS
4260 if (skb_shinfo(skb)->tso_size) { 4355 if (skb_shinfo(skb)->tso_size &&
4356 !(large_send == QETH_LARGE_SEND_NO)) {
4261 card->perf_stats.large_send_bytes += skb->len; 4357 card->perf_stats.large_send_bytes += skb->len;
4262 card->perf_stats.large_send_cnt++; 4358 card->perf_stats.large_send_cnt++;
4263 } 4359 }
@@ -7154,7 +7250,7 @@ qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
7154} 7250}
7155 7251
7156static int 7252static int
7157qeth_stop_card(struct qeth_card *card) 7253qeth_stop_card(struct qeth_card *card, int recovery_mode)
7158{ 7254{
7159 int rc = 0; 7255 int rc = 0;
7160 7256
@@ -7167,9 +7263,13 @@ qeth_stop_card(struct qeth_card *card)
7167 if (card->read.state == CH_STATE_UP && 7263 if (card->read.state == CH_STATE_UP &&
7168 card->write.state == CH_STATE_UP && 7264 card->write.state == CH_STATE_UP &&
7169 (card->state == CARD_STATE_UP)) { 7265 (card->state == CARD_STATE_UP)) {
7170 rtnl_lock(); 7266 if(recovery_mode) {
7171 dev_close(card->dev); 7267 qeth_stop(card->dev);
7172 rtnl_unlock(); 7268 } else {
7269 rtnl_lock();
7270 dev_close(card->dev);
7271 rtnl_unlock();
7272 }
7173 if (!card->use_hard_stop) { 7273 if (!card->use_hard_stop) {
7174 __u8 *mac = &card->dev->dev_addr[0]; 7274 __u8 *mac = &card->dev->dev_addr[0];
7175 rc = qeth_layer2_send_delmac(card, mac); 7275 rc = qeth_layer2_send_delmac(card, mac);
@@ -7341,13 +7441,17 @@ qeth_register_netdev(struct qeth_card *card)
7341} 7441}
7342 7442
7343static void 7443static void
7344qeth_start_again(struct qeth_card *card) 7444qeth_start_again(struct qeth_card *card, int recovery_mode)
7345{ 7445{
7346 QETH_DBF_TEXT(setup ,2, "startag"); 7446 QETH_DBF_TEXT(setup ,2, "startag");
7347 7447
7348 rtnl_lock(); 7448 if(recovery_mode) {
7349 dev_open(card->dev); 7449 qeth_open(card->dev);
7350 rtnl_unlock(); 7450 } else {
7451 rtnl_lock();
7452 dev_open(card->dev);
7453 rtnl_unlock();
7454 }
7351 /* this also sets saved unicast addresses */ 7455 /* this also sets saved unicast addresses */
7352 qeth_set_multicast_list(card->dev); 7456 qeth_set_multicast_list(card->dev);
7353} 7457}
@@ -7404,7 +7508,7 @@ static void qeth_make_parameters_consistent(struct qeth_card *card)
7404 7508
7405 7509
7406static int 7510static int
7407qeth_set_online(struct ccwgroup_device *gdev) 7511__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
7408{ 7512{
7409 struct qeth_card *card = gdev->dev.driver_data; 7513 struct qeth_card *card = gdev->dev.driver_data;
7410 int rc = 0; 7514 int rc = 0;
@@ -7464,12 +7568,12 @@ qeth_set_online(struct ccwgroup_device *gdev)
7464 * we can also use this state for recovery purposes*/ 7568 * we can also use this state for recovery purposes*/
7465 qeth_set_allowed_threads(card, 0xffffffff, 0); 7569 qeth_set_allowed_threads(card, 0xffffffff, 0);
7466 if (recover_flag == CARD_STATE_RECOVER) 7570 if (recover_flag == CARD_STATE_RECOVER)
7467 qeth_start_again(card); 7571 qeth_start_again(card, recovery_mode);
7468 qeth_notify_processes(); 7572 qeth_notify_processes();
7469 return 0; 7573 return 0;
7470out_remove: 7574out_remove:
7471 card->use_hard_stop = 1; 7575 card->use_hard_stop = 1;
7472 qeth_stop_card(card); 7576 qeth_stop_card(card, 0);
7473 ccw_device_set_offline(CARD_DDEV(card)); 7577 ccw_device_set_offline(CARD_DDEV(card));
7474 ccw_device_set_offline(CARD_WDEV(card)); 7578 ccw_device_set_offline(CARD_WDEV(card));
7475 ccw_device_set_offline(CARD_RDEV(card)); 7579 ccw_device_set_offline(CARD_RDEV(card));
@@ -7480,6 +7584,12 @@ out_remove:
7480 return -ENODEV; 7584 return -ENODEV;
7481} 7585}
7482 7586
7587static int
7588qeth_set_online(struct ccwgroup_device *gdev)
7589{
7590 return __qeth_set_online(gdev, 0);
7591}
7592
7483static struct ccw_device_id qeth_ids[] = { 7593static struct ccw_device_id qeth_ids[] = {
7484 {CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE}, 7594 {CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE},
7485 {CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD}, 7595 {CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD},
diff --git a/drivers/s390/net/qeth_tso.c b/drivers/s390/net/qeth_tso.c
deleted file mode 100644
index c91976274e7b..000000000000
--- a/drivers/s390/net/qeth_tso.c
+++ /dev/null
@@ -1,285 +0,0 @@
1/*
2 * linux/drivers/s390/net/qeth_tso.c ($Revision: 1.6 $)
3 *
4 * Header file for qeth TCP Segmentation Offload support.
5 *
6 * Copyright 2004 IBM Corporation
7 *
8 * Author(s): Frank Pavlic <pavlic@de.ibm.com>
9 *
10 * $Revision: 1.6 $ $Date: 2005/03/24 09:04:18 $
11 *
12 */
13
14#include <linux/skbuff.h>
15#include <linux/tcp.h>
16#include <linux/ip.h>
17#include <linux/ipv6.h>
18#include <net/ip6_checksum.h>
19#include "qeth.h"
20#include "qeth_mpc.h"
21#include "qeth_tso.h"
22
23/**
24 * skb already partially prepared
25 * classic qdio header in skb->data
26 * */
27static inline struct qeth_hdr_tso *
28qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb)
29{
30 int rc = 0;
31
32 QETH_DBF_TEXT(trace, 5, "tsoprsk");
33 rc = qeth_realloc_headroom(card, skb,sizeof(struct qeth_hdr_ext_tso));
34 if (rc)
35 return NULL;
36
37 return qeth_push_skb(card, skb, sizeof(struct qeth_hdr_ext_tso));
38}
39
40/**
41 * fill header for a TSO packet
42 */
43static inline void
44qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb)
45{
46 struct qeth_hdr_tso *hdr;
47 struct tcphdr *tcph;
48 struct iphdr *iph;
49
50 QETH_DBF_TEXT(trace, 5, "tsofhdr");
51
52 hdr = (struct qeth_hdr_tso *) skb->data;
53 iph = skb->nh.iph;
54 tcph = skb->h.th;
55 /*fix header to TSO values ...*/
56 hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
57 /*set values which are fix for the first approach ...*/
58 hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
59 hdr->ext.imb_hdr_no = 1;
60 hdr->ext.hdr_type = 1;
61 hdr->ext.hdr_version = 1;
62 hdr->ext.hdr_len = 28;
63 /*insert non-fix values */
64 hdr->ext.mss = skb_shinfo(skb)->tso_size;
65 hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
66 hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
67 sizeof(struct qeth_hdr_tso));
68}
69
70/**
71 * change some header values as requested by hardware
72 */
73static inline void
74qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb)
75{
76 struct iphdr *iph;
77 struct ipv6hdr *ip6h;
78 struct tcphdr *tcph;
79
80 iph = skb->nh.iph;
81 ip6h = skb->nh.ipv6h;
82 tcph = skb->h.th;
83
84 tcph->check = 0;
85 if (skb->protocol == ETH_P_IPV6) {
86 ip6h->payload_len = 0;
87 tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
88 0, IPPROTO_TCP, 0);
89 return;
90 }
91 /*OSA want us to set these values ...*/
92 tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
93 0, IPPROTO_TCP, 0);
94 iph->tot_len = 0;
95 iph->check = 0;
96}
97
98static inline struct qeth_hdr_tso *
99qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb,
100 int ipv, int cast_type)
101{
102 struct qeth_hdr_tso *hdr;
103 int rc = 0;
104
105 QETH_DBF_TEXT(trace, 5, "tsoprep");
106
107 /*get headroom for tso qdio header */
108 hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb);
109 if (hdr == NULL) {
110 QETH_DBF_TEXT_(trace, 4, "2err%d", rc);
111 return NULL;
112 }
113 memset(hdr, 0, sizeof(struct qeth_hdr_tso));
114 /*fill first 32 bytes of qdio header as used
115 *FIXME: TSO has two struct members
116 * with different names but same size
117 * */
118 qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type);
119 qeth_tso_fill_header(card, skb);
120 qeth_tso_set_tcpip_header(card, skb);
121 return hdr;
122}
123
124static inline int
125qeth_tso_get_queue_buffer(struct qeth_qdio_out_q *queue)
126{
127 struct qeth_qdio_out_buffer *buffer;
128 int flush_cnt = 0;
129
130 QETH_DBF_TEXT(trace, 5, "tsobuf");
131
132 /* force to non-packing*/
133 if (queue->do_pack)
134 queue->do_pack = 0;
135 buffer = &queue->bufs[queue->next_buf_to_fill];
136 /* get a new buffer if current is already in use*/
137 if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
138 (buffer->next_element_to_fill > 0)) {
139 atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
140 queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
141 QDIO_MAX_BUFFERS_PER_Q;
142 flush_cnt++;
143 }
144 return flush_cnt;
145}
146
147static inline void
148__qeth_tso_fill_buffer_frag(struct qeth_qdio_out_buffer *buf,
149 struct sk_buff *skb)
150{
151 struct skb_frag_struct *frag;
152 struct qdio_buffer *buffer;
153 int fragno, cnt, element;
154 unsigned long addr;
155
156 QETH_DBF_TEXT(trace, 6, "tsfilfrg");
157
158 /*initialize variables ...*/
159 fragno = skb_shinfo(skb)->nr_frags;
160 buffer = buf->buffer;
161 element = buf->next_element_to_fill;
162 /*fill buffer elements .....*/
163 for (cnt = 0; cnt < fragno; cnt++) {
164 frag = &skb_shinfo(skb)->frags[cnt];
165 addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
166 frag->page_offset;
167 buffer->element[element].addr = (char *)addr;
168 buffer->element[element].length = frag->size;
169 if (cnt < (fragno - 1))
170 buffer->element[element].flags =
171 SBAL_FLAGS_MIDDLE_FRAG;
172 else
173 buffer->element[element].flags =
174 SBAL_FLAGS_LAST_FRAG;
175 element++;
176 }
177 buf->next_element_to_fill = element;
178}
179
180static inline int
181qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf,
182 struct sk_buff *skb)
183{
184 int length, length_here, element;
185 int hdr_len;
186 struct qdio_buffer *buffer;
187 struct qeth_hdr_tso *hdr;
188 char *data;
189
190 QETH_DBF_TEXT(trace, 3, "tsfilbuf");
191
192 /*increment user count and queue skb ...*/
193 atomic_inc(&skb->users);
194 skb_queue_tail(&buf->skb_list, skb);
195
196 /*initialize all variables...*/
197 buffer = buf->buffer;
198 hdr = (struct qeth_hdr_tso *)skb->data;
199 hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
200 data = skb->data + hdr_len;
201 length = skb->len - hdr_len;
202 element = buf->next_element_to_fill;
203 /*fill first buffer entry only with header information */
204 buffer->element[element].addr = skb->data;
205 buffer->element[element].length = hdr_len;
206 buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
207 buf->next_element_to_fill++;
208
209 if (skb_shinfo(skb)->nr_frags > 0) {
210 __qeth_tso_fill_buffer_frag(buf, skb);
211 goto out;
212 }
213
214 /*start filling buffer entries ...*/
215 element++;
216 while (length > 0) {
217 /* length_here is the remaining amount of data in this page */
218 length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
219 if (length < length_here)
220 length_here = length;
221 buffer->element[element].addr = data;
222 buffer->element[element].length = length_here;
223 length -= length_here;
224 if (!length)
225 buffer->element[element].flags =
226 SBAL_FLAGS_LAST_FRAG;
227 else
228 buffer->element[element].flags =
229 SBAL_FLAGS_MIDDLE_FRAG;
230 data += length_here;
231 element++;
232 }
233 /*set the buffer to primed ...*/
234 buf->next_element_to_fill = element;
235out:
236 atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
237 return 1;
238}
239
240int
241qeth_tso_send_packet(struct qeth_card *card, struct sk_buff *skb,
242 struct qeth_qdio_out_q *queue, int ipv, int cast_type)
243{
244 int flush_cnt = 0;
245 struct qeth_hdr_tso *hdr;
246 struct qeth_qdio_out_buffer *buffer;
247 int start_index;
248
249 QETH_DBF_TEXT(trace, 3, "tsosend");
250
251 if (!(hdr = qeth_tso_prepare_packet(card, skb, ipv, cast_type)))
252 return -ENOMEM;
253 /*check if skb fits in one SBAL ...*/
254 if (!(qeth_get_elements_no(card, (void*)hdr, skb)))
255 return -EINVAL;
256 /*lock queue, force switching to non-packing and send it ...*/
257 while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED,
258 QETH_OUT_Q_LOCKED,
259 &queue->state));
260 start_index = queue->next_buf_to_fill;
261 buffer = &queue->bufs[queue->next_buf_to_fill];
262 /*check if card is too busy ...*/
263 if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){
264 card->stats.tx_dropped++;
265 goto out;
266 }
267 /*let's force to non-packing and get a new SBAL*/
268 flush_cnt += qeth_tso_get_queue_buffer(queue);
269 buffer = &queue->bufs[queue->next_buf_to_fill];
270 if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) {
271 card->stats.tx_dropped++;
272 goto out;
273 }
274 flush_cnt += qeth_tso_fill_buffer(buffer, skb);
275 queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
276 QDIO_MAX_BUFFERS_PER_Q;
277out:
278 atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
279 if (flush_cnt)
280 qeth_flush_buffers(queue, 0, start_index, flush_cnt);
281 /*do some statistics */
282 card->stats.tx_packets++;
283 card->stats.tx_bytes += skb->len;
284 return 0;
285}
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
index 83504dee3f57..ad33e6f466f1 100644
--- a/drivers/s390/net/qeth_tso.h
+++ b/drivers/s390/net/qeth_tso.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.4 $) 2 * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.7 $)
3 * 3 *
4 * Header file for qeth TCP Segmentation Offload support. 4 * Header file for qeth TCP Segmentation Offload support.
5 * 5 *
@@ -7,52 +7,148 @@
7 * 7 *
8 * Author(s): Frank Pavlic <pavlic@de.ibm.com> 8 * Author(s): Frank Pavlic <pavlic@de.ibm.com>
9 * 9 *
10 * $Revision: 1.4 $ $Date: 2005/03/24 09:04:18 $ 10 * $Revision: 1.7 $ $Date: 2005/05/04 20:19:18 $
11 * 11 *
12 */ 12 */
13#ifndef __QETH_TSO_H__ 13#ifndef __QETH_TSO_H__
14#define __QETH_TSO_H__ 14#define __QETH_TSO_H__
15 15
16#include <linux/skbuff.h>
17#include <linux/tcp.h>
18#include <linux/ip.h>
19#include <linux/ipv6.h>
20#include <net/ip6_checksum.h>
21#include "qeth.h"
22#include "qeth_mpc.h"
16 23
17extern int
18qeth_tso_send_packet(struct qeth_card *, struct sk_buff *,
19 struct qeth_qdio_out_q *, int , int);
20 24
21struct qeth_hdr_ext_tso { 25static inline struct qeth_hdr_tso *
22 __u16 hdr_tot_len; 26qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb)
23 __u8 imb_hdr_no; 27{
24 __u8 reserved; 28 QETH_DBF_TEXT(trace, 5, "tsoprsk");
25 __u8 hdr_type; 29 return qeth_push_skb(card, skb, sizeof(struct qeth_hdr_tso));
26 __u8 hdr_version; 30}
27 __u16 hdr_len; 31
28 __u32 payload_len; 32/**
29 __u16 mss; 33 * fill header for a TSO packet
30 __u16 dg_hdr_len; 34 */
31 __u8 padding[16]; 35static inline void
32} __attribute__ ((packed)); 36qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb)
37{
38 struct qeth_hdr_tso *hdr;
39 struct tcphdr *tcph;
40 struct iphdr *iph;
41
42 QETH_DBF_TEXT(trace, 5, "tsofhdr");
43
44 hdr = (struct qeth_hdr_tso *) skb->data;
45 iph = skb->nh.iph;
46 tcph = skb->h.th;
47 /*fix header to TSO values ...*/
48 hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
49 /*set values which are fix for the first approach ...*/
50 hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
51 hdr->ext.imb_hdr_no = 1;
52 hdr->ext.hdr_type = 1;
53 hdr->ext.hdr_version = 1;
54 hdr->ext.hdr_len = 28;
55 /*insert non-fix values */
56 hdr->ext.mss = skb_shinfo(skb)->tso_size;
57 hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
58 hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
59 sizeof(struct qeth_hdr_tso));
60}
61
62/**
63 * change some header values as requested by hardware
64 */
65static inline void
66qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb)
67{
68 struct iphdr *iph;
69 struct ipv6hdr *ip6h;
70 struct tcphdr *tcph;
33 71
34struct qeth_hdr_tso { 72 iph = skb->nh.iph;
35 struct qeth_hdr hdr; /*hdr->hdr.l3.xxx*/ 73 ip6h = skb->nh.ipv6h;
36 struct qeth_hdr_ext_tso ext; 74 tcph = skb->h.th;
37} __attribute__ ((packed));
38 75
39/*some helper functions*/ 76 tcph->check = 0;
77 if (skb->protocol == ETH_P_IPV6) {
78 ip6h->payload_len = 0;
79 tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
80 0, IPPROTO_TCP, 0);
81 return;
82 }
83 /*OSA want us to set these values ...*/
84 tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
85 0, IPPROTO_TCP, 0);
86 iph->tot_len = 0;
87 iph->check = 0;
88}
40 89
41static inline int 90static inline int
42qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) 91qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb,
92 int ipv, int cast_type)
93{
94 struct qeth_hdr_tso *hdr;
95
96 QETH_DBF_TEXT(trace, 5, "tsoprep");
97
98 hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb);
99 if (hdr == NULL) {
100 QETH_DBF_TEXT(trace, 4, "tsoperr");
101 return -ENOMEM;
102 }
103 memset(hdr, 0, sizeof(struct qeth_hdr_tso));
104 /*fill first 32 bytes of qdio header as used
105 *FIXME: TSO has two struct members
106 * with different names but same size
107 * */
108 qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type);
109 qeth_tso_fill_header(card, skb);
110 qeth_tso_set_tcpip_header(card, skb);
111 return 0;
112}
113
114static inline void
115__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
116 int is_tso, int *next_element_to_fill)
43{ 117{
44 int elements_needed = 0; 118 struct skb_frag_struct *frag;
45 119 int fragno;
46 if (skb_shinfo(skb)->nr_frags > 0) 120 unsigned long addr;
47 elements_needed = (skb_shinfo(skb)->nr_frags + 1); 121 int element, cnt, dlen;
48 if (elements_needed == 0 ) 122
49 elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) 123 fragno = skb_shinfo(skb)->nr_frags;
50 + skb->len) >> PAGE_SHIFT); 124 element = *next_element_to_fill;
51 if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ 125 dlen = 0;
52 PRINT_ERR("qeth_do_send_packet: invalid size of " 126
53 "IP packet. Discarded."); 127 if (is_tso)
54 return 0; 128 buffer->element[element].flags =
129 SBAL_FLAGS_MIDDLE_FRAG;
130 else
131 buffer->element[element].flags =
132 SBAL_FLAGS_FIRST_FRAG;
133 if ( (dlen = (skb->len - skb->data_len)) ) {
134 buffer->element[element].addr = skb->data;
135 buffer->element[element].length = dlen;
136 element++;
137 }
138 for (cnt = 0; cnt < fragno; cnt++) {
139 frag = &skb_shinfo(skb)->frags[cnt];
140 addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
141 frag->page_offset;
142 buffer->element[element].addr = (char *)addr;
143 buffer->element[element].length = frag->size;
144 if (cnt < (fragno - 1))
145 buffer->element[element].flags =
146 SBAL_FLAGS_MIDDLE_FRAG;
147 else
148 buffer->element[element].flags =
149 SBAL_FLAGS_LAST_FRAG;
150 element++;
55 } 151 }
56 return elements_needed; 152 *next_element_to_fill = element;
57} 153}
58#endif /* __QETH_TSO_H__ */ 154#endif /* __QETH_TSO_H__ */