]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] s390: qeth network driver
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 2 Dec 2004 23:45:27 +0000 (15:45 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 2 Dec 2004 23:45:27 +0000 (15:45 -0800)
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: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/s390/net/qeth.h
drivers/s390/net/qeth_main.c
drivers/s390/net/qeth_sys.c

index 96b54af09103dea886776e050fe028b5aaa593bf..f426245956bb898063895f65957b34f11a0acf6a 100644 (file)
@@ -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)
index 00711fc8522285c1aa52248ea0d31ed064d9f85b..0ec53f32753d20f8e19935296a17fff9478176a9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *
- * 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);
 }
 
index 14d6198394382c40d9e1396b888c7fa2f886c2ff..15c863fcaa8819d361dc0dae3abd218217267e53 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *
- * 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;
 }