Commit 024345b4 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: qeth network driver

From: Thomas Spatzier <tspat@de.ibm.com>

network driver changes:
 - qeth: Handle both VLAN_FRAME and INCLUDES_VLAN_TAG in qdio header.
 - qeth: Always save IP addresses registered on a card when going offline.
 - qeth: Check size of printk buffer to 4K for ipa_takeover, vipa & rxip.


From: Thomas Spatzier <tspat@de.ibm.com>,
      Heiko Carstens <heiko.carstens@de.ibm.com>

Thomas created the patch below which removes the hardcoded 3900 bytes
limit as suggested by Jeff Garzik. Please apply.

network driver changes:
 - qeth: Calculate end of sysfs data buffer correctly.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ea584e0c
......@@ -24,7 +24,7 @@
#include "qeth_mpc.h"
#define VERSION_QETH_H "$Revision: 1.123 $"
#define VERSION_QETH_H "$Revision: 1.124 $"
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
......@@ -330,10 +330,6 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
#define QETH_WATERMARK_PACK_FUZZ 1
#define QETH_IP_HEADER_SIZE 40
/* VLAN defines */
#define QETH_EXT_HDR_VLAN_FRAME 0x01
#define QETH_EXT_HDR_TOKEN_ID 0x02
#define QETH_EXT_HDR_INCLUDE_VLAN_TAG 0x04
struct qeth_hdr_layer3 {
__u8 id;
......@@ -392,10 +388,12 @@ enum qeth_header_ids {
QETH_HEADER_TYPE_LAYER2 = 0x02,
};
/* flags for qeth_hdr.ext_flags */
#define QETH_HDR_EXT_VLAN_FRAME 0x01
#define QETH_HDR_EXT_CSUM_HDR_REQ 0x10
#define QETH_HDR_EXT_CSUM_TRANSP_REQ 0x20
#define QETH_HDR_EXT_SRC_MAC_ADDR 0x08
#define QETH_HDR_EXT_VLAN_FRAME 0x01
#define QETH_HDR_EXT_TOKEN_ID 0x02
#define QETH_HDR_EXT_INCLUDE_VLAN_TAG 0x04
#define QETH_HDR_EXT_SRC_MAC_ADDR 0x08
#define QETH_HDR_EXT_CSUM_HDR_REQ 0x10
#define QETH_HDR_EXT_CSUM_TRANSP_REQ 0x20
static inline int
qeth_is_last_sbale(struct qdio_buffer_element *sbale)
......
/*
*
* linux/drivers/s390/net/qeth_main.c ($Revision: 1.168 $)
* linux/drivers/s390/net/qeth_main.c ($Revision: 1.170 $)
*
* Linux on zSeries OSA Express and HiperSockets support
*
......@@ -12,7 +12,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com>
*
* $Revision: 1.168 $ $Date: 2004/11/08 15:55:12 $
* $Revision: 1.170 $ $Date: 2004/11/17 09:54:06 $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -78,7 +78,7 @@ qeth_eyecatcher(void)
#include "qeth_mpc.h"
#include "qeth_fs.h"
#define VERSION_QETH_C "$Revision: 1.168 $"
#define VERSION_QETH_C "$Revision: 1.170 $"
static const char *version = "qeth S/390 OSA-Express driver";
/**
......@@ -2236,9 +2236,11 @@ qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb,
#ifdef CONFIG_QETH_VLAN
u16 *vlan_tag;
if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME) {
if (hdr->hdr.l3.ext_flags &
(QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) {
vlan_tag = (u16 *) skb_push(skb, VLAN_HLEN);
*vlan_tag = hdr->hdr.l3.vlan_id;
*vlan_tag = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)?
hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]);
*(vlan_tag + 1) = skb->protocol;
skb->protocol = __constant_htons(ETH_P_8021Q);
}
......@@ -3789,8 +3791,8 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
*/
if (card->vlangrp && vlan_tx_tag_present(skb)) {
hdr->hdr.l3.ext_flags = (ipv == 4) ?
QETH_EXT_HDR_VLAN_FRAME :
QETH_EXT_HDR_INCLUDE_VLAN_TAG;
QETH_HDR_EXT_VLAN_FRAME :
QETH_HDR_EXT_INCLUDE_VLAN_TAG;
hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb);
}
#endif /* CONFIG_QETH_VLAN */
......@@ -6702,7 +6704,6 @@ qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
static int
qeth_stop_card(struct qeth_card *card)
{
int recover_flag = 0;
int rc = 0;
QETH_DBF_TEXT(setup ,2,"stopcard");
......@@ -6714,7 +6715,6 @@ qeth_stop_card(struct qeth_card *card)
if (card->read.state == CH_STATE_UP &&
card->write.state == CH_STATE_UP &&
(card->state == CARD_STATE_UP)) {
recover_flag = 1;
rtnl_lock();
dev_close(card->dev);
rtnl_unlock();
......@@ -6733,7 +6733,7 @@ qeth_stop_card(struct qeth_card *card)
if (card->options.layer2)
qeth_layer2_process_vlans(card, 1);
#endif
qeth_clear_ip_list(card, !card->use_hard_stop, recover_flag);
qeth_clear_ip_list(card, !card->use_hard_stop, 1);
qeth_clear_ipacmd_list(card);
card->state = CARD_STATE_HARDSETUP;
}
......@@ -6901,6 +6901,7 @@ qeth_start_again(struct qeth_card *card)
rtnl_lock();
dev_open(card->dev);
rtnl_unlock();
/* this also sets saved unicast addresses */
qeth_set_multicast_list(card->dev);
}
......
/*
*
* linux/drivers/s390/net/qeth_sys.c ($Revision: 1.35 $)
* linux/drivers/s390/net/qeth_sys.c ($Revision: 1.40 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs.
......@@ -20,7 +20,7 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
const char *VERSION_QETH_SYS_C = "$Revision: 1.35 $";
const char *VERSION_QETH_SYS_C = "$Revision: 1.40 $";
/*****************************************************************************/
/* */
......@@ -876,21 +876,31 @@ qeth_dev_ipato_add_show(char *buf, struct qeth_card *card,
{
struct qeth_ipato_entry *ipatoe;
unsigned long flags;
char addr_str[49];
char addr_str[40];
int entry_len; /* length of 1 entry string, differs between v4 and v6 */
int i = 0;
if (qeth_check_layer2(card))
return -EPERM;
entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
/* add strlen for "/<mask>\n" */
entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
spin_lock_irqsave(&card->ip_lock, flags);
list_for_each_entry(ipatoe, &card->ipato.entries, entry){
if (ipatoe->proto != proto)
continue;
/* String must not be longer than PAGE_SIZE. So we check if
* string length gets near PAGE_SIZE. Then we can savely display
* the next IPv6 address (worst case, compared to IPv4) */
if ((PAGE_SIZE - i) <= entry_len)
break;
qeth_ipaddr_to_string(proto, ipatoe->addr, addr_str);
i += sprintf(buf + i, "%s/%i\n", addr_str, ipatoe->mask_bits);
i += snprintf(buf + i, PAGE_SIZE - i,
"%s/%i\n", addr_str, ipatoe->mask_bits);
}
spin_unlock_irqrestore(&card->ip_lock, flags);
i += sprintf(buf + i, "\n");
i += snprintf(buf + i, PAGE_SIZE - i, "\n");
return i;
}
......@@ -1122,24 +1132,32 @@ qeth_dev_vipa_add_show(char *buf, struct qeth_card *card,
enum qeth_prot_versions proto)
{
struct qeth_ipaddr *ipaddr;
char addr_str[49];
char addr_str[40];
int entry_len; /* length of 1 entry string, differs between v4 and v6 */
unsigned long flags;
int i = 0;
if (qeth_check_layer2(card))
return -EPERM;
entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
entry_len += 2; /* \n + terminator */
spin_lock_irqsave(&card->ip_lock, flags);
list_for_each_entry(ipaddr, &card->ip_list, entry){
if (ipaddr->proto != proto)
continue;
if (ipaddr->type != QETH_IP_TYPE_VIPA)
continue;
/* String must not be longer than PAGE_SIZE. So we check if
* string length gets near PAGE_SIZE. Then we can savely display
* the next IPv6 address (worst case, compared to IPv4) */
if ((PAGE_SIZE - i) <= entry_len)
break;
qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
i += sprintf(buf + i, "%s\n", addr_str);
i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
}
spin_unlock_irqrestore(&card->ip_lock, flags);
i += sprintf(buf + i, "\n");
i += snprintf(buf + i, PAGE_SIZE - i, "\n");
return i;
}
......@@ -1295,24 +1313,32 @@ qeth_dev_rxip_add_show(char *buf, struct qeth_card *card,
enum qeth_prot_versions proto)
{
struct qeth_ipaddr *ipaddr;
char addr_str[49];
char addr_str[40];
int entry_len; /* length of 1 entry string, differs between v4 and v6 */
unsigned long flags;
int i = 0;
if (qeth_check_layer2(card))
return -EPERM;
entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
entry_len += 2; /* \n + terminator */
spin_lock_irqsave(&card->ip_lock, flags);
list_for_each_entry(ipaddr, &card->ip_list, entry){
if (ipaddr->proto != proto)
continue;
if (ipaddr->type != QETH_IP_TYPE_RXIP)
continue;
/* String must not be longer than PAGE_SIZE. So we check if
* string length gets near PAGE_SIZE. Then we can savely display
* the next IPv6 address (worst case, compared to IPv4) */
if ((PAGE_SIZE - i) <= entry_len)
break;
qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
i += sprintf(buf + i, "%s\n", addr_str);
i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
}
spin_unlock_irqrestore(&card->ip_lock, flags);
i += sprintf(buf + i, "\n");
i += snprintf(buf + i, PAGE_SIZE - i, "\n");
return i;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment