aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/qeth_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/net/qeth_main.c')
-rw-r--r--drivers/s390/net/qeth_main.c316
1 files changed, 213 insertions, 103 deletions
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},