Commit 99cfb338 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: qeth layer 2 support

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

qeth network driver changes:
 - Add Layer 2 support for OSA-Express.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent bd307f59
......@@ -23,7 +23,7 @@
#include "qeth_mpc.h"
#define VERSION_QETH_H "$Revision: 1.113 $"
#define VERSION_QETH_H "$Revision: 1.116 $"
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
......@@ -43,7 +43,7 @@
#define QETH_DBF_SETUP_LEN 8
#define QETH_DBF_SETUP_INDEX 3
#define QETH_DBF_SETUP_NR_AREAS 1
#define QETH_DBF_SETUP_LEVEL 3
#define QETH_DBF_SETUP_LEVEL 5
#define QETH_DBF_MISC_NAME "qeth_misc"
#define QETH_DBF_MISC_LEN 128
......@@ -61,13 +61,13 @@
#define QETH_DBF_CONTROL_LEN 256
#define QETH_DBF_CONTROL_INDEX 3
#define QETH_DBF_CONTROL_NR_AREAS 2
#define QETH_DBF_CONTROL_LEVEL 2
#define QETH_DBF_CONTROL_LEVEL 5
#define QETH_DBF_TRACE_NAME "qeth_trace"
#define QETH_DBF_TRACE_LEN 8
#define QETH_DBF_TRACE_INDEX 2
#define QETH_DBF_TRACE_NR_AREAS 2
#define QETH_DBF_TRACE_LEVEL 3
#define QETH_DBF_TRACE_LEVEL 5
#define QETH_DBF_SENSE_NAME "qeth_sense"
#define QETH_DBF_SENSE_LEN 64
......@@ -334,7 +334,7 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
#define QETH_EXT_HDR_TOKEN_ID 0x02
#define QETH_EXT_HDR_INCLUDE_VLAN_TAG 0x04
struct qeth_hdr {
struct qeth_hdr_layer3 {
__u8 id;
__u8 flags;
__u16 inbound_checksum;
......@@ -347,6 +347,26 @@ struct qeth_hdr {
__u8 dest_addr[16];
} __attribute__ ((packed));
struct qeth_hdr_layer2 {
__u8 id;
__u8 flags[3];
__u8 port_no;
__u8 hdr_length;
__u16 pkt_length;
__u16 seq_no;
__u16 vlan_id;
__u32 reserved;
__u8 reserved2[16];
} __attribute__ ((packed));
struct qeth_hdr {
union {
struct qeth_hdr_layer2 l2;
struct qeth_hdr_layer3 l3;
} hdr;
} __attribute__ ((packed));
/* flags for qeth_hdr.flags */
#define QETH_HDR_PASSTHRU 0x10
#define QETH_HDR_IPV6 0x80
......@@ -359,6 +379,17 @@ enum qeth_cast_flags {
QETH_CAST_NOCAST = 0x00,
};
enum qeth_layer2_frame_flags {
QETH_LAYER2_FLAG_MULTICAST = 0x01,
QETH_LAYER2_FLAG_BROADCAST = 0x02,
QETH_LAYER2_FLAG_UNICAST = 0x04,
QETH_LAYER2_FLAG_VLAN = 0x10,
};
enum qeth_header_ids {
QETH_HEADER_TYPE_LAYER3 = 0x01,
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
......@@ -645,6 +676,7 @@ struct qeth_card_info {
__u16 func_level;
char mcl_level[QETH_MCL_LENGTH + 1];
int guestlan;
int layer2_mac_registered;
int portname_required;
int portno;
char portname[9];
......@@ -672,6 +704,7 @@ struct qeth_card_options {
int fake_broadcast;
int add_hhlen;
int fake_ll;
int layer2;
};
/*
......@@ -706,6 +739,8 @@ struct qeth_card {
#ifdef CONFIG_QETH_VLAN
spinlock_t vlanlock;
struct vlan_group *vlangrp;
__u8 vlans_current[VLAN_GROUP_ARRAY_LEN/(8*sizeof(__u8))];
__u8 vlans_new[VLAN_GROUP_ARRAY_LEN/(8*sizeof(__u8))];
#endif
struct work_struct kernel_thread_starter;
spinlock_t thread_mask_lock;
......@@ -779,9 +814,11 @@ qeth_get_hlen(__u8 link_type)
}
inline static unsigned short
qeth_get_netdev_flags(int cardtype)
qeth_get_netdev_flags(struct qeth_card *card)
{
switch (cardtype) {
if (card->options.layer2)
return 0;
switch (card->info.type) {
case QETH_CARD_TYPE_IQD:
return IFF_NOARP;
#ifdef CONFIG_QETH_IPV6
......
This diff is collapsed.
......@@ -14,7 +14,7 @@
#include <asm/qeth.h>
#define VERSION_QETH_MPC_H "$Revision: 1.36 $"
#define VERSION_QETH_MPC_H "$Revision: 1.38 $"
extern const char *VERSION_QETH_MPC_C;
......@@ -105,6 +105,12 @@ enum qeth_routing_types {
enum qeth_ipa_cmds {
IPA_CMD_STARTLAN = 0x01,
IPA_CMD_STOPLAN = 0x02,
IPA_CMD_SETVMAC = 0x21,
IPA_CMD_DELVMAC = 0x22,
IPA_CMD_SETGMAC = 0x23,
IPA_CMD_DELGMAC = 0x24,
IPA_CMD_SETVLAN = 0x25,
IPA_CMD_DELVLAN = 0x26,
IPA_CMD_SETIP = 0xb1,
IPA_CMD_DELIP = 0xb7,
IPA_CMD_QIPASSIST = 0xb2,
......@@ -239,6 +245,16 @@ struct qeth_ipacmd_setdelipm {
__u8 ip4[4];
} __attribute__ ((packed));
struct qeth_ipacmd_layer2setdelmac {
__u32 mac_length;
__u8 mac[6];
} __attribute__ ((packed));
struct qeth_ipacmd_layer2setdelvlan {
__u16 vlan_id;
} __attribute__ ((packed));
struct qeth_ipacmd_setassparms_hdr {
__u32 assist_no;
__u16 length;
......@@ -381,13 +397,15 @@ struct qeth_ipacmd_hdr {
struct qeth_ipa_cmd {
struct qeth_ipacmd_hdr hdr;
union {
struct qeth_ipacmd_setdelip4 setdelip4;
struct qeth_ipacmd_setdelip6 setdelip6;
struct qeth_ipacmd_setdelipm setdelipm;
struct qeth_ipacmd_setassparms setassparms;
struct qeth_create_destroy_address create_destroy_addr;
struct qeth_ipacmd_setadpparms setadapterparms;
struct qeth_set_routing setrtg;
struct qeth_ipacmd_setdelip4 setdelip4;
struct qeth_ipacmd_setdelip6 setdelip6;
struct qeth_ipacmd_setdelipm setdelipm;
struct qeth_ipacmd_setassparms setassparms;
struct qeth_ipacmd_layer2setdelmac setdelmac;
struct qeth_ipacmd_layer2setdelvlan setdelvlan;
struct qeth_create_destroy_address create_destroy_addr;
struct qeth_ipacmd_setadpparms setadapterparms;
struct qeth_set_routing setrtg;
} data;
} __attribute__ ((packed));
......@@ -459,6 +477,11 @@ extern unsigned char ULP_ENABLE[];
(PDU_ENCAPSULATION(buffer) + 0x17)
#define QETH_ULP_ENABLE_RESP_LINK_TYPE(buffer) \
(PDU_ENCAPSULATION(buffer)+ 0x2b)
/* Layer 2 defintions */
#define QETH_PROT_LAYER2 0x08
#define QETH_PROT_TCPIP 0x03
#define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer+0x50)
#define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer+0x19)
extern unsigned char ULP_SETUP[];
#define ULP_SETUP_SIZE 0x6c
......
/*
*
* linux/drivers/s390/net/qeth_sys.c ($Revision: 1.33 $)
* linux/drivers/s390/net/qeth_sys.c ($Revision: 1.35 $)
*
* 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.33 $";
const char *VERSION_QETH_SYS_C = "$Revision: 1.35 $";
/*****************************************************************************/
/* */
......@@ -694,6 +694,44 @@ qeth_dev_canonical_macaddr_store(struct device *dev, const char *buf,
static DEVICE_ATTR(canonical_macaddr, 0644, qeth_dev_canonical_macaddr_show,
qeth_dev_canonical_macaddr_store);
static ssize_t
qeth_dev_layer2_show(struct device *dev, char *buf)
{
struct qeth_card *card = dev->driver_data;
if (!card)
return -EINVAL;
return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);
}
static ssize_t
qeth_dev_layer2_store(struct device *dev, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
int i;
if (!card)
return -EINVAL;
if ((card->state != CARD_STATE_DOWN) &&
(card->state != CARD_STATE_RECOVER))
return -EPERM;
i = simple_strtoul(buf, &tmp, 16);
if ((i == 0) || (i == 1))
card->options.layer2 = i;
else {
PRINT_WARN("layer2: write 0 or 1 to this file!\n");
return -EINVAL;
}
return count;
}
static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
qeth_dev_layer2_store);
static struct device_attribute * qeth_device_attrs[] = {
&dev_attr_state,
&dev_attr_chpid,
......@@ -714,6 +752,7 @@ static struct device_attribute * qeth_device_attrs[] = {
&dev_attr_recover,
&dev_attr_broadcast_mode,
&dev_attr_canonical_macaddr,
&dev_attr_layer2,
NULL,
};
......@@ -729,6 +768,15 @@ struct device_attribute dev_attr_##_id = { \
.store = _store, \
};
int
qeth_check_layer2(struct qeth_card *card)
{
if (card->options.layer2)
return -EPERM;
return 0;
}
static ssize_t
qeth_dev_ipato_enable_show(struct device *dev, char *buf)
{
......@@ -737,6 +785,8 @@ qeth_dev_ipato_enable_show(struct device *dev, char *buf)
if (!card)
return -EINVAL;
if (qeth_check_layer2(card))
return -EPERM;
return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
}
......@@ -753,6 +803,9 @@ qeth_dev_ipato_enable_store(struct device *dev, const char *buf, size_t count)
(card->state != CARD_STATE_RECOVER))
return -EPERM;
if (qeth_check_layer2(card))
return -EPERM;
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "toggle")){
card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
......@@ -780,6 +833,9 @@ qeth_dev_ipato_invert4_show(struct device *dev, char *buf)
if (!card)
return -EINVAL;
if (qeth_check_layer2(card))
return -EPERM;
return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
}
......@@ -792,6 +848,9 @@ qeth_dev_ipato_invert4_store(struct device *dev, const char *buf, size_t count)
if (!card)
return -EINVAL;
if (qeth_check_layer2(card))
return -EPERM;
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "toggle")){
card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
......@@ -820,6 +879,9 @@ qeth_dev_ipato_add_show(char *buf, struct qeth_card *card,
char addr_str[49];
int i = 0;
if (qeth_check_layer2(card))
return -EPERM;
spin_lock_irqsave(&card->ip_lock, flags);
list_for_each_entry(ipatoe, &card->ipato.entries, entry){
if (ipatoe->proto != proto)
......@@ -880,6 +942,8 @@ qeth_dev_ipato_add_store(const char *buf, size_t count,
int mask_bits;
int rc;
if (qeth_check_layer2(card))
return -EPERM;
if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
return rc;
......@@ -923,6 +987,8 @@ qeth_dev_ipato_del_store(const char *buf, size_t count,
int mask_bits;
int rc;
if (qeth_check_layer2(card))
return -EPERM;
if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
return rc;
......@@ -954,6 +1020,9 @@ qeth_dev_ipato_invert6_show(struct device *dev, char *buf)
if (!card)
return -EINVAL;
if (qeth_check_layer2(card))
return -EPERM;
return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
}
......@@ -966,6 +1035,9 @@ qeth_dev_ipato_invert6_store(struct device *dev, const char *buf, size_t count)
if (!card)
return -EINVAL;
if (qeth_check_layer2(card))
return -EPERM;
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "toggle")){
card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
......@@ -1054,6 +1126,9 @@ qeth_dev_vipa_add_show(char *buf, struct qeth_card *card,
unsigned long flags;
int i = 0;
if (qeth_check_layer2(card))
return -EPERM;
spin_lock_irqsave(&card->ip_lock, flags);
list_for_each_entry(ipaddr, &card->ip_list, entry){
if (ipaddr->proto != proto)
......@@ -1098,6 +1173,8 @@ qeth_dev_vipa_add_store(const char *buf, size_t count,
u8 addr[16] = {0, };
int rc;
if (qeth_check_layer2(card))
return -EPERM;
if ((rc = qeth_parse_vipae(buf, proto, addr)))
return rc;
......@@ -1129,6 +1206,8 @@ qeth_dev_vipa_del_store(const char *buf, size_t count,
u8 addr[16];
int rc;
if (qeth_check_layer2(card))
return -EPERM;
if ((rc = qeth_parse_vipae(buf, proto, addr)))
return rc;
......@@ -1186,6 +1265,9 @@ qeth_dev_vipa_del6_store(struct device *dev, const char *buf, size_t count)
if (!card)
return -EINVAL;
if (qeth_check_layer2(card))
return -EPERM;
return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
}
......@@ -1217,6 +1299,9 @@ qeth_dev_rxip_add_show(char *buf, struct qeth_card *card,
unsigned long flags;
int i = 0;
if (qeth_check_layer2(card))
return -EPERM;
spin_lock_irqsave(&card->ip_lock, flags);
list_for_each_entry(ipaddr, &card->ip_list, entry){
if (ipaddr->proto != proto)
......@@ -1261,6 +1346,8 @@ qeth_dev_rxip_add_store(const char *buf, size_t count,
u8 addr[16] = {0, };
int rc;
if (qeth_check_layer2(card))
return -EPERM;
if ((rc = qeth_parse_rxipe(buf, proto, addr)))
return rc;
......@@ -1292,6 +1379,8 @@ qeth_dev_rxip_del_store(const char *buf, size_t count,
u8 addr[16];
int rc;
if (qeth_check_layer2(card))
return -EPERM;
if ((rc = qeth_parse_rxipe(buf, proto, addr)))
return rc;
......
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