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 @@ ...@@ -24,7 +24,7 @@
#include "qeth_mpc.h" #include "qeth_mpc.h"
#define VERSION_QETH_H "$Revision: 1.123 $" #define VERSION_QETH_H "$Revision: 1.124 $"
#ifdef CONFIG_QETH_IPV6 #ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6" #define QETH_VERSION_IPV6 ":IPv6"
...@@ -330,10 +330,6 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func) ...@@ -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_WATERMARK_PACK_FUZZ 1
#define QETH_IP_HEADER_SIZE 40 #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 { struct qeth_hdr_layer3 {
__u8 id; __u8 id;
...@@ -393,9 +389,11 @@ enum qeth_header_ids { ...@@ -393,9 +389,11 @@ enum qeth_header_ids {
}; };
/* flags for qeth_hdr.ext_flags */ /* flags for qeth_hdr.ext_flags */
#define QETH_HDR_EXT_VLAN_FRAME 0x01 #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_HDR_REQ 0x10
#define QETH_HDR_EXT_CSUM_TRANSP_REQ 0x20 #define QETH_HDR_EXT_CSUM_TRANSP_REQ 0x20
#define QETH_HDR_EXT_SRC_MAC_ADDR 0x08
static inline int static inline int
qeth_is_last_sbale(struct qdio_buffer_element *sbale) 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 * Linux on zSeries OSA Express and HiperSockets support
* *
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and * Frank Pavlic (pavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com> * 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -78,7 +78,7 @@ qeth_eyecatcher(void) ...@@ -78,7 +78,7 @@ qeth_eyecatcher(void)
#include "qeth_mpc.h" #include "qeth_mpc.h"
#include "qeth_fs.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"; 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, ...@@ -2236,9 +2236,11 @@ qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb,
#ifdef CONFIG_QETH_VLAN #ifdef CONFIG_QETH_VLAN
u16 *vlan_tag; 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 = (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; *(vlan_tag + 1) = skb->protocol;
skb->protocol = __constant_htons(ETH_P_8021Q); skb->protocol = __constant_htons(ETH_P_8021Q);
} }
...@@ -3789,8 +3791,8 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, ...@@ -3789,8 +3791,8 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
*/ */
if (card->vlangrp && vlan_tx_tag_present(skb)) { if (card->vlangrp && vlan_tx_tag_present(skb)) {
hdr->hdr.l3.ext_flags = (ipv == 4) ? hdr->hdr.l3.ext_flags = (ipv == 4) ?
QETH_EXT_HDR_VLAN_FRAME : QETH_HDR_EXT_VLAN_FRAME :
QETH_EXT_HDR_INCLUDE_VLAN_TAG; QETH_HDR_EXT_INCLUDE_VLAN_TAG;
hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb); hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb);
} }
#endif /* CONFIG_QETH_VLAN */ #endif /* CONFIG_QETH_VLAN */
...@@ -6702,7 +6704,6 @@ qeth_wait_for_threads(struct qeth_card *card, unsigned long threads) ...@@ -6702,7 +6704,6 @@ qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
static int static int
qeth_stop_card(struct qeth_card *card) qeth_stop_card(struct qeth_card *card)
{ {
int recover_flag = 0;
int rc = 0; int rc = 0;
QETH_DBF_TEXT(setup ,2,"stopcard"); QETH_DBF_TEXT(setup ,2,"stopcard");
...@@ -6714,7 +6715,6 @@ qeth_stop_card(struct qeth_card *card) ...@@ -6714,7 +6715,6 @@ qeth_stop_card(struct qeth_card *card)
if (card->read.state == CH_STATE_UP && if (card->read.state == CH_STATE_UP &&
card->write.state == CH_STATE_UP && card->write.state == CH_STATE_UP &&
(card->state == CARD_STATE_UP)) { (card->state == CARD_STATE_UP)) {
recover_flag = 1;
rtnl_lock(); rtnl_lock();
dev_close(card->dev); dev_close(card->dev);
rtnl_unlock(); rtnl_unlock();
...@@ -6733,7 +6733,7 @@ qeth_stop_card(struct qeth_card *card) ...@@ -6733,7 +6733,7 @@ qeth_stop_card(struct qeth_card *card)
if (card->options.layer2) if (card->options.layer2)
qeth_layer2_process_vlans(card, 1); qeth_layer2_process_vlans(card, 1);
#endif #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); qeth_clear_ipacmd_list(card);
card->state = CARD_STATE_HARDSETUP; card->state = CARD_STATE_HARDSETUP;
} }
...@@ -6901,6 +6901,7 @@ qeth_start_again(struct qeth_card *card) ...@@ -6901,6 +6901,7 @@ qeth_start_again(struct qeth_card *card)
rtnl_lock(); rtnl_lock();
dev_open(card->dev); dev_open(card->dev);
rtnl_unlock(); rtnl_unlock();
/* this also sets saved unicast addresses */
qeth_set_multicast_list(card->dev); 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 * Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs. * This file contains code related to sysfs.
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include "qeth_mpc.h" #include "qeth_mpc.h"
#include "qeth_fs.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, ...@@ -876,21 +876,31 @@ qeth_dev_ipato_add_show(char *buf, struct qeth_card *card,
{ {
struct qeth_ipato_entry *ipatoe; struct qeth_ipato_entry *ipatoe;
unsigned long flags; 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; int i = 0;
if (qeth_check_layer2(card)) if (qeth_check_layer2(card))
return -EPERM; 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); spin_lock_irqsave(&card->ip_lock, flags);
list_for_each_entry(ipatoe, &card->ipato.entries, entry){ list_for_each_entry(ipatoe, &card->ipato.entries, entry){
if (ipatoe->proto != proto) if (ipatoe->proto != proto)
continue; 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); 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); spin_unlock_irqrestore(&card->ip_lock, flags);
i += sprintf(buf + i, "\n"); i += snprintf(buf + i, PAGE_SIZE - i, "\n");
return i; return i;
} }
...@@ -1122,24 +1132,32 @@ qeth_dev_vipa_add_show(char *buf, struct qeth_card *card, ...@@ -1122,24 +1132,32 @@ qeth_dev_vipa_add_show(char *buf, struct qeth_card *card,
enum qeth_prot_versions proto) enum qeth_prot_versions proto)
{ {
struct qeth_ipaddr *ipaddr; 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; unsigned long flags;
int i = 0; int i = 0;
if (qeth_check_layer2(card)) if (qeth_check_layer2(card))
return -EPERM; return -EPERM;
entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
entry_len += 2; /* \n + terminator */
spin_lock_irqsave(&card->ip_lock, flags); spin_lock_irqsave(&card->ip_lock, flags);
list_for_each_entry(ipaddr, &card->ip_list, entry){ list_for_each_entry(ipaddr, &card->ip_list, entry){
if (ipaddr->proto != proto) if (ipaddr->proto != proto)
continue; continue;
if (ipaddr->type != QETH_IP_TYPE_VIPA) if (ipaddr->type != QETH_IP_TYPE_VIPA)
continue; 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); 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); spin_unlock_irqrestore(&card->ip_lock, flags);
i += sprintf(buf + i, "\n"); i += snprintf(buf + i, PAGE_SIZE - i, "\n");
return i; return i;
} }
...@@ -1295,24 +1313,32 @@ qeth_dev_rxip_add_show(char *buf, struct qeth_card *card, ...@@ -1295,24 +1313,32 @@ qeth_dev_rxip_add_show(char *buf, struct qeth_card *card,
enum qeth_prot_versions proto) enum qeth_prot_versions proto)
{ {
struct qeth_ipaddr *ipaddr; 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; unsigned long flags;
int i = 0; int i = 0;
if (qeth_check_layer2(card)) if (qeth_check_layer2(card))
return -EPERM; return -EPERM;
entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
entry_len += 2; /* \n + terminator */
spin_lock_irqsave(&card->ip_lock, flags); spin_lock_irqsave(&card->ip_lock, flags);
list_for_each_entry(ipaddr, &card->ip_list, entry){ list_for_each_entry(ipaddr, &card->ip_list, entry){
if (ipaddr->proto != proto) if (ipaddr->proto != proto)
continue; continue;
if (ipaddr->type != QETH_IP_TYPE_RXIP) if (ipaddr->type != QETH_IP_TYPE_RXIP)
continue; 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); 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); spin_unlock_irqrestore(&card->ip_lock, flags);
i += sprintf(buf + i, "\n"); i += snprintf(buf + i, PAGE_SIZE - i, "\n");
return i; 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