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.c145
1 files changed, 105 insertions, 40 deletions
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index e18bcf9fb588..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.210 $) 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.210 $ $Date: 2005/04/18 17:27:39 $ 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.210 $" 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));
@@ -3786,16 +3795,12 @@ static inline int
3786qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, 3795qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
3787 struct qeth_hdr **hdr, int ipv) 3796 struct qeth_hdr **hdr, int ipv)
3788{ 3797{
3789 int rc = 0;
3790#ifdef CONFIG_QETH_VLAN 3798#ifdef CONFIG_QETH_VLAN
3791 u16 *tag; 3799 u16 *tag;
3792#endif 3800#endif
3793 3801
3794 QETH_DBF_TEXT(trace, 6, "prepskb"); 3802 QETH_DBF_TEXT(trace, 6, "prepskb");
3795 3803
3796 rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
3797 if (rc)
3798 return rc;
3799#ifdef CONFIG_QETH_VLAN 3804#ifdef CONFIG_QETH_VLAN
3800 if (card->vlangrp && vlan_tx_tag_present(*skb) && 3805 if (card->vlangrp && vlan_tx_tag_present(*skb) &&
3801 ((ipv == 6) || card->options.layer2) ) { 3806 ((ipv == 6) || card->options.layer2) ) {
@@ -3977,25 +3982,28 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
3977 3982
3978static inline void 3983static inline void
3979__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, 3984__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
3980 int *next_element_to_fill) 3985 int is_tso, int *next_element_to_fill)
3981{ 3986{
3982 int length = skb->len; 3987 int length = skb->len;
3983 int length_here; 3988 int length_here;
3984 int element; 3989 int element;
3985 char *data; 3990 char *data;
3986 int first_lap = 1; 3991 int first_lap ;
3987 3992
3988 element = *next_element_to_fill; 3993 element = *next_element_to_fill;
3989 data = skb->data; 3994 data = skb->data;
3995 first_lap = (is_tso == 0 ? 1 : 0);
3996
3990 while (length > 0) { 3997 while (length > 0) {
3991 /* length_here is the remaining amount of data in this page */ 3998 /* length_here is the remaining amount of data in this page */
3992 length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE); 3999 length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
3993 if (length < length_here) 4000 if (length < length_here)
3994 length_here = length; 4001 length_here = length;
4002
3995 buffer->element[element].addr = data; 4003 buffer->element[element].addr = data;
3996 buffer->element[element].length = length_here; 4004 buffer->element[element].length = length_here;
3997 length -= length_here; 4005 length -= length_here;
3998 if (!length){ 4006 if (!length) {
3999 if (first_lap) 4007 if (first_lap)
4000 buffer->element[element].flags = 0; 4008 buffer->element[element].flags = 0;
4001 else 4009 else
@@ -4022,17 +4030,35 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue,
4022 struct sk_buff *skb) 4030 struct sk_buff *skb)
4023{ 4031{
4024 struct qdio_buffer *buffer; 4032 struct qdio_buffer *buffer;
4025 int flush_cnt = 0; 4033 struct qeth_hdr_tso *hdr;
4034 int flush_cnt = 0, hdr_len, large_send = 0;
4026 4035
4027 QETH_DBF_TEXT(trace, 6, "qdfillbf"); 4036 QETH_DBF_TEXT(trace, 6, "qdfillbf");
4037
4028 buffer = buf->buffer; 4038 buffer = buf->buffer;
4029 atomic_inc(&skb->users); 4039 atomic_inc(&skb->users);
4030 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 }
4031 if (skb_shinfo(skb)->nr_frags == 0) 4057 if (skb_shinfo(skb)->nr_frags == 0)
4032 __qeth_fill_buffer(skb, buffer, 4058 __qeth_fill_buffer(skb, buffer, large_send,
4033 (int *)&buf->next_element_to_fill); 4059 (int *)&buf->next_element_to_fill);
4034 else 4060 else
4035 __qeth_fill_buffer_frag(skb, buffer, 0, 4061 __qeth_fill_buffer_frag(skb, buffer, large_send,
4036 (int *)&buf->next_element_to_fill); 4062 (int *)&buf->next_element_to_fill);
4037 4063
4038 if (!queue->do_pack) { 4064 if (!queue->do_pack) {
@@ -4225,6 +4251,25 @@ out:
4225} 4251}
4226 4252
4227static 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
4228qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) 4273qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
4229{ 4274{
4230 int ipv = 0; 4275 int ipv = 0;
@@ -4266,19 +4311,25 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
4266 if (skb_shinfo(skb)->tso_size) 4311 if (skb_shinfo(skb)->tso_size)
4267 large_send = card->options.large_send; 4312 large_send = card->options.large_send;
4268 4313
4269 if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))){
4270 QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc);
4271 return rc;
4272 }
4273 /*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 */
4274 if ((large_send == QETH_LARGE_SEND_TSO) && 4315 if ((large_send == QETH_LARGE_SEND_TSO) &&
4275 (cast_type == RTN_UNSPEC)) { 4316 (cast_type == RTN_UNSPEC)) {
4276 rc = qeth_tso_send_packet(card, skb, queue, 4317 rc = qeth_tso_prepare_packet(card, skb, ipv, cast_type);
4277 ipv, cast_type); 4318 if (rc) {
4278 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);
4279 } 4331 }
4280 4332
4281 qeth_fill_header(card, hdr, skb, ipv, cast_type);
4282 if (large_send == QETH_LARGE_SEND_EDDP) { 4333 if (large_send == QETH_LARGE_SEND_EDDP) {
4283 ctx = qeth_eddp_create_context(card, skb, hdr); 4334 ctx = qeth_eddp_create_context(card, skb, hdr);
4284 if (ctx == NULL) { 4335 if (ctx == NULL) {
@@ -4286,7 +4337,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
4286 return -EINVAL; 4337 return -EINVAL;
4287 } 4338 }
4288 } else { 4339 } else {
4289 elements_needed = qeth_get_elements_no(card,(void*) hdr, skb); 4340 elements_needed += qeth_get_elements_no(card,(void*) hdr, skb);
4290 if (!elements_needed) 4341 if (!elements_needed)
4291 return -EINVAL; 4342 return -EINVAL;
4292 } 4343 }
@@ -4297,12 +4348,12 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
4297 else 4348 else
4298 rc = qeth_do_send_packet_fast(card, queue, skb, hdr, 4349 rc = qeth_do_send_packet_fast(card, queue, skb, hdr,
4299 elements_needed, ctx); 4350 elements_needed, ctx);
4300do_statistics:
4301 if (!rc){ 4351 if (!rc){
4302 card->stats.tx_packets++; 4352 card->stats.tx_packets++;
4303 card->stats.tx_bytes += skb->len; 4353 card->stats.tx_bytes += skb->len;
4304#ifdef CONFIG_QETH_PERF_STATS 4354#ifdef CONFIG_QETH_PERF_STATS
4305 if (skb_shinfo(skb)->tso_size) { 4355 if (skb_shinfo(skb)->tso_size &&
4356 !(large_send == QETH_LARGE_SEND_NO)) {
4306 card->perf_stats.large_send_bytes += skb->len; 4357 card->perf_stats.large_send_bytes += skb->len;
4307 card->perf_stats.large_send_cnt++; 4358 card->perf_stats.large_send_cnt++;
4308 } 4359 }
@@ -7199,7 +7250,7 @@ qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
7199} 7250}
7200 7251
7201static int 7252static int
7202qeth_stop_card(struct qeth_card *card) 7253qeth_stop_card(struct qeth_card *card, int recovery_mode)
7203{ 7254{
7204 int rc = 0; 7255 int rc = 0;
7205 7256
@@ -7212,9 +7263,13 @@ qeth_stop_card(struct qeth_card *card)
7212 if (card->read.state == CH_STATE_UP && 7263 if (card->read.state == CH_STATE_UP &&
7213 card->write.state == CH_STATE_UP && 7264 card->write.state == CH_STATE_UP &&
7214 (card->state == CARD_STATE_UP)) { 7265 (card->state == CARD_STATE_UP)) {
7215 rtnl_lock(); 7266 if(recovery_mode) {
7216 dev_close(card->dev); 7267 qeth_stop(card->dev);
7217 rtnl_unlock(); 7268 } else {
7269 rtnl_lock();
7270 dev_close(card->dev);
7271 rtnl_unlock();
7272 }
7218 if (!card->use_hard_stop) { 7273 if (!card->use_hard_stop) {
7219 __u8 *mac = &card->dev->dev_addr[0]; 7274 __u8 *mac = &card->dev->dev_addr[0];
7220 rc = qeth_layer2_send_delmac(card, mac); 7275 rc = qeth_layer2_send_delmac(card, mac);
@@ -7386,13 +7441,17 @@ qeth_register_netdev(struct qeth_card *card)
7386} 7441}
7387 7442
7388static void 7443static void
7389qeth_start_again(struct qeth_card *card) 7444qeth_start_again(struct qeth_card *card, int recovery_mode)
7390{ 7445{
7391 QETH_DBF_TEXT(setup ,2, "startag"); 7446 QETH_DBF_TEXT(setup ,2, "startag");
7392 7447
7393 rtnl_lock(); 7448 if(recovery_mode) {
7394 dev_open(card->dev); 7449 qeth_open(card->dev);
7395 rtnl_unlock(); 7450 } else {
7451 rtnl_lock();
7452 dev_open(card->dev);
7453 rtnl_unlock();
7454 }
7396 /* this also sets saved unicast addresses */ 7455 /* this also sets saved unicast addresses */
7397 qeth_set_multicast_list(card->dev); 7456 qeth_set_multicast_list(card->dev);
7398} 7457}
@@ -7449,7 +7508,7 @@ static void qeth_make_parameters_consistent(struct qeth_card *card)
7449 7508
7450 7509
7451static int 7510static int
7452qeth_set_online(struct ccwgroup_device *gdev) 7511__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
7453{ 7512{
7454 struct qeth_card *card = gdev->dev.driver_data; 7513 struct qeth_card *card = gdev->dev.driver_data;
7455 int rc = 0; 7514 int rc = 0;
@@ -7509,12 +7568,12 @@ qeth_set_online(struct ccwgroup_device *gdev)
7509 * we can also use this state for recovery purposes*/ 7568 * we can also use this state for recovery purposes*/
7510 qeth_set_allowed_threads(card, 0xffffffff, 0); 7569 qeth_set_allowed_threads(card, 0xffffffff, 0);
7511 if (recover_flag == CARD_STATE_RECOVER) 7570 if (recover_flag == CARD_STATE_RECOVER)
7512 qeth_start_again(card); 7571 qeth_start_again(card, recovery_mode);
7513 qeth_notify_processes(); 7572 qeth_notify_processes();
7514 return 0; 7573 return 0;
7515out_remove: 7574out_remove:
7516 card->use_hard_stop = 1; 7575 card->use_hard_stop = 1;
7517 qeth_stop_card(card); 7576 qeth_stop_card(card, 0);
7518 ccw_device_set_offline(CARD_DDEV(card)); 7577 ccw_device_set_offline(CARD_DDEV(card));
7519 ccw_device_set_offline(CARD_WDEV(card)); 7578 ccw_device_set_offline(CARD_WDEV(card));
7520 ccw_device_set_offline(CARD_RDEV(card)); 7579 ccw_device_set_offline(CARD_RDEV(card));
@@ -7525,6 +7584,12 @@ out_remove:
7525 return -ENODEV; 7584 return -ENODEV;
7526} 7585}
7527 7586
7587static int
7588qeth_set_online(struct ccwgroup_device *gdev)
7589{
7590 return __qeth_set_online(gdev, 0);
7591}
7592
7528static struct ccw_device_id qeth_ids[] = { 7593static struct ccw_device_id qeth_ids[] = {
7529 {CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE}, 7594 {CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE},
7530 {CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD}, 7595 {CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD},