提交 4a71df50 编写于 作者: F Frank Blaschka 提交者: Jeff Garzik

qeth: new qeth device driver

List of major changes and improvements:
 no manipulation of the global ARP constructor
 clean code split into core, layer 2 and layer 3 functionality
 better exploitation of the ethtool interface
 better representation of the various hardware capabilities
 fix packet socket support (tcpdump), no fake_ll required
 osasnmpd notification via udev events
 coding style and beautification
Signed-off-by: NFrank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: NJeff Garzik <jeff@garzik.org>
上级 04885948
......@@ -537,11 +537,9 @@ CONFIG_CTC=m
# CONFIG_SMSGIUCV is not set
# CONFIG_CLAW is not set
CONFIG_QETH=y
#
# Gigabit Ethernet default settings
#
# CONFIG_QETH_IPV6 is not set
CONFIG_QETH_L2=y
CONFIG_QETH_L3=y
CONFIG_QETH_IPV6=y
CONFIG_CCWGROUP=y
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
......
......@@ -67,23 +67,26 @@ config QETH
To compile this driver as a module, choose M.
The module name is qeth.ko.
config QETH_L2
tristate "qeth layer 2 device support"
depends on QETH
help
Select this option to be able to run qeth devices in layer 2 mode.
To compile as a module, choose M. The module name is qeth_l2.ko.
If unsure, choose y.
comment "Gigabit Ethernet default settings"
depends on QETH
config QETH_L3
tristate "qeth layer 3 device support"
depends on QETH
help
Select this option to be able to run qeth devices in layer 3 mode.
To compile as a module choose M. The module name is qeth_l3.ko.
If unsure, choose Y.
config QETH_IPV6
bool "IPv6 support for gigabit ethernet"
depends on (QETH = IPV6) || (QETH && IPV6 = 'y')
help
If CONFIG_QETH is switched on, this option will include IPv6
support in the qeth device driver.
config QETH_VLAN
bool "VLAN support for gigabit ethernet"
depends on (QETH = VLAN_8021Q) || (QETH && VLAN_8021Q = 'y')
help
If CONFIG_QETH is switched on, this option will include IEEE
802.1q VLAN support in the qeth device driver.
bool
depends on (QETH_L3 = IPV6) || (QETH_L3 && IPV6 = 'y')
default y
config CCWGROUP
tristate
......
......@@ -8,6 +8,9 @@ obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
obj-$(CONFIG_LCS) += lcs.o cu3088.o
obj-$(CONFIG_CLAW) += claw.o cu3088.o
qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o
qeth-$(CONFIG_PROC_FS) += qeth_proc.o
qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o qeth_core_offl.o
obj-$(CONFIG_QETH) += qeth.o
qeth_l2-y += qeth_l2_main.o
obj-$(CONFIG_QETH_L2) += qeth_l2.o
qeth_l3-y += qeth_l3_main.o qeth_l3_sys.o
obj-$(CONFIG_QETH_L3) += qeth_l3.o
此差异已折叠。
此差异已折叠。
/*
* drivers/s390/net/qeth_core_mpc.c
*
* Copyright IBM Corp. 2007
* Author(s): Frank Pavlic <fpavlic@de.ibm.com>,
* Thomas Spatzier <tspat@de.ibm.com>,
* Frank Blaschka <frank.blaschka@de.ibm.com>
*/
#include <linux/module.h>
#include <asm/cio.h>
#include "qeth_core_mpc.h"
unsigned char IDX_ACTIVATE_READ[] = {
0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x19, 0x01, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc1,
0xd3, 0xd3, 0xd6, 0xd3, 0xc5, 0x40, 0x00, 0x00,
0x00, 0x00
};
unsigned char IDX_ACTIVATE_WRITE[] = {
0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x15, 0x01, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc1,
0xd3, 0xd3, 0xd6, 0xd3, 0xc5, 0x40, 0x00, 0x00,
0x00, 0x00
};
unsigned char CM_ENABLE[] = {
0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x63,
0x10, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
0x81, 0x7e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x23,
0x00, 0x00, 0x23, 0x05, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x40,
0x00, 0x0c, 0x41, 0x02, 0x00, 0x17, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x0b, 0x04, 0x01,
0x7e, 0x04, 0x05, 0x00, 0x01, 0x01, 0x0f,
0x00,
0x0c, 0x04, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff
};
unsigned char CM_SETUP[] = {
0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x64,
0x10, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
0x81, 0x7e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x24,
0x00, 0x00, 0x24, 0x05, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x40,
0x00, 0x0c, 0x41, 0x04, 0x00, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x09, 0x04, 0x04,
0x05, 0x00, 0x01, 0x01, 0x11,
0x00, 0x09, 0x04,
0x05, 0x05, 0x00, 0x00, 0x00, 0x00,
0x00, 0x06,
0x04, 0x06, 0xc8, 0x00
};
unsigned char ULP_ENABLE[] = {
0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x6b,
0x10, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
0x41, 0x7e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x2b,
0x00, 0x00, 0x2b, 0x05, 0x20, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x40,
0x00, 0x0c, 0x41, 0x02, 0x00, 0x1f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x0b, 0x04, 0x01,
0x03, 0x04, 0x05, 0x00, 0x01, 0x01, 0x12,
0x00,
0x14, 0x04, 0x0a, 0x00, 0x20, 0x00, 0x00, 0xff,
0xff, 0x00, 0x08, 0xc8, 0xe8, 0xc4, 0xf1, 0xc7,
0xf1, 0x00, 0x00
};
unsigned char ULP_SETUP[] = {
0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x6c,
0x10, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
0x41, 0x7e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x01, 0x00, 0x24, 0x00, 0x2c,
0x00, 0x00, 0x2c, 0x05, 0x20, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x40,
0x00, 0x0c, 0x41, 0x04, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x09, 0x04, 0x04,
0x05, 0x00, 0x01, 0x01, 0x14,
0x00, 0x09, 0x04,
0x05, 0x05, 0x30, 0x01, 0x00, 0x00,
0x00, 0x06,
0x04, 0x06, 0x40, 0x00,
0x00, 0x08, 0x04, 0x0b,
0x00, 0x00, 0x00, 0x00
};
unsigned char DM_ACT[] = {
0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x55,
0x10, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
0x41, 0x7e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x02, 0x00, 0x24, 0x00, 0x15,
0x00, 0x00, 0x2c, 0x05, 0x20, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x40,
0x00, 0x0c, 0x43, 0x60, 0x00, 0x09, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x09, 0x04, 0x04,
0x05, 0x40, 0x01, 0x01, 0x00
};
unsigned char IPA_PDU_HEADER[] = {
0x00, 0xe0, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77,
0x00, 0x00, 0x00, 0x14, 0x00, 0x00,
(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) / 256,
(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) % 256,
0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0xc1, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
sizeof(struct qeth_ipa_cmd) / 256,
sizeof(struct qeth_ipa_cmd) % 256,
0x00,
sizeof(struct qeth_ipa_cmd) / 256,
sizeof(struct qeth_ipa_cmd) % 256,
0x05,
0x77, 0x77, 0x77, 0x77,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00,
sizeof(struct qeth_ipa_cmd) / 256,
sizeof(struct qeth_ipa_cmd) % 256,
0x00, 0x00, 0x00, 0x40,
};
EXPORT_SYMBOL_GPL(IPA_PDU_HEADER);
unsigned char WRITE_CCW[] = {
0x01, CCW_FLAG_SLI, 0, 0,
0, 0, 0, 0
};
unsigned char READ_CCW[] = {
0x02, CCW_FLAG_SLI, 0, 0,
0, 0, 0, 0
};
struct ipa_rc_msg {
enum qeth_ipa_return_codes rc;
char *msg;
};
static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
{IPA_RC_SUCCESS, "success"},
{IPA_RC_NOTSUPP, "Command not supported"},
{IPA_RC_IP_TABLE_FULL, "Add Addr IP Table Full - ipv6"},
{IPA_RC_UNKNOWN_ERROR, "IPA command failed - reason unknown"},
{IPA_RC_UNSUPPORTED_COMMAND, "Command not supported"},
{IPA_RC_DUP_IPV6_REMOTE, "ipv6 address already registered remote"},
{IPA_RC_DUP_IPV6_HOME, "ipv6 address already registered"},
{IPA_RC_UNREGISTERED_ADDR, "Address not registered"},
{IPA_RC_NO_ID_AVAILABLE, "No identifiers available"},
{IPA_RC_ID_NOT_FOUND, "Identifier not found"},
{IPA_RC_INVALID_IP_VERSION, "IP version incorrect"},
{IPA_RC_LAN_FRAME_MISMATCH, "LAN and frame mismatch"},
{IPA_RC_L2_UNSUPPORTED_CMD, "Unsupported layer 2 command"},
{IPA_RC_L2_DUP_MAC, "Duplicate MAC address"},
{IPA_RC_L2_ADDR_TABLE_FULL, "Layer2 address table full"},
{IPA_RC_L2_DUP_LAYER3_MAC, "Duplicate with layer 3 MAC"},
{IPA_RC_L2_GMAC_NOT_FOUND, "GMAC not found"},
{IPA_RC_L2_MAC_NOT_FOUND, "L2 mac address not found"},
{IPA_RC_L2_INVALID_VLAN_ID, "L2 invalid vlan id"},
{IPA_RC_L2_DUP_VLAN_ID, "L2 duplicate vlan id"},
{IPA_RC_L2_VLAN_ID_NOT_FOUND, "L2 vlan id not found"},
{IPA_RC_DATA_MISMATCH, "Data field mismatch (v4/v6 mixed)"},
{IPA_RC_INVALID_MTU_SIZE, "Invalid MTU size"},
{IPA_RC_INVALID_LANTYPE, "Invalid LAN type"},
{IPA_RC_INVALID_LANNUM, "Invalid LAN num"},
{IPA_RC_DUPLICATE_IP_ADDRESS, "Address already registered"},
{IPA_RC_IP_ADDR_TABLE_FULL, "IP address table full"},
{IPA_RC_LAN_PORT_STATE_ERROR, "LAN port state error"},
{IPA_RC_SETIP_NO_STARTLAN, "Setip no startlan received"},
{IPA_RC_SETIP_ALREADY_RECEIVED, "Setip already received"},
{IPA_RC_IP_ADDR_ALREADY_USED, "IP address already in use on LAN"},
{IPA_RC_MULTICAST_FULL, "No task available, multicast full"},
{IPA_RC_SETIP_INVALID_VERSION, "SETIP invalid IP version"},
{IPA_RC_UNSUPPORTED_SUBCMD, "Unsupported assist subcommand"},
{IPA_RC_ARP_ASSIST_NO_ENABLE, "Only partial success, no enable"},
{IPA_RC_PRIMARY_ALREADY_DEFINED, "Primary already defined"},
{IPA_RC_SECOND_ALREADY_DEFINED, "Secondary already defined"},
{IPA_RC_INVALID_SETRTG_INDICATOR, "Invalid SETRTG indicator"},
{IPA_RC_MC_ADDR_ALREADY_DEFINED, "Multicast address already defined"},
{IPA_RC_LAN_OFFLINE, "STRTLAN_LAN_DISABLED - LAN offline"},
{IPA_RC_INVALID_IP_VERSION2, "Invalid IP version"},
{IPA_RC_FFFF, "Unknown Error"}
};
char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc)
{
int x = 0;
qeth_ipa_rc_msg[sizeof(qeth_ipa_rc_msg) /
sizeof(struct ipa_rc_msg) - 1].rc = rc;
while (qeth_ipa_rc_msg[x].rc != rc)
x++;
return qeth_ipa_rc_msg[x].msg;
}
struct ipa_cmd_names {
enum qeth_ipa_cmds cmd;
char *name;
};
static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
{IPA_CMD_STARTLAN, "startlan"},
{IPA_CMD_STOPLAN, "stoplan"},
{IPA_CMD_SETVMAC, "setvmac"},
{IPA_CMD_DELVMAC, "delvmca"},
{IPA_CMD_SETGMAC, "setgmac"},
{IPA_CMD_DELGMAC, "delgmac"},
{IPA_CMD_SETVLAN, "setvlan"},
{IPA_CMD_DELVLAN, "delvlan"},
{IPA_CMD_SETCCID, "setccid"},
{IPA_CMD_DELCCID, "delccid"},
{IPA_CMD_MODCCID, "modccid"},
{IPA_CMD_SETIP, "setip"},
{IPA_CMD_QIPASSIST, "qipassist"},
{IPA_CMD_SETASSPARMS, "setassparms"},
{IPA_CMD_SETIPM, "setipm"},
{IPA_CMD_DELIPM, "delipm"},
{IPA_CMD_SETRTG, "setrtg"},
{IPA_CMD_DELIP, "delip"},
{IPA_CMD_SETADAPTERPARMS, "setadapterparms"},
{IPA_CMD_SET_DIAG_ASS, "set_diag_ass"},
{IPA_CMD_CREATE_ADDR, "create_addr"},
{IPA_CMD_DESTROY_ADDR, "destroy_addr"},
{IPA_CMD_REGISTER_LOCAL_ADDR, "register_local_addr"},
{IPA_CMD_UNREGISTER_LOCAL_ADDR, "unregister_local_addr"},
{IPA_CMD_UNKNOWN, "unknown"},
};
char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd)
{
int x = 0;
qeth_ipa_cmd_names[
sizeof(qeth_ipa_cmd_names) /
sizeof(struct ipa_cmd_names)-1].cmd = cmd;
while (qeth_ipa_cmd_names[x].cmd != cmd)
x++;
return qeth_ipa_cmd_names[x].name;
}
/*
* drivers/s390/net/qeth_core_mpc.h
*
* Copyright IBM Corp. 2007
* Author(s): Frank Pavlic <fpavlic@de.ibm.com>,
* Thomas Spatzier <tspat@de.ibm.com>,
* Frank Blaschka <frank.blaschka@de.ibm.com>
*/
#ifndef __QETH_CORE_MPC_H__
#define __QETH_CORE_MPC_H__
#include <asm/qeth.h>
#define IPA_PDU_HEADER_SIZE 0x40
#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer + 0x0e)
#define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer + 0x26)
#define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer + 0x29)
#define QETH_IPA_PDU_LEN_PDU3(buffer) (buffer + 0x3a)
extern unsigned char IPA_PDU_HEADER[];
#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer + 0x2c)
#define IPA_CMD_LENGTH (IPA_PDU_HEADER_SIZE + sizeof(struct qeth_ipa_cmd))
#define QETH_SEQ_NO_LENGTH 4
#define QETH_MPC_TOKEN_LENGTH 4
#define QETH_MCL_LENGTH 4
#define OSA_ADDR_LEN 6
#define QETH_TIMEOUT (10 * HZ)
#define QETH_IPA_TIMEOUT (45 * HZ)
#define QETH_IDX_COMMAND_SEQNO 0xffff0000
#define SR_INFO_LEN 16
#define QETH_CLEAR_CHANNEL_PARM -10
#define QETH_HALT_CHANNEL_PARM -11
#define QETH_RCD_PARM -12
/*****************************************************************************/
/* IP Assist related definitions */
/*****************************************************************************/
#define IPA_CMD_INITIATOR_HOST 0x00
#define IPA_CMD_INITIATOR_OSA 0x01
#define IPA_CMD_INITIATOR_HOST_REPLY 0x80
#define IPA_CMD_INITIATOR_OSA_REPLY 0x81
#define IPA_CMD_PRIM_VERSION_NO 0x01
enum qeth_card_types {
QETH_CARD_TYPE_UNKNOWN = 0,
QETH_CARD_TYPE_OSAE = 10,
QETH_CARD_TYPE_IQD = 1234,
QETH_CARD_TYPE_OSN = 11,
};
#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
/* only the first two bytes are looked at in qeth_get_cardname_short */
enum qeth_link_types {
QETH_LINK_TYPE_FAST_ETH = 0x01,
QETH_LINK_TYPE_HSTR = 0x02,
QETH_LINK_TYPE_GBIT_ETH = 0x03,
QETH_LINK_TYPE_OSN = 0x04,
QETH_LINK_TYPE_10GBIT_ETH = 0x10,
QETH_LINK_TYPE_LANE_ETH100 = 0x81,
QETH_LINK_TYPE_LANE_TR = 0x82,
QETH_LINK_TYPE_LANE_ETH1000 = 0x83,
QETH_LINK_TYPE_LANE = 0x88,
QETH_LINK_TYPE_ATM_NATIVE = 0x90,
};
enum qeth_tr_macaddr_modes {
QETH_TR_MACADDR_NONCANONICAL = 0,
QETH_TR_MACADDR_CANONICAL = 1,
};
enum qeth_tr_broadcast_modes {
QETH_TR_BROADCAST_ALLRINGS = 0,
QETH_TR_BROADCAST_LOCAL = 1,
};
/* these values match CHECKSUM_* in include/linux/skbuff.h */
enum qeth_checksum_types {
SW_CHECKSUMMING = 0, /* TODO: set to bit flag used in IPA Command */
HW_CHECKSUMMING = 1,
NO_CHECKSUMMING = 2,
};
#define QETH_CHECKSUM_DEFAULT SW_CHECKSUMMING
/*
* Routing stuff
*/
#define RESET_ROUTING_FLAG 0x10 /* indicate that routing type shall be set */
enum qeth_routing_types {
/* TODO: set to bit flag used in IPA Command */
NO_ROUTER = 0,
PRIMARY_ROUTER = 1,
SECONDARY_ROUTER = 2,
MULTICAST_ROUTER = 3,
PRIMARY_CONNECTOR = 4,
SECONDARY_CONNECTOR = 5,
};
/* IPA Commands */
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_SETCCID = 0x41,
IPA_CMD_DELCCID = 0x42,
IPA_CMD_MODCCID = 0x43,
IPA_CMD_SETIP = 0xb1,
IPA_CMD_QIPASSIST = 0xb2,
IPA_CMD_SETASSPARMS = 0xb3,
IPA_CMD_SETIPM = 0xb4,
IPA_CMD_DELIPM = 0xb5,
IPA_CMD_SETRTG = 0xb6,
IPA_CMD_DELIP = 0xb7,
IPA_CMD_SETADAPTERPARMS = 0xb8,
IPA_CMD_SET_DIAG_ASS = 0xb9,
IPA_CMD_CREATE_ADDR = 0xc3,
IPA_CMD_DESTROY_ADDR = 0xc4,
IPA_CMD_REGISTER_LOCAL_ADDR = 0xd1,
IPA_CMD_UNREGISTER_LOCAL_ADDR = 0xd2,
IPA_CMD_UNKNOWN = 0x00
};
enum qeth_ip_ass_cmds {
IPA_CMD_ASS_START = 0x0001,
IPA_CMD_ASS_STOP = 0x0002,
IPA_CMD_ASS_CONFIGURE = 0x0003,
IPA_CMD_ASS_ENABLE = 0x0004,
};
enum qeth_arp_process_subcmds {
IPA_CMD_ASS_ARP_SET_NO_ENTRIES = 0x0003,
IPA_CMD_ASS_ARP_QUERY_CACHE = 0x0004,
IPA_CMD_ASS_ARP_ADD_ENTRY = 0x0005,
IPA_CMD_ASS_ARP_REMOVE_ENTRY = 0x0006,
IPA_CMD_ASS_ARP_FLUSH_CACHE = 0x0007,
IPA_CMD_ASS_ARP_QUERY_INFO = 0x0104,
IPA_CMD_ASS_ARP_QUERY_STATS = 0x0204,
};
/* Return Codes for IPA Commands
* according to OSA card Specs */
enum qeth_ipa_return_codes {
IPA_RC_SUCCESS = 0x0000,
IPA_RC_NOTSUPP = 0x0001,
IPA_RC_IP_TABLE_FULL = 0x0002,
IPA_RC_UNKNOWN_ERROR = 0x0003,
IPA_RC_UNSUPPORTED_COMMAND = 0x0004,
IPA_RC_DUP_IPV6_REMOTE = 0x0008,
IPA_RC_DUP_IPV6_HOME = 0x0010,
IPA_RC_UNREGISTERED_ADDR = 0x0011,
IPA_RC_NO_ID_AVAILABLE = 0x0012,
IPA_RC_ID_NOT_FOUND = 0x0013,
IPA_RC_INVALID_IP_VERSION = 0x0020,
IPA_RC_LAN_FRAME_MISMATCH = 0x0040,
IPA_RC_L2_UNSUPPORTED_CMD = 0x2003,
IPA_RC_L2_DUP_MAC = 0x2005,
IPA_RC_L2_ADDR_TABLE_FULL = 0x2006,
IPA_RC_L2_DUP_LAYER3_MAC = 0x200a,
IPA_RC_L2_GMAC_NOT_FOUND = 0x200b,
IPA_RC_L2_MAC_NOT_FOUND = 0x2010,
IPA_RC_L2_INVALID_VLAN_ID = 0x2015,
IPA_RC_L2_DUP_VLAN_ID = 0x2016,
IPA_RC_L2_VLAN_ID_NOT_FOUND = 0x2017,
IPA_RC_DATA_MISMATCH = 0xe001,
IPA_RC_INVALID_MTU_SIZE = 0xe002,
IPA_RC_INVALID_LANTYPE = 0xe003,
IPA_RC_INVALID_LANNUM = 0xe004,
IPA_RC_DUPLICATE_IP_ADDRESS = 0xe005,
IPA_RC_IP_ADDR_TABLE_FULL = 0xe006,
IPA_RC_LAN_PORT_STATE_ERROR = 0xe007,
IPA_RC_SETIP_NO_STARTLAN = 0xe008,
IPA_RC_SETIP_ALREADY_RECEIVED = 0xe009,
IPA_RC_IP_ADDR_ALREADY_USED = 0xe00a,
IPA_RC_MULTICAST_FULL = 0xe00b,
IPA_RC_SETIP_INVALID_VERSION = 0xe00d,
IPA_RC_UNSUPPORTED_SUBCMD = 0xe00e,
IPA_RC_ARP_ASSIST_NO_ENABLE = 0xe00f,
IPA_RC_PRIMARY_ALREADY_DEFINED = 0xe010,
IPA_RC_SECOND_ALREADY_DEFINED = 0xe011,
IPA_RC_INVALID_SETRTG_INDICATOR = 0xe012,
IPA_RC_MC_ADDR_ALREADY_DEFINED = 0xe013,
IPA_RC_LAN_OFFLINE = 0xe080,
IPA_RC_INVALID_IP_VERSION2 = 0xf001,
IPA_RC_FFFF = 0xffff
};
/* IPA function flags; each flag marks availability of respective function */
enum qeth_ipa_funcs {
IPA_ARP_PROCESSING = 0x00000001L,
IPA_INBOUND_CHECKSUM = 0x00000002L,
IPA_OUTBOUND_CHECKSUM = 0x00000004L,
IPA_IP_FRAGMENTATION = 0x00000008L,
IPA_FILTERING = 0x00000010L,
IPA_IPV6 = 0x00000020L,
IPA_MULTICASTING = 0x00000040L,
IPA_IP_REASSEMBLY = 0x00000080L,
IPA_QUERY_ARP_COUNTERS = 0x00000100L,
IPA_QUERY_ARP_ADDR_INFO = 0x00000200L,
IPA_SETADAPTERPARMS = 0x00000400L,
IPA_VLAN_PRIO = 0x00000800L,
IPA_PASSTHRU = 0x00001000L,
IPA_FLUSH_ARP_SUPPORT = 0x00002000L,
IPA_FULL_VLAN = 0x00004000L,
IPA_INBOUND_PASSTHRU = 0x00008000L,
IPA_SOURCE_MAC = 0x00010000L,
IPA_OSA_MC_ROUTER = 0x00020000L,
IPA_QUERY_ARP_ASSIST = 0x00040000L,
IPA_INBOUND_TSO = 0x00080000L,
IPA_OUTBOUND_TSO = 0x00100000L,
};
/* SETIP/DELIP IPA Command: ***************************************************/
enum qeth_ipa_setdelip_flags {
QETH_IPA_SETDELIP_DEFAULT = 0x00L, /* default */
QETH_IPA_SETIP_VIPA_FLAG = 0x01L, /* no grat. ARP */
QETH_IPA_SETIP_TAKEOVER_FLAG = 0x02L, /* nofail on grat. ARP */
QETH_IPA_DELIP_ADDR_2_B_TAKEN_OVER = 0x20L,
QETH_IPA_DELIP_VIPA_FLAG = 0x40L,
QETH_IPA_DELIP_ADDR_NEEDS_SETIP = 0x80L,
};
/* SETADAPTER IPA Command: ****************************************************/
enum qeth_ipa_setadp_cmd {
IPA_SETADP_QUERY_COMMANDS_SUPPORTED = 0x0001,
IPA_SETADP_ALTER_MAC_ADDRESS = 0x0002,
IPA_SETADP_ADD_DELETE_GROUP_ADDRESS = 0x0004,
IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR = 0x0008,
IPA_SETADP_SET_ADDRESSING_MODE = 0x0010,
IPA_SETADP_SET_CONFIG_PARMS = 0x0020,
IPA_SETADP_SET_CONFIG_PARMS_EXTENDED = 0x0040,
IPA_SETADP_SET_BROADCAST_MODE = 0x0080,
IPA_SETADP_SEND_OSA_MESSAGE = 0x0100,
IPA_SETADP_SET_SNMP_CONTROL = 0x0200,
IPA_SETADP_QUERY_CARD_INFO = 0x0400,
IPA_SETADP_SET_PROMISC_MODE = 0x0800,
};
enum qeth_ipa_mac_ops {
CHANGE_ADDR_READ_MAC = 0,
CHANGE_ADDR_REPLACE_MAC = 1,
CHANGE_ADDR_ADD_MAC = 2,
CHANGE_ADDR_DEL_MAC = 4,
CHANGE_ADDR_RESET_MAC = 8,
};
enum qeth_ipa_addr_ops {
CHANGE_ADDR_READ_ADDR = 0,
CHANGE_ADDR_ADD_ADDR = 1,
CHANGE_ADDR_DEL_ADDR = 2,
CHANGE_ADDR_FLUSH_ADDR_TABLE = 4,
};
enum qeth_ipa_promisc_modes {
SET_PROMISC_MODE_OFF = 0,
SET_PROMISC_MODE_ON = 1,
};
/* (SET)DELIP(M) IPA stuff ***************************************************/
struct qeth_ipacmd_setdelip4 {
__u8 ip_addr[4];
__u8 mask[4];
__u32 flags;
} __attribute__ ((packed));
struct qeth_ipacmd_setdelip6 {
__u8 ip_addr[16];
__u8 mask[16];
__u32 flags;
} __attribute__ ((packed));
struct qeth_ipacmd_setdelipm {
__u8 mac[6];
__u8 padding[2];
__u8 ip6[12];
__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;
__u16 command_code;
__u16 return_code;
__u8 number_of_replies;
__u8 seq_no;
} __attribute__((packed));
struct qeth_arp_query_data {
__u16 request_bits;
__u16 reply_bits;
__u32 no_entries;
char data;
} __attribute__((packed));
/* used as parameter for arp_query reply */
struct qeth_arp_query_info {
__u32 udata_len;
__u16 mask_bits;
__u32 udata_offset;
__u32 no_entries;
char *udata;
};
/* SETASSPARMS IPA Command: */
struct qeth_ipacmd_setassparms {
struct qeth_ipacmd_setassparms_hdr hdr;
union {
__u32 flags_32bit;
struct qeth_arp_cache_entry add_arp_entry;
struct qeth_arp_query_data query_arp;
__u8 ip[16];
} data;
} __attribute__ ((packed));
/* SETRTG IPA Command: ****************************************************/
struct qeth_set_routing {
__u8 type;
};
/* SETADAPTERPARMS IPA Command: *******************************************/
struct qeth_query_cmds_supp {
__u32 no_lantypes_supp;
__u8 lan_type;
__u8 reserved1[3];
__u32 supported_cmds;
__u8 reserved2[8];
} __attribute__ ((packed));
struct qeth_change_addr {
__u32 cmd;
__u32 addr_size;
__u32 no_macs;
__u8 addr[OSA_ADDR_LEN];
} __attribute__ ((packed));
struct qeth_snmp_cmd {
__u8 token[16];
__u32 request;
__u32 interface;
__u32 returncode;
__u32 firmwarelevel;
__u32 seqno;
__u8 data;
} __attribute__ ((packed));
struct qeth_snmp_ureq_hdr {
__u32 data_len;
__u32 req_len;
__u32 reserved1;
__u32 reserved2;
} __attribute__ ((packed));
struct qeth_snmp_ureq {
struct qeth_snmp_ureq_hdr hdr;
struct qeth_snmp_cmd cmd;
} __attribute__((packed));
struct qeth_ipacmd_setadpparms_hdr {
__u32 supp_hw_cmds;
__u32 reserved1;
__u16 cmdlength;
__u16 reserved2;
__u32 command_code;
__u16 return_code;
__u8 used_total;
__u8 seq_no;
__u32 reserved3;
} __attribute__ ((packed));
struct qeth_ipacmd_setadpparms {
struct qeth_ipacmd_setadpparms_hdr hdr;
union {
struct qeth_query_cmds_supp query_cmds_supp;
struct qeth_change_addr change_addr;
struct qeth_snmp_cmd snmp;
__u32 mode;
} data;
} __attribute__ ((packed));
/* CREATE_ADDR IPA Command: ***********************************************/
struct qeth_create_destroy_address {
__u8 unique_id[8];
} __attribute__ ((packed));
/* Header for each IPA command */
struct qeth_ipacmd_hdr {
__u8 command;
__u8 initiator;
__u16 seqno;
__u16 return_code;
__u8 adapter_type;
__u8 rel_adapter_no;
__u8 prim_version_no;
__u8 param_count;
__u16 prot_version;
__u32 ipa_supported;
__u32 ipa_enabled;
} __attribute__ ((packed));
/* The IPA command itself */
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_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));
/*
* special command for ARP processing.
* this is not included in setassparms command before, because we get
* problem with the size of struct qeth_ipacmd_setassparms otherwise
*/
enum qeth_ipa_arp_return_codes {
QETH_IPA_ARP_RC_SUCCESS = 0x0000,
QETH_IPA_ARP_RC_FAILED = 0x0001,
QETH_IPA_ARP_RC_NOTSUPP = 0x0002,
QETH_IPA_ARP_RC_OUT_OF_RANGE = 0x0003,
QETH_IPA_ARP_RC_Q_NOTSUPP = 0x0004,
QETH_IPA_ARP_RC_Q_NO_DATA = 0x0008,
};
extern char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
extern char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
#define QETH_SETASS_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
sizeof(struct qeth_ipacmd_setassparms_hdr))
#define QETH_IPA_ARP_DATA_POS(buffer) (buffer + IPA_PDU_HEADER_SIZE + \
QETH_SETASS_BASE_LEN)
#define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
sizeof(struct qeth_ipacmd_setadpparms_hdr))
#define QETH_SNMP_SETADP_CMDLENGTH 16
#define QETH_ARP_DATA_SIZE 3968
#define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8)
/* Helper functions */
#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
(cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
/*****************************************************************************/
/* END OF IP Assist related definitions */
/*****************************************************************************/
extern unsigned char WRITE_CCW[];
extern unsigned char READ_CCW[];
extern unsigned char CM_ENABLE[];
#define CM_ENABLE_SIZE 0x63
#define QETH_CM_ENABLE_ISSUER_RM_TOKEN(buffer) (buffer + 0x2c)
#define QETH_CM_ENABLE_FILTER_TOKEN(buffer) (buffer + 0x53)
#define QETH_CM_ENABLE_USER_DATA(buffer) (buffer + 0x5b)
#define QETH_CM_ENABLE_RESP_FILTER_TOKEN(buffer) \
(PDU_ENCAPSULATION(buffer) + 0x13)
extern unsigned char CM_SETUP[];
#define CM_SETUP_SIZE 0x64
#define QETH_CM_SETUP_DEST_ADDR(buffer) (buffer + 0x2c)
#define QETH_CM_SETUP_CONNECTION_TOKEN(buffer) (buffer + 0x51)
#define QETH_CM_SETUP_FILTER_TOKEN(buffer) (buffer + 0x5a)
#define QETH_CM_SETUP_RESP_DEST_ADDR(buffer) \
(PDU_ENCAPSULATION(buffer) + 0x1a)
extern unsigned char ULP_ENABLE[];
#define ULP_ENABLE_SIZE 0x6b
#define QETH_ULP_ENABLE_LINKNUM(buffer) (buffer + 0x61)
#define QETH_ULP_ENABLE_DEST_ADDR(buffer) (buffer + 0x2c)
#define QETH_ULP_ENABLE_FILTER_TOKEN(buffer) (buffer + 0x53)
#define QETH_ULP_ENABLE_PORTNAME_AND_LL(buffer) (buffer + 0x62)
#define QETH_ULP_ENABLE_RESP_FILTER_TOKEN(buffer) \
(PDU_ENCAPSULATION(buffer) + 0x13)
#define QETH_ULP_ENABLE_RESP_MAX_MTU(buffer) \
(PDU_ENCAPSULATION(buffer) + 0x1f)
#define QETH_ULP_ENABLE_RESP_DIFINFO_LEN(buffer) \
(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_PROT_OSN2 0x0a
#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
#define QETH_ULP_SETUP_DEST_ADDR(buffer) (buffer + 0x2c)
#define QETH_ULP_SETUP_CONNECTION_TOKEN(buffer) (buffer + 0x51)
#define QETH_ULP_SETUP_FILTER_TOKEN(buffer) (buffer + 0x5a)
#define QETH_ULP_SETUP_CUA(buffer) (buffer + 0x68)
#define QETH_ULP_SETUP_REAL_DEVADDR(buffer) (buffer + 0x6a)
#define QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(buffer) \
(PDU_ENCAPSULATION(buffer) + 0x1a)
extern unsigned char DM_ACT[];
#define DM_ACT_SIZE 0x55
#define QETH_DM_ACT_DEST_ADDR(buffer) (buffer + 0x2c)
#define QETH_DM_ACT_CONNECTION_TOKEN(buffer) (buffer + 0x51)
#define QETH_TRANSPORT_HEADER_SEQ_NO(buffer) (buffer + 4)
#define QETH_PDU_HEADER_SEQ_NO(buffer) (buffer + 0x1c)
#define QETH_PDU_HEADER_ACK_SEQ_NO(buffer) (buffer + 0x20)
extern unsigned char IDX_ACTIVATE_READ[];
extern unsigned char IDX_ACTIVATE_WRITE[];
#define IDX_ACTIVATE_SIZE 0x22
#define QETH_IDX_ACT_PNO(buffer) (buffer+0x0b)
#define QETH_IDX_ACT_ISSUER_RM_TOKEN(buffer) (buffer + 0x0c)
#define QETH_IDX_NO_PORTNAME_REQUIRED(buffer) ((buffer)[0x0b] & 0x80)
#define QETH_IDX_ACT_FUNC_LEVEL(buffer) (buffer + 0x10)
#define QETH_IDX_ACT_DATASET_NAME(buffer) (buffer + 0x16)
#define QETH_IDX_ACT_QDIO_DEV_CUA(buffer) (buffer + 0x1e)
#define QETH_IDX_ACT_QDIO_DEV_REALADDR(buffer) (buffer + 0x20)
#define QETH_IS_IDX_ACT_POS_REPLY(buffer) (((buffer)[0x08] & 3) == 2)
#define QETH_IDX_REPLY_LEVEL(buffer) (buffer + 0x12)
#define QETH_IDX_ACT_CAUSE_CODE(buffer) (buffer)[0x09]
#define PDU_ENCAPSULATION(buffer) \
(buffer + *(buffer + (*(buffer + 0x0b)) + \
*(buffer + *(buffer + 0x0b) + 0x11) + 0x07))
#define IS_IPA(buffer) \
((buffer) && \
(*(buffer + ((*(buffer + 0x0b)) + 4)) == 0xc1))
#define ADDR_FRAME_TYPE_DIX 1
#define ADDR_FRAME_TYPE_802_3 2
#define ADDR_FRAME_TYPE_TR_WITHOUT_SR 0x10
#define ADDR_FRAME_TYPE_TR_WITH_SR 0x20
#endif
此差异已折叠。
/*
* drivers/s390/net/qeth_core_offl.h
*
* Copyright IBM Corp. 2007
* Author(s): Thomas Spatzier <tspat@de.ibm.com>,
* Frank Blaschka <frank.blaschka@de.ibm.com>
*/
#ifndef __QETH_CORE_OFFL_H__
#define __QETH_CORE_OFFL_H__
struct qeth_eddp_element {
u32 flags;
u32 length;
void *addr;
};
struct qeth_eddp_context {
atomic_t refcnt;
enum qeth_large_send_types type;
int num_pages; /* # of allocated pages */
u8 **pages; /* pointers to pages */
int offset; /* offset in ctx during creation */
int num_elements; /* # of required 'SBALEs' */
struct qeth_eddp_element *elements; /* array of 'SBALEs' */
int elements_per_skb; /* # of 'SBALEs' per skb **/
};
struct qeth_eddp_context_reference {
struct list_head list;
struct qeth_eddp_context *ctx;
};
struct qeth_eddp_data {
struct qeth_hdr qh;
struct ethhdr mac;
__be16 vlan[2];
union {
struct {
struct iphdr h;
u8 options[40];
} ip4;
struct {
struct ipv6hdr h;
} ip6;
} nh;
u8 nhl;
void *nh_in_ctx; /* address of nh within the ctx */
union {
struct {
struct tcphdr h;
u8 options[40];
} tcp;
} th;
u8 thl;
void *th_in_ctx; /* address of th within the ctx */
struct sk_buff *skb;
int skb_offset;
int frag;
int frag_offset;
} __attribute__ ((packed));
extern struct qeth_eddp_context *qeth_eddp_create_context(struct qeth_card *,
struct sk_buff *, struct qeth_hdr *, unsigned char);
extern void qeth_eddp_put_context(struct qeth_eddp_context *);
extern int qeth_eddp_fill_buffer(struct qeth_qdio_out_q *,
struct qeth_eddp_context *, int);
extern void qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *);
extern int qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *,
struct qeth_eddp_context *);
void qeth_tso_fill_header(struct qeth_card *, struct qeth_hdr *,
struct sk_buff *);
void qeth_tx_csum(struct sk_buff *skb);
#endif /* __QETH_CORE_EDDP_H__ */
/*
* drivers/s390/net/qeth_core_sys.c
*
* Copyright IBM Corp. 2007
* Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
* Frank Pavlic <fpavlic@de.ibm.com>,
* Thomas Spatzier <tspat@de.ibm.com>,
* Frank Blaschka <frank.blaschka@de.ibm.com>
*/
#include <linux/list.h>
#include <linux/rwsem.h>
#include <asm/ebcdic.h>
#include "qeth_core.h"
static ssize_t qeth_dev_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
if (!card)
return -EINVAL;
switch (card->state) {
case CARD_STATE_DOWN:
return sprintf(buf, "DOWN\n");
case CARD_STATE_HARDSETUP:
return sprintf(buf, "HARDSETUP\n");
case CARD_STATE_SOFTSETUP:
return sprintf(buf, "SOFTSETUP\n");
case CARD_STATE_UP:
if (card->lan_online)
return sprintf(buf, "UP (LAN ONLINE)\n");
else
return sprintf(buf, "UP (LAN OFFLINE)\n");
case CARD_STATE_RECOVER:
return sprintf(buf, "RECOVER\n");
default:
return sprintf(buf, "UNKNOWN\n");
}
}
static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL);
static ssize_t qeth_dev_chpid_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
if (!card)
return -EINVAL;
return sprintf(buf, "%02X\n", card->info.chpid);
}
static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL);
static ssize_t qeth_dev_if_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
if (!card)
return -EINVAL;
return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card));
}
static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);
static ssize_t qeth_dev_card_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
if (!card)
return -EINVAL;
return sprintf(buf, "%s\n", qeth_get_cardname_short(card));
}
static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL);
static inline const char *qeth_get_bufsize_str(struct qeth_card *card)
{
if (card->qdio.in_buf_size == 16384)
return "16k";
else if (card->qdio.in_buf_size == 24576)
return "24k";
else if (card->qdio.in_buf_size == 32768)
return "32k";
else if (card->qdio.in_buf_size == 40960)
return "40k";
else
return "64k";
}
static ssize_t qeth_dev_inbuf_size_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
if (!card)
return -EINVAL;
return sprintf(buf, "%s\n", qeth_get_bufsize_str(card));
}
static DEVICE_ATTR(inbuf_size, 0444, qeth_dev_inbuf_size_show, NULL);
static ssize_t qeth_dev_portno_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
if (!card)
return -EINVAL;
return sprintf(buf, "%i\n", card->info.portno);
}
static ssize_t qeth_dev_portno_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
unsigned int portno;
if (!card)
return -EINVAL;
if ((card->state != CARD_STATE_DOWN) &&
(card->state != CARD_STATE_RECOVER))
return -EPERM;
portno = simple_strtoul(buf, &tmp, 16);
if (portno > QETH_MAX_PORTNO) {
PRINT_WARN("portno 0x%X is out of range\n", portno);
return -EINVAL;
}
card->info.portno = portno;
return count;
}
static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
static ssize_t qeth_dev_portname_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
char portname[9] = {0, };
if (!card)
return -EINVAL;
if (card->info.portname_required) {
memcpy(portname, card->info.portname + 1, 8);
EBCASC(portname, 8);
return sprintf(buf, "%s\n", portname);
} else
return sprintf(buf, "no portname required\n");
}
static ssize_t qeth_dev_portname_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
int i;
if (!card)
return -EINVAL;
if ((card->state != CARD_STATE_DOWN) &&
(card->state != CARD_STATE_RECOVER))
return -EPERM;
tmp = strsep((char **) &buf, "\n");
if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
return -EINVAL;
card->info.portname[0] = strlen(tmp);
/* for beauty reasons */
for (i = 1; i < 9; i++)
card->info.portname[i] = ' ';
strcpy(card->info.portname + 1, tmp);
ASCEBC(card->info.portname + 1, 8);
return count;
}
static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
qeth_dev_portname_store);
static ssize_t qeth_dev_prioqing_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
if (!card)
return -EINVAL;
switch (card->qdio.do_prio_queueing) {
case QETH_PRIO_Q_ING_PREC:
return sprintf(buf, "%s\n", "by precedence");
case QETH_PRIO_Q_ING_TOS:
return sprintf(buf, "%s\n", "by type of service");
default:
return sprintf(buf, "always queue %i\n",
card->qdio.default_out_queue);
}
}
static ssize_t qeth_dev_prioqing_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
if (!card)
return -EINVAL;
if ((card->state != CARD_STATE_DOWN) &&
(card->state != CARD_STATE_RECOVER))
return -EPERM;
/* check if 1920 devices are supported ,
* if though we have to permit priority queueing
*/
if (card->qdio.no_out_queues == 1) {
PRINT_WARN("Priority queueing disabled due "
"to hardware limitations!\n");
card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
return -EPERM;
}
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "prio_queueing_prec"))
card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_PREC;
else if (!strcmp(tmp, "prio_queueing_tos"))
card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_TOS;
else if (!strcmp(tmp, "no_prio_queueing:0")) {
card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
card->qdio.default_out_queue = 0;
} else if (!strcmp(tmp, "no_prio_queueing:1")) {
card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
card->qdio.default_out_queue = 1;
} else if (!strcmp(tmp, "no_prio_queueing:2")) {
card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
card->qdio.default_out_queue = 2;
} else if (!strcmp(tmp, "no_prio_queueing:3")) {
card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
card->qdio.default_out_queue = 3;
} else if (!strcmp(tmp, "no_prio_queueing")) {
card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
} else {
PRINT_WARN("Unknown queueing type '%s'\n", tmp);
return -EINVAL;
}
return count;
}
static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
qeth_dev_prioqing_store);
static ssize_t qeth_dev_bufcnt_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
if (!card)
return -EINVAL;
return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count);
}
static ssize_t qeth_dev_bufcnt_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
int cnt, old_cnt;
int rc;
if (!card)
return -EINVAL;
if ((card->state != CARD_STATE_DOWN) &&
(card->state != CARD_STATE_RECOVER))
return -EPERM;
old_cnt = card->qdio.in_buf_pool.buf_count;
cnt = simple_strtoul(buf, &tmp, 10);
cnt = (cnt < QETH_IN_BUF_COUNT_MIN) ? QETH_IN_BUF_COUNT_MIN :
((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt);
if (old_cnt != cnt) {
rc = qeth_realloc_buffer_pool(card, cnt);
if (rc)
PRINT_WARN("Error (%d) while setting "
"buffer count.\n", rc);
}
return count;
}
static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
qeth_dev_bufcnt_store);
static ssize_t qeth_dev_recover_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
int i;
if (!card)
return -EINVAL;
if (card->state != CARD_STATE_UP)
return -EPERM;
i = simple_strtoul(buf, &tmp, 16);
if (i == 1)
qeth_schedule_recovery(card);
return count;
}
static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store);
static ssize_t qeth_dev_performance_stats_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
if (!card)
return -EINVAL;
return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0);
}
static ssize_t qeth_dev_performance_stats_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
int i;
if (!card)
return -EINVAL;
i = simple_strtoul(buf, &tmp, 16);
if ((i == 0) || (i == 1)) {
if (i == card->options.performance_stats)
return count;
card->options.performance_stats = i;
if (i == 0)
memset(&card->perf_stats, 0,
sizeof(struct qeth_perf_stats));
card->perf_stats.initial_rx_packets = card->stats.rx_packets;
card->perf_stats.initial_tx_packets = card->stats.tx_packets;
} else {
PRINT_WARN("performance_stats: write 0 or 1 to this file!\n");
return -EINVAL;
}
return count;
}
static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
qeth_dev_performance_stats_store);
static ssize_t qeth_dev_layer2_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
if (!card)
return -EINVAL;
return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);
}
static ssize_t qeth_dev_layer2_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
int i, rc;
enum qeth_discipline_id newdis;
if (!card)
return -EINVAL;
if (((card->state != CARD_STATE_DOWN) &&
(card->state != CARD_STATE_RECOVER)))
return -EPERM;
i = simple_strtoul(buf, &tmp, 16);
switch (i) {
case 0:
newdis = QETH_DISCIPLINE_LAYER3;
break;
case 1:
newdis = QETH_DISCIPLINE_LAYER2;
break;
default:
PRINT_WARN("layer2: write 0 or 1 to this file!\n");
return -EINVAL;
}
if (card->options.layer2 == newdis) {
return count;
} else {
if (card->discipline.ccwgdriver) {
card->discipline.ccwgdriver->remove(card->gdev);
qeth_core_free_discipline(card);
}
}
rc = qeth_core_load_discipline(card, newdis);
if (rc)
return rc;
rc = card->discipline.ccwgdriver->probe(card->gdev);
if (rc)
return rc;
return count;
}
static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
qeth_dev_layer2_store);
static ssize_t qeth_dev_large_send_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
if (!card)
return -EINVAL;
switch (card->options.large_send) {
case QETH_LARGE_SEND_NO:
return sprintf(buf, "%s\n", "no");
case QETH_LARGE_SEND_EDDP:
return sprintf(buf, "%s\n", "EDDP");
case QETH_LARGE_SEND_TSO:
return sprintf(buf, "%s\n", "TSO");
default:
return sprintf(buf, "%s\n", "N/A");
}
}
static ssize_t qeth_dev_large_send_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
enum qeth_large_send_types type;
int rc = 0;
char *tmp;
if (!card)
return -EINVAL;
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "no")) {
type = QETH_LARGE_SEND_NO;
} else if (!strcmp(tmp, "EDDP")) {
type = QETH_LARGE_SEND_EDDP;
} else if (!strcmp(tmp, "TSO")) {
type = QETH_LARGE_SEND_TSO;
} else {
PRINT_WARN("large_send: invalid mode %s!\n", tmp);
return -EINVAL;
}
if (card->options.large_send == type)
return count;
rc = qeth_set_large_send(card, type);
if (rc)
return rc;
return count;
}
static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show,
qeth_dev_large_send_store);
static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value)
{
if (!card)
return -EINVAL;
return sprintf(buf, "%i\n", value);
}
static ssize_t qeth_dev_blkt_store(struct qeth_card *card,
const char *buf, size_t count, int *value, int max_value)
{
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, 10);
if (i <= max_value) {
*value = i;
} else {
PRINT_WARN("blkt total time: write values between"
" 0 and %d to this file!\n", max_value);
return -EINVAL;
}
return count;
}
static ssize_t qeth_dev_blkt_total_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total);
}
static ssize_t qeth_dev_blkt_total_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_dev_blkt_store(card, buf, count,
&card->info.blkt.time_total, 1000);
}
static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show,
qeth_dev_blkt_total_store);
static ssize_t qeth_dev_blkt_inter_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet);
}
static ssize_t qeth_dev_blkt_inter_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_dev_blkt_store(card, buf, count,
&card->info.blkt.inter_packet, 100);
}
static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show,
qeth_dev_blkt_inter_store);
static ssize_t qeth_dev_blkt_inter_jumbo_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_dev_blkt_show(buf, card,
card->info.blkt.inter_packet_jumbo);
}
static ssize_t qeth_dev_blkt_inter_jumbo_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_dev_blkt_store(card, buf, count,
&card->info.blkt.inter_packet_jumbo, 100);
}
static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show,
qeth_dev_blkt_inter_jumbo_store);
static struct attribute *qeth_blkt_device_attrs[] = {
&dev_attr_total.attr,
&dev_attr_inter.attr,
&dev_attr_inter_jumbo.attr,
NULL,
};
static struct attribute_group qeth_device_blkt_group = {
.name = "blkt",
.attrs = qeth_blkt_device_attrs,
};
static struct attribute *qeth_device_attrs[] = {
&dev_attr_state.attr,
&dev_attr_chpid.attr,
&dev_attr_if_name.attr,
&dev_attr_card_type.attr,
&dev_attr_inbuf_size.attr,
&dev_attr_portno.attr,
&dev_attr_portname.attr,
&dev_attr_priority_queueing.attr,
&dev_attr_buffer_count.attr,
&dev_attr_recover.attr,
&dev_attr_performance_stats.attr,
&dev_attr_layer2.attr,
&dev_attr_large_send.attr,
NULL,
};
static struct attribute_group qeth_device_attr_group = {
.attrs = qeth_device_attrs,
};
static struct attribute *qeth_osn_device_attrs[] = {
&dev_attr_state.attr,
&dev_attr_chpid.attr,
&dev_attr_if_name.attr,
&dev_attr_card_type.attr,
&dev_attr_buffer_count.attr,
&dev_attr_recover.attr,
NULL,
};
static struct attribute_group qeth_osn_device_attr_group = {
.attrs = qeth_osn_device_attrs,
};
int qeth_core_create_device_attributes(struct device *dev)
{
int ret;
ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group);
if (ret)
return ret;
ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group);
if (ret)
sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
return 0;
}
void qeth_core_remove_device_attributes(struct device *dev)
{
sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group);
}
int qeth_core_create_osn_attributes(struct device *dev)
{
return sysfs_create_group(&dev->kobj, &qeth_osn_device_attr_group);
}
void qeth_core_remove_osn_attributes(struct device *dev)
{
sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group);
return;
}
此差异已折叠。
/*
* drivers/s390/net/qeth_l3.h
*
* Copyright IBM Corp. 2007
* Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
* Frank Pavlic <fpavlic@de.ibm.com>,
* Thomas Spatzier <tspat@de.ibm.com>,
* Frank Blaschka <frank.blaschka@de.ibm.com>
*/
#ifndef __QETH_L3_H__
#define __QETH_L3_H__
#include "qeth_core.h"
#define QETH_DBF_TEXT_(name, level, text...) \
do { \
if (qeth_dbf_passes(qeth_dbf_##name, level)) { \
char *dbf_txt_buf = get_cpu_var(qeth_l3_dbf_txt_buf); \
sprintf(dbf_txt_buf, text); \
debug_text_event(qeth_dbf_##name, level, dbf_txt_buf); \
put_cpu_var(qeth_l3_dbf_txt_buf); \
} \
} while (0)
DECLARE_PER_CPU(char[256], qeth_l3_dbf_txt_buf);
struct qeth_ipaddr {
struct list_head entry;
enum qeth_ip_types type;
enum qeth_ipa_setdelip_flags set_flags;
enum qeth_ipa_setdelip_flags del_flags;
int is_multicast;
int users;
enum qeth_prot_versions proto;
unsigned char mac[OSA_ADDR_LEN];
union {
struct {
unsigned int addr;
unsigned int mask;
} a4;
struct {
struct in6_addr addr;
unsigned int pfxlen;
} a6;
} u;
};
struct qeth_ipato_entry {
struct list_head entry;
enum qeth_prot_versions proto;
char addr[16];
int mask_bits;
};
void qeth_l3_ipaddr4_to_string(const __u8 *, char *);
int qeth_l3_string_to_ipaddr4(const char *, __u8 *);
void qeth_l3_ipaddr6_to_string(const __u8 *, char *);
int qeth_l3_string_to_ipaddr6(const char *, __u8 *);
void qeth_l3_ipaddr_to_string(enum qeth_prot_versions, const __u8 *, char *);
int qeth_l3_string_to_ipaddr(const char *, enum qeth_prot_versions, __u8 *);
int qeth_l3_create_device_attributes(struct device *);
void qeth_l3_remove_device_attributes(struct device *);
int qeth_l3_setrouting_v4(struct qeth_card *);
int qeth_l3_setrouting_v6(struct qeth_card *);
int qeth_l3_add_ipato_entry(struct qeth_card *, struct qeth_ipato_entry *);
void qeth_l3_del_ipato_entry(struct qeth_card *, enum qeth_prot_versions,
u8 *, int);
int qeth_l3_add_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
void qeth_l3_del_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions,
const u8 *);
#endif /* __QETH_L3_H__ */
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册