forked from luck/tmp_suning_uos_patched
ctcm: infrastructure for replaced ctc driver
ctcm driver supports the channel-to-channel connections of the old ctc driver plus an additional MPC protocol to provide SNA connectivity. This new ctcm driver replaces the existing ctc driver. Signed-off-by: Peter Tiedemann <ptiedem@de.ibm.com> Signed-off-by: Ursula Braun <braunu@de.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
f423f73506
commit
293d984f0e
|
@ -11,15 +11,17 @@ config LCS
|
||||||
To compile as a module, choose M. The module name is lcs.ko.
|
To compile as a module, choose M. The module name is lcs.ko.
|
||||||
If you do not know what it is, it's safe to choose Y.
|
If you do not know what it is, it's safe to choose Y.
|
||||||
|
|
||||||
config CTC
|
config CTCM
|
||||||
tristate "CTC device support"
|
tristate "CTC and MPC SNA device support"
|
||||||
depends on CCW && NETDEVICES
|
depends on CCW && NETDEVICES
|
||||||
help
|
help
|
||||||
Select this option if you want to use channel-to-channel
|
Select this option if you want to use channel-to-channel
|
||||||
point-to-point networking on IBM System z.
|
point-to-point networking on IBM System z.
|
||||||
This device driver supports real CTC coupling using ESCON.
|
This device driver supports real CTC coupling using ESCON.
|
||||||
It also supports virtual CTCs when running under VM.
|
It also supports virtual CTCs when running under VM.
|
||||||
To compile as a module, choose M. The module name is ctc.ko.
|
This driver also supports channel-to-channel MPC SNA devices.
|
||||||
|
MPC is an SNA protocol device used by Communication Server for Linux.
|
||||||
|
To compile as a module, choose M. The module name is ctcm.ko.
|
||||||
To compile into the kernel, choose Y.
|
To compile into the kernel, choose Y.
|
||||||
If you do not need any channel-to-channel connection, choose N.
|
If you do not need any channel-to-channel connection, choose N.
|
||||||
|
|
||||||
|
@ -84,7 +86,7 @@ config QETH_VLAN
|
||||||
802.1q VLAN support in the qeth device driver.
|
802.1q VLAN support in the qeth device driver.
|
||||||
|
|
||||||
config CCWGROUP
|
config CCWGROUP
|
||||||
tristate
|
tristate
|
||||||
default (LCS || CTC || QETH)
|
default (LCS || CTCM || QETH)
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
# S/390 network devices
|
# S/390 network devices
|
||||||
#
|
#
|
||||||
|
|
||||||
ctc-objs := ctcmain.o ctcdbug.o
|
ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o
|
||||||
|
obj-$(CONFIG_CTCM) += ctcm.o fsm.o cu3088.o
|
||||||
obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
|
obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
|
||||||
obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
|
obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
|
||||||
obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
|
|
||||||
obj-$(CONFIG_LCS) += lcs.o cu3088.o
|
obj-$(CONFIG_LCS) += lcs.o cu3088.o
|
||||||
obj-$(CONFIG_CLAW) += claw.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-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o
|
||||||
|
|
67
drivers/s390/net/ctcm_dbug.c
Normal file
67
drivers/s390/net/ctcm_dbug.c
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* drivers/s390/net/ctcm_dbug.c
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2001, 2007
|
||||||
|
* Authors: Peter Tiedemann (ptiedem@de.ibm.com)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/stddef.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/ctype.h>
|
||||||
|
#include <linux/sysctl.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/debugfs.h>
|
||||||
|
#include "ctcm_dbug.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Debug Facility Stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
DEFINE_PER_CPU(char[256], ctcm_dbf_txt_buf);
|
||||||
|
|
||||||
|
struct ctcm_dbf_info ctcm_dbf[CTCM_DBF_INFOS] = {
|
||||||
|
[CTCM_DBF_SETUP] = {"ctc_setup", 8, 1, 64, 5, NULL},
|
||||||
|
[CTCM_DBF_ERROR] = {"ctc_error", 8, 1, 64, 3, NULL},
|
||||||
|
[CTCM_DBF_TRACE] = {"ctc_trace", 8, 1, 64, 3, NULL},
|
||||||
|
[CTCM_DBF_MPC_SETUP] = {"mpc_setup", 8, 1, 64, 5, NULL},
|
||||||
|
[CTCM_DBF_MPC_ERROR] = {"mpc_error", 8, 1, 64, 3, NULL},
|
||||||
|
[CTCM_DBF_MPC_TRACE] = {"mpc_trace", 8, 1, 64, 3, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
void ctcm_unregister_dbf_views(void)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < CTCM_DBF_INFOS; x++) {
|
||||||
|
debug_unregister(ctcm_dbf[x].id);
|
||||||
|
ctcm_dbf[x].id = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ctcm_register_dbf_views(void)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < CTCM_DBF_INFOS; x++) {
|
||||||
|
/* register the areas */
|
||||||
|
ctcm_dbf[x].id = debug_register(ctcm_dbf[x].name,
|
||||||
|
ctcm_dbf[x].pages,
|
||||||
|
ctcm_dbf[x].areas,
|
||||||
|
ctcm_dbf[x].len);
|
||||||
|
if (ctcm_dbf[x].id == NULL) {
|
||||||
|
ctcm_unregister_dbf_views();
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* register a view */
|
||||||
|
debug_register_view(ctcm_dbf[x].id, &debug_hex_ascii_view);
|
||||||
|
/* set a passing level */
|
||||||
|
debug_set_level(ctcm_dbf[x].id, ctcm_dbf[x].level);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
158
drivers/s390/net/ctcm_dbug.h
Normal file
158
drivers/s390/net/ctcm_dbug.h
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* drivers/s390/net/ctcm_dbug.h
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2001, 2007
|
||||||
|
* Authors: Peter Tiedemann (ptiedem@de.ibm.com)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CTCM_DBUG_H_
|
||||||
|
#define _CTCM_DBUG_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Debug Facility stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm/debug.h>
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define do_debug 1
|
||||||
|
#else
|
||||||
|
#define do_debug 0
|
||||||
|
#endif
|
||||||
|
#ifdef DEBUGDATA
|
||||||
|
#define do_debug_data 1
|
||||||
|
#else
|
||||||
|
#define do_debug_data 0
|
||||||
|
#endif
|
||||||
|
#ifdef DEBUGCCW
|
||||||
|
#define do_debug_ccw 1
|
||||||
|
#else
|
||||||
|
#define do_debug_ccw 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* define dbf debug levels similar to kernel msg levels */
|
||||||
|
#define CTC_DBF_ALWAYS 0 /* always print this */
|
||||||
|
#define CTC_DBF_EMERG 0 /* system is unusable */
|
||||||
|
#define CTC_DBF_ALERT 1 /* action must be taken immediately */
|
||||||
|
#define CTC_DBF_CRIT 2 /* critical conditions */
|
||||||
|
#define CTC_DBF_ERROR 3 /* error conditions */
|
||||||
|
#define CTC_DBF_WARN 4 /* warning conditions */
|
||||||
|
#define CTC_DBF_NOTICE 5 /* normal but significant condition */
|
||||||
|
#define CTC_DBF_INFO 5 /* informational */
|
||||||
|
#define CTC_DBF_DEBUG 6 /* debug-level messages */
|
||||||
|
|
||||||
|
DECLARE_PER_CPU(char[256], ctcm_dbf_txt_buf);
|
||||||
|
|
||||||
|
enum ctcm_dbf_names {
|
||||||
|
CTCM_DBF_SETUP,
|
||||||
|
CTCM_DBF_ERROR,
|
||||||
|
CTCM_DBF_TRACE,
|
||||||
|
CTCM_DBF_MPC_SETUP,
|
||||||
|
CTCM_DBF_MPC_ERROR,
|
||||||
|
CTCM_DBF_MPC_TRACE,
|
||||||
|
CTCM_DBF_INFOS /* must be last element */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ctcm_dbf_info {
|
||||||
|
char name[DEBUG_MAX_NAME_LEN];
|
||||||
|
int pages;
|
||||||
|
int areas;
|
||||||
|
int len;
|
||||||
|
int level;
|
||||||
|
debug_info_t *id;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct ctcm_dbf_info ctcm_dbf[CTCM_DBF_INFOS];
|
||||||
|
|
||||||
|
int ctcm_register_dbf_views(void);
|
||||||
|
void ctcm_unregister_dbf_views(void);
|
||||||
|
|
||||||
|
static inline const char *strtail(const char *s, int n)
|
||||||
|
{
|
||||||
|
int l = strlen(s);
|
||||||
|
return (l > n) ? s + (l - n) : s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sort out levels early to avoid unnecessary sprintfs */
|
||||||
|
static inline int ctcm_dbf_passes(debug_info_t *dbf_grp, int level)
|
||||||
|
{
|
||||||
|
return (dbf_grp->level >= level);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CTCM_FUNTAIL strtail((char *)__func__, 16)
|
||||||
|
|
||||||
|
#define CTCM_DBF_TEXT(name, level, text) \
|
||||||
|
do { \
|
||||||
|
debug_text_event(ctcm_dbf[CTCM_DBF_##name].id, level, text); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CTCM_DBF_HEX(name, level, addr, len) \
|
||||||
|
do { \
|
||||||
|
debug_event(ctcm_dbf[CTCM_DBF_##name].id, \
|
||||||
|
level, (void *)(addr), len); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CTCM_DBF_TEXT_(name, level, text...) \
|
||||||
|
do { \
|
||||||
|
if (ctcm_dbf_passes(ctcm_dbf[CTCM_DBF_##name].id, level)) { \
|
||||||
|
char *ctcm_dbf_txt_buf = \
|
||||||
|
get_cpu_var(ctcm_dbf_txt_buf); \
|
||||||
|
sprintf(ctcm_dbf_txt_buf, text); \
|
||||||
|
debug_text_event(ctcm_dbf[CTCM_DBF_##name].id, \
|
||||||
|
level, ctcm_dbf_txt_buf); \
|
||||||
|
put_cpu_var(ctcm_dbf_txt_buf); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cat : one of {setup, mpc_setup, trace, mpc_trace, error, mpc_error}.
|
||||||
|
* dev : netdevice with valid name field.
|
||||||
|
* text: any text string.
|
||||||
|
*/
|
||||||
|
#define CTCM_DBF_DEV_NAME(cat, dev, text) \
|
||||||
|
do { \
|
||||||
|
CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%s) : %s", \
|
||||||
|
CTCM_FUNTAIL, dev->name, text); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define MPC_DBF_DEV_NAME(cat, dev, text) \
|
||||||
|
do { \
|
||||||
|
CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%s) : %s", \
|
||||||
|
CTCM_FUNTAIL, dev->name, text); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CTCMY_DBF_DEV_NAME(cat, dev, text) \
|
||||||
|
do { \
|
||||||
|
if (IS_MPCDEV(dev)) \
|
||||||
|
MPC_DBF_DEV_NAME(cat, dev, text); \
|
||||||
|
else \
|
||||||
|
CTCM_DBF_DEV_NAME(cat, dev, text); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cat : one of {setup, mpc_setup, trace, mpc_trace, error, mpc_error}.
|
||||||
|
* dev : netdevice.
|
||||||
|
* text: any text string.
|
||||||
|
*/
|
||||||
|
#define CTCM_DBF_DEV(cat, dev, text) \
|
||||||
|
do { \
|
||||||
|
CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%p) : %s", \
|
||||||
|
CTCM_FUNTAIL, dev, text); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define MPC_DBF_DEV(cat, dev, text) \
|
||||||
|
do { \
|
||||||
|
CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%p) : %s", \
|
||||||
|
CTCM_FUNTAIL, dev, text); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CTCMY_DBF_DEV(cat, dev, text) \
|
||||||
|
do { \
|
||||||
|
if (IS_MPCDEV(dev)) \
|
||||||
|
MPC_DBF_DEV(cat, dev, text); \
|
||||||
|
else \
|
||||||
|
CTCM_DBF_DEV(cat, dev, text); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif
|
2347
drivers/s390/net/ctcm_fsms.c
Normal file
2347
drivers/s390/net/ctcm_fsms.c
Normal file
File diff suppressed because it is too large
Load Diff
359
drivers/s390/net/ctcm_fsms.h
Normal file
359
drivers/s390/net/ctcm_fsms.h
Normal file
|
@ -0,0 +1,359 @@
|
||||||
|
/*
|
||||||
|
* drivers/s390/net/ctcm_fsms.h
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2001, 2007
|
||||||
|
* Authors: Fritz Elfert (felfert@millenux.com)
|
||||||
|
* Peter Tiedemann (ptiedem@de.ibm.com)
|
||||||
|
* MPC additions :
|
||||||
|
* Belinda Thompson (belindat@us.ibm.com)
|
||||||
|
* Andy Richter (richtera@us.ibm.com)
|
||||||
|
*/
|
||||||
|
#ifndef _CTCM_FSMS_H_
|
||||||
|
#define _CTCM_FSMS_H_
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
|
||||||
|
#include <linux/signal.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/if_arp.h>
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/ctype.h>
|
||||||
|
#include <net/dst.h>
|
||||||
|
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <asm/ccwdev.h>
|
||||||
|
#include <asm/ccwgroup.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <asm/idals.h>
|
||||||
|
|
||||||
|
#include "fsm.h"
|
||||||
|
#include "cu3088.h"
|
||||||
|
#include "ctcm_main.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions for the channel statemachine(s) for ctc and ctcmpc
|
||||||
|
*
|
||||||
|
* To allow better kerntyping, prefix-less definitions for channel states
|
||||||
|
* and channel events have been replaced :
|
||||||
|
* ch_event... -> ctc_ch_event...
|
||||||
|
* CH_EVENT... -> CTC_EVENT...
|
||||||
|
* ch_state... -> ctc_ch_state...
|
||||||
|
* CH_STATE... -> CTC_STATE...
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Events of the channel statemachine(s) for ctc and ctcmpc
|
||||||
|
*/
|
||||||
|
enum ctc_ch_events {
|
||||||
|
/*
|
||||||
|
* Events, representing return code of
|
||||||
|
* I/O operations (ccw_device_start, ccw_device_halt et al.)
|
||||||
|
*/
|
||||||
|
CTC_EVENT_IO_SUCCESS,
|
||||||
|
CTC_EVENT_IO_EBUSY,
|
||||||
|
CTC_EVENT_IO_ENODEV,
|
||||||
|
CTC_EVENT_IO_UNKNOWN,
|
||||||
|
|
||||||
|
CTC_EVENT_ATTNBUSY,
|
||||||
|
CTC_EVENT_ATTN,
|
||||||
|
CTC_EVENT_BUSY,
|
||||||
|
/*
|
||||||
|
* Events, representing unit-check
|
||||||
|
*/
|
||||||
|
CTC_EVENT_UC_RCRESET,
|
||||||
|
CTC_EVENT_UC_RSRESET,
|
||||||
|
CTC_EVENT_UC_TXTIMEOUT,
|
||||||
|
CTC_EVENT_UC_TXPARITY,
|
||||||
|
CTC_EVENT_UC_HWFAIL,
|
||||||
|
CTC_EVENT_UC_RXPARITY,
|
||||||
|
CTC_EVENT_UC_ZERO,
|
||||||
|
CTC_EVENT_UC_UNKNOWN,
|
||||||
|
/*
|
||||||
|
* Events, representing subchannel-check
|
||||||
|
*/
|
||||||
|
CTC_EVENT_SC_UNKNOWN,
|
||||||
|
/*
|
||||||
|
* Events, representing machine checks
|
||||||
|
*/
|
||||||
|
CTC_EVENT_MC_FAIL,
|
||||||
|
CTC_EVENT_MC_GOOD,
|
||||||
|
/*
|
||||||
|
* Event, representing normal IRQ
|
||||||
|
*/
|
||||||
|
CTC_EVENT_IRQ,
|
||||||
|
CTC_EVENT_FINSTAT,
|
||||||
|
/*
|
||||||
|
* Event, representing timer expiry.
|
||||||
|
*/
|
||||||
|
CTC_EVENT_TIMER,
|
||||||
|
/*
|
||||||
|
* Events, representing commands from upper levels.
|
||||||
|
*/
|
||||||
|
CTC_EVENT_START,
|
||||||
|
CTC_EVENT_STOP,
|
||||||
|
CTC_NR_EVENTS,
|
||||||
|
/*
|
||||||
|
* additional MPC events
|
||||||
|
*/
|
||||||
|
CTC_EVENT_SEND_XID = CTC_NR_EVENTS,
|
||||||
|
CTC_EVENT_RSWEEP_TIMER,
|
||||||
|
/*
|
||||||
|
* MUST be always the last element!!
|
||||||
|
*/
|
||||||
|
CTC_MPC_NR_EVENTS,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* States of the channel statemachine(s) for ctc and ctcmpc.
|
||||||
|
*/
|
||||||
|
enum ctc_ch_states {
|
||||||
|
/*
|
||||||
|
* Channel not assigned to any device,
|
||||||
|
* initial state, direction invalid
|
||||||
|
*/
|
||||||
|
CTC_STATE_IDLE,
|
||||||
|
/*
|
||||||
|
* Channel assigned but not operating
|
||||||
|
*/
|
||||||
|
CTC_STATE_STOPPED,
|
||||||
|
CTC_STATE_STARTWAIT,
|
||||||
|
CTC_STATE_STARTRETRY,
|
||||||
|
CTC_STATE_SETUPWAIT,
|
||||||
|
CTC_STATE_RXINIT,
|
||||||
|
CTC_STATE_TXINIT,
|
||||||
|
CTC_STATE_RX,
|
||||||
|
CTC_STATE_TX,
|
||||||
|
CTC_STATE_RXIDLE,
|
||||||
|
CTC_STATE_TXIDLE,
|
||||||
|
CTC_STATE_RXERR,
|
||||||
|
CTC_STATE_TXERR,
|
||||||
|
CTC_STATE_TERM,
|
||||||
|
CTC_STATE_DTERM,
|
||||||
|
CTC_STATE_NOTOP,
|
||||||
|
CTC_NR_STATES, /* MUST be the last element of non-expanded states */
|
||||||
|
/*
|
||||||
|
* additional MPC states
|
||||||
|
*/
|
||||||
|
CH_XID0_PENDING = CTC_NR_STATES,
|
||||||
|
CH_XID0_INPROGRESS,
|
||||||
|
CH_XID7_PENDING,
|
||||||
|
CH_XID7_PENDING1,
|
||||||
|
CH_XID7_PENDING2,
|
||||||
|
CH_XID7_PENDING3,
|
||||||
|
CH_XID7_PENDING4,
|
||||||
|
CTC_MPC_NR_STATES, /* MUST be the last element of expanded mpc states */
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const char *ctc_ch_event_names[];
|
||||||
|
|
||||||
|
extern const char *ctc_ch_state_names[];
|
||||||
|
|
||||||
|
void ctcm_ccw_check_rc(struct channel *ch, int rc, char *msg);
|
||||||
|
void ctcm_purge_skb_queue(struct sk_buff_head *q);
|
||||||
|
void fsm_action_nop(fsm_instance *fi, int event, void *arg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----- non-static actions for ctcm channel statemachine -----
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void ctcm_chx_txidle(fsm_instance *fi, int event, void *arg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----- FSM (state/event/action) of the ctcm channel statemachine -----
|
||||||
|
*/
|
||||||
|
extern const fsm_node ch_fsm[];
|
||||||
|
extern int ch_fsm_len;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----- non-static actions for ctcmpc channel statemachine ----
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/* shared :
|
||||||
|
void ctcm_chx_txidle(fsm_instance * fi, int event, void *arg);
|
||||||
|
*/
|
||||||
|
void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----- FSM (state/event/action) of the ctcmpc channel statemachine -----
|
||||||
|
*/
|
||||||
|
extern const fsm_node ctcmpc_ch_fsm[];
|
||||||
|
extern int mpc_ch_fsm_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions for the device interface statemachine for ctc and mpc
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* States of the device interface statemachine.
|
||||||
|
*/
|
||||||
|
enum dev_states {
|
||||||
|
DEV_STATE_STOPPED,
|
||||||
|
DEV_STATE_STARTWAIT_RXTX,
|
||||||
|
DEV_STATE_STARTWAIT_RX,
|
||||||
|
DEV_STATE_STARTWAIT_TX,
|
||||||
|
DEV_STATE_STOPWAIT_RXTX,
|
||||||
|
DEV_STATE_STOPWAIT_RX,
|
||||||
|
DEV_STATE_STOPWAIT_TX,
|
||||||
|
DEV_STATE_RUNNING,
|
||||||
|
/*
|
||||||
|
* MUST be always the last element!!
|
||||||
|
*/
|
||||||
|
CTCM_NR_DEV_STATES
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const char *dev_state_names[];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Events of the device interface statemachine.
|
||||||
|
* ctcm and ctcmpc
|
||||||
|
*/
|
||||||
|
enum dev_events {
|
||||||
|
DEV_EVENT_START,
|
||||||
|
DEV_EVENT_STOP,
|
||||||
|
DEV_EVENT_RXUP,
|
||||||
|
DEV_EVENT_TXUP,
|
||||||
|
DEV_EVENT_RXDOWN,
|
||||||
|
DEV_EVENT_TXDOWN,
|
||||||
|
DEV_EVENT_RESTART,
|
||||||
|
/*
|
||||||
|
* MUST be always the last element!!
|
||||||
|
*/
|
||||||
|
CTCM_NR_DEV_EVENTS
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const char *dev_event_names[];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Actions for the device interface statemachine.
|
||||||
|
* ctc and ctcmpc
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
static void dev_action_start(fsm_instance * fi, int event, void *arg);
|
||||||
|
static void dev_action_stop(fsm_instance * fi, int event, void *arg);
|
||||||
|
static void dev_action_restart(fsm_instance *fi, int event, void *arg);
|
||||||
|
static void dev_action_chup(fsm_instance * fi, int event, void *arg);
|
||||||
|
static void dev_action_chdown(fsm_instance * fi, int event, void *arg);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The (state/event/action) fsm table of the device interface statemachine.
|
||||||
|
* ctcm and ctcmpc
|
||||||
|
*/
|
||||||
|
extern const fsm_node dev_fsm[];
|
||||||
|
extern int dev_fsm_len;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions for the MPC Group statemachine
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MPC Group Station FSM States
|
||||||
|
|
||||||
|
State Name When In This State
|
||||||
|
====================== =======================================
|
||||||
|
MPCG_STATE_RESET Initial State When Driver Loaded
|
||||||
|
We receive and send NOTHING
|
||||||
|
|
||||||
|
MPCG_STATE_INOP INOP Received.
|
||||||
|
Group level non-recoverable error
|
||||||
|
|
||||||
|
MPCG_STATE_READY XID exchanges for at least 1 write and
|
||||||
|
1 read channel have completed.
|
||||||
|
Group is ready for data transfer.
|
||||||
|
|
||||||
|
States from ctc_mpc_alloc_channel
|
||||||
|
==============================================================
|
||||||
|
MPCG_STATE_XID2INITW Awaiting XID2(0) Initiation
|
||||||
|
ATTN from other side will start
|
||||||
|
XID negotiations.
|
||||||
|
Y-side protocol only.
|
||||||
|
|
||||||
|
MPCG_STATE_XID2INITX XID2(0) negotiations are in progress.
|
||||||
|
At least 1, but not all, XID2(0)'s
|
||||||
|
have been received from partner.
|
||||||
|
|
||||||
|
MPCG_STATE_XID7INITW XID2(0) complete
|
||||||
|
No XID2(7)'s have yet been received.
|
||||||
|
XID2(7) negotiations pending.
|
||||||
|
|
||||||
|
MPCG_STATE_XID7INITX XID2(7) negotiations in progress.
|
||||||
|
At least 1, but not all, XID2(7)'s
|
||||||
|
have been received from partner.
|
||||||
|
|
||||||
|
MPCG_STATE_XID7INITF XID2(7) negotiations complete.
|
||||||
|
Transitioning to READY.
|
||||||
|
|
||||||
|
MPCG_STATE_READY Ready for Data Transfer.
|
||||||
|
|
||||||
|
|
||||||
|
States from ctc_mpc_establish_connectivity call
|
||||||
|
==============================================================
|
||||||
|
MPCG_STATE_XID0IOWAIT Initiating XID2(0) negotiations.
|
||||||
|
X-side protocol only.
|
||||||
|
ATTN-BUSY from other side will convert
|
||||||
|
this to Y-side protocol and the
|
||||||
|
ctc_mpc_alloc_channel flow will begin.
|
||||||
|
|
||||||
|
MPCG_STATE_XID0IOWAIX XID2(0) negotiations are in progress.
|
||||||
|
At least 1, but not all, XID2(0)'s
|
||||||
|
have been received from partner.
|
||||||
|
|
||||||
|
MPCG_STATE_XID7INITI XID2(0) complete
|
||||||
|
No XID2(7)'s have yet been received.
|
||||||
|
XID2(7) negotiations pending.
|
||||||
|
|
||||||
|
MPCG_STATE_XID7INITZ XID2(7) negotiations in progress.
|
||||||
|
At least 1, but not all, XID2(7)'s
|
||||||
|
have been received from partner.
|
||||||
|
|
||||||
|
MPCG_STATE_XID7INITF XID2(7) negotiations complete.
|
||||||
|
Transitioning to READY.
|
||||||
|
|
||||||
|
MPCG_STATE_READY Ready for Data Transfer.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum mpcg_events {
|
||||||
|
MPCG_EVENT_INOP,
|
||||||
|
MPCG_EVENT_DISCONC,
|
||||||
|
MPCG_EVENT_XID0DO,
|
||||||
|
MPCG_EVENT_XID2,
|
||||||
|
MPCG_EVENT_XID2DONE,
|
||||||
|
MPCG_EVENT_XID7DONE,
|
||||||
|
MPCG_EVENT_TIMER,
|
||||||
|
MPCG_EVENT_DOIO,
|
||||||
|
MPCG_NR_EVENTS,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum mpcg_states {
|
||||||
|
MPCG_STATE_RESET,
|
||||||
|
MPCG_STATE_INOP,
|
||||||
|
MPCG_STATE_XID2INITW,
|
||||||
|
MPCG_STATE_XID2INITX,
|
||||||
|
MPCG_STATE_XID7INITW,
|
||||||
|
MPCG_STATE_XID7INITX,
|
||||||
|
MPCG_STATE_XID0IOWAIT,
|
||||||
|
MPCG_STATE_XID0IOWAIX,
|
||||||
|
MPCG_STATE_XID7INITI,
|
||||||
|
MPCG_STATE_XID7INITZ,
|
||||||
|
MPCG_STATE_XID7INITF,
|
||||||
|
MPCG_STATE_FLOWC,
|
||||||
|
MPCG_STATE_READY,
|
||||||
|
MPCG_NR_STATES,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/* --- This is the END my friend --- */
|
1772
drivers/s390/net/ctcm_main.c
Normal file
1772
drivers/s390/net/ctcm_main.c
Normal file
File diff suppressed because it is too large
Load Diff
287
drivers/s390/net/ctcm_main.h
Normal file
287
drivers/s390/net/ctcm_main.h
Normal file
|
@ -0,0 +1,287 @@
|
||||||
|
/*
|
||||||
|
* drivers/s390/net/ctcm_main.h
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2001, 2007
|
||||||
|
* Authors: Fritz Elfert (felfert@millenux.com)
|
||||||
|
* Peter Tiedemann (ptiedem@de.ibm.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CTCM_MAIN_H_
|
||||||
|
#define _CTCM_MAIN_H_
|
||||||
|
|
||||||
|
#include <asm/ccwdev.h>
|
||||||
|
#include <asm/ccwgroup.h>
|
||||||
|
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
|
||||||
|
#include "fsm.h"
|
||||||
|
#include "cu3088.h"
|
||||||
|
#include "ctcm_dbug.h"
|
||||||
|
#include "ctcm_mpc.h"
|
||||||
|
|
||||||
|
#define CTC_DRIVER_NAME "ctcm"
|
||||||
|
#define CTC_DEVICE_NAME "ctc"
|
||||||
|
#define CTC_DEVICE_GENE "ctc%d"
|
||||||
|
#define MPC_DEVICE_NAME "mpc"
|
||||||
|
#define MPC_DEVICE_GENE "mpc%d"
|
||||||
|
|
||||||
|
#define CHANNEL_FLAGS_READ 0
|
||||||
|
#define CHANNEL_FLAGS_WRITE 1
|
||||||
|
#define CHANNEL_FLAGS_INUSE 2
|
||||||
|
#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4
|
||||||
|
#define CHANNEL_FLAGS_FAILED 8
|
||||||
|
#define CHANNEL_FLAGS_WAITIRQ 16
|
||||||
|
#define CHANNEL_FLAGS_RWMASK 1
|
||||||
|
#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
|
||||||
|
|
||||||
|
#define LOG_FLAG_ILLEGALPKT 1
|
||||||
|
#define LOG_FLAG_ILLEGALSIZE 2
|
||||||
|
#define LOG_FLAG_OVERRUN 4
|
||||||
|
#define LOG_FLAG_NOMEM 8
|
||||||
|
|
||||||
|
#define ctcm_pr_debug(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
|
||||||
|
#define ctcm_pr_info(fmt, arg...) printk(KERN_INFO fmt, ##arg)
|
||||||
|
#define ctcm_pr_notice(fmt, arg...) printk(KERN_NOTICE fmt, ##arg)
|
||||||
|
#define ctcm_pr_warn(fmt, arg...) printk(KERN_WARNING fmt, ##arg)
|
||||||
|
#define ctcm_pr_emerg(fmt, arg...) printk(KERN_EMERG fmt, ##arg)
|
||||||
|
#define ctcm_pr_err(fmt, arg...) printk(KERN_ERR fmt, ##arg)
|
||||||
|
#define ctcm_pr_crit(fmt, arg...) printk(KERN_CRIT fmt, ##arg)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CCW commands, used in this driver.
|
||||||
|
*/
|
||||||
|
#define CCW_CMD_WRITE 0x01
|
||||||
|
#define CCW_CMD_READ 0x02
|
||||||
|
#define CCW_CMD_NOOP 0x03
|
||||||
|
#define CCW_CMD_TIC 0x08
|
||||||
|
#define CCW_CMD_SENSE_CMD 0x14
|
||||||
|
#define CCW_CMD_WRITE_CTL 0x17
|
||||||
|
#define CCW_CMD_SET_EXTENDED 0xc3
|
||||||
|
#define CCW_CMD_PREPARE 0xe3
|
||||||
|
|
||||||
|
#define CTCM_PROTO_S390 0
|
||||||
|
#define CTCM_PROTO_LINUX 1
|
||||||
|
#define CTCM_PROTO_LINUX_TTY 2
|
||||||
|
#define CTCM_PROTO_OS390 3
|
||||||
|
#define CTCM_PROTO_MPC 4
|
||||||
|
#define CTCM_PROTO_MAX 4
|
||||||
|
|
||||||
|
#define CTCM_BUFSIZE_LIMIT 65535
|
||||||
|
#define CTCM_BUFSIZE_DEFAULT 32768
|
||||||
|
#define MPC_BUFSIZE_DEFAULT CTCM_BUFSIZE_LIMIT
|
||||||
|
|
||||||
|
#define CTCM_TIME_1_SEC 1000
|
||||||
|
#define CTCM_TIME_5_SEC 5000
|
||||||
|
#define CTCM_TIME_10_SEC 10000
|
||||||
|
|
||||||
|
#define CTCM_INITIAL_BLOCKLEN 2
|
||||||
|
|
||||||
|
#define READ 0
|
||||||
|
#define WRITE 1
|
||||||
|
|
||||||
|
#define CTCM_ID_SIZE BUS_ID_SIZE+3
|
||||||
|
|
||||||
|
struct ctcm_profile {
|
||||||
|
unsigned long maxmulti;
|
||||||
|
unsigned long maxcqueue;
|
||||||
|
unsigned long doios_single;
|
||||||
|
unsigned long doios_multi;
|
||||||
|
unsigned long txlen;
|
||||||
|
unsigned long tx_time;
|
||||||
|
struct timespec send_stamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definition of one channel
|
||||||
|
*/
|
||||||
|
struct channel {
|
||||||
|
struct channel *next;
|
||||||
|
char id[CTCM_ID_SIZE];
|
||||||
|
struct ccw_device *cdev;
|
||||||
|
/*
|
||||||
|
* Type of this channel.
|
||||||
|
* CTC/A or Escon for valid channels.
|
||||||
|
*/
|
||||||
|
enum channel_types type;
|
||||||
|
/*
|
||||||
|
* Misc. flags. See CHANNEL_FLAGS_... below
|
||||||
|
*/
|
||||||
|
__u32 flags;
|
||||||
|
__u16 protocol; /* protocol of this channel (4 = MPC) */
|
||||||
|
/*
|
||||||
|
* I/O and irq related stuff
|
||||||
|
*/
|
||||||
|
struct ccw1 *ccw;
|
||||||
|
struct irb *irb;
|
||||||
|
/*
|
||||||
|
* RX/TX buffer size
|
||||||
|
*/
|
||||||
|
int max_bufsize;
|
||||||
|
struct sk_buff *trans_skb; /* transmit/receive buffer */
|
||||||
|
struct sk_buff_head io_queue; /* universal I/O queue */
|
||||||
|
struct tasklet_struct ch_tasklet; /* MPC ONLY */
|
||||||
|
/*
|
||||||
|
* TX queue for collecting skb's during busy.
|
||||||
|
*/
|
||||||
|
struct sk_buff_head collect_queue;
|
||||||
|
/*
|
||||||
|
* Amount of data in collect_queue.
|
||||||
|
*/
|
||||||
|
int collect_len;
|
||||||
|
/*
|
||||||
|
* spinlock for collect_queue and collect_len
|
||||||
|
*/
|
||||||
|
spinlock_t collect_lock;
|
||||||
|
/*
|
||||||
|
* Timer for detecting unresposive
|
||||||
|
* I/O operations.
|
||||||
|
*/
|
||||||
|
fsm_timer timer;
|
||||||
|
/* MPC ONLY section begin */
|
||||||
|
__u32 th_seq_num; /* SNA TH seq number */
|
||||||
|
__u8 th_seg;
|
||||||
|
__u32 pdu_seq;
|
||||||
|
struct sk_buff *xid_skb;
|
||||||
|
char *xid_skb_data;
|
||||||
|
struct th_header *xid_th;
|
||||||
|
struct xid2 *xid;
|
||||||
|
char *xid_id;
|
||||||
|
struct th_header *rcvd_xid_th;
|
||||||
|
struct xid2 *rcvd_xid;
|
||||||
|
char *rcvd_xid_id;
|
||||||
|
__u8 in_mpcgroup;
|
||||||
|
fsm_timer sweep_timer;
|
||||||
|
struct sk_buff_head sweep_queue;
|
||||||
|
struct th_header *discontact_th;
|
||||||
|
struct tasklet_struct ch_disc_tasklet;
|
||||||
|
/* MPC ONLY section end */
|
||||||
|
|
||||||
|
int retry; /* retry counter for misc. operations */
|
||||||
|
fsm_instance *fsm; /* finite state machine of this channel */
|
||||||
|
struct net_device *netdev; /* corresponding net_device */
|
||||||
|
struct ctcm_profile prof;
|
||||||
|
unsigned char *trans_skb_data;
|
||||||
|
__u16 logflags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ctcm_priv {
|
||||||
|
struct net_device_stats stats;
|
||||||
|
unsigned long tbusy;
|
||||||
|
|
||||||
|
/* The MPC group struct of this interface */
|
||||||
|
struct mpc_group *mpcg; /* MPC only */
|
||||||
|
struct xid2 *xid; /* MPC only */
|
||||||
|
|
||||||
|
/* The finite state machine of this interface */
|
||||||
|
fsm_instance *fsm;
|
||||||
|
|
||||||
|
/* The protocol of this device */
|
||||||
|
__u16 protocol;
|
||||||
|
|
||||||
|
/* Timer for restarting after I/O Errors */
|
||||||
|
fsm_timer restart_timer;
|
||||||
|
|
||||||
|
int buffer_size; /* ctc only */
|
||||||
|
|
||||||
|
struct channel *channel[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
int ctcm_open(struct net_device *dev);
|
||||||
|
int ctcm_close(struct net_device *dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* prototypes for non-static sysfs functions
|
||||||
|
*/
|
||||||
|
int ctcm_add_attributes(struct device *dev);
|
||||||
|
void ctcm_remove_attributes(struct device *dev);
|
||||||
|
int ctcm_add_files(struct device *dev);
|
||||||
|
void ctcm_remove_files(struct device *dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compatibility macros for busy handling
|
||||||
|
* of network devices.
|
||||||
|
*/
|
||||||
|
static inline void ctcm_clear_busy_do(struct net_device *dev)
|
||||||
|
{
|
||||||
|
clear_bit(0, &(((struct ctcm_priv *)dev->priv)->tbusy));
|
||||||
|
netif_wake_queue(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctcm_clear_busy(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct mpc_group *grp;
|
||||||
|
grp = ((struct ctcm_priv *)dev->priv)->mpcg;
|
||||||
|
|
||||||
|
if (!(grp && grp->in_sweep))
|
||||||
|
ctcm_clear_busy_do(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline int ctcm_test_and_set_busy(struct net_device *dev)
|
||||||
|
{
|
||||||
|
netif_stop_queue(dev);
|
||||||
|
return test_and_set_bit(0, &(((struct ctcm_priv *)dev->priv)->tbusy));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int loglevel;
|
||||||
|
extern struct channel *channels;
|
||||||
|
|
||||||
|
void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions related to setup and device detection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline int ctcm_less_than(char *id1, char *id2)
|
||||||
|
{
|
||||||
|
unsigned long dev1, dev2;
|
||||||
|
|
||||||
|
id1 = id1 + 5;
|
||||||
|
id2 = id2 + 5;
|
||||||
|
|
||||||
|
dev1 = simple_strtoul(id1, &id1, 16);
|
||||||
|
dev2 = simple_strtoul(id2, &id2, 16);
|
||||||
|
|
||||||
|
return (dev1 < dev2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ctcm_ch_alloc_buffer(struct channel *ch);
|
||||||
|
|
||||||
|
static inline int ctcm_checkalloc_buffer(struct channel *ch)
|
||||||
|
{
|
||||||
|
if (ch->trans_skb == NULL)
|
||||||
|
return ctcm_ch_alloc_buffer(ch);
|
||||||
|
if (ch->flags & CHANNEL_FLAGS_BUFSIZE_CHANGED) {
|
||||||
|
dev_kfree_skb(ch->trans_skb);
|
||||||
|
return ctcm_ch_alloc_buffer(ch);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv);
|
||||||
|
|
||||||
|
/* test if protocol attribute (of struct ctcm_priv or struct channel)
|
||||||
|
* has MPC protocol setting. Type is not checked
|
||||||
|
*/
|
||||||
|
#define IS_MPC(p) ((p)->protocol == CTCM_PROTO_MPC)
|
||||||
|
|
||||||
|
/* test if struct ctcm_priv of struct net_device has MPC protocol setting */
|
||||||
|
#define IS_MPCDEV(d) IS_MPC((struct ctcm_priv *)d->priv)
|
||||||
|
|
||||||
|
static inline gfp_t gfp_type(void)
|
||||||
|
{
|
||||||
|
return in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definition of our link level header.
|
||||||
|
*/
|
||||||
|
struct ll_header {
|
||||||
|
__u16 length;
|
||||||
|
__u16 type;
|
||||||
|
__u16 unused;
|
||||||
|
};
|
||||||
|
#define LL_HEADER_LENGTH (sizeof(struct ll_header))
|
||||||
|
|
||||||
|
#endif
|
2472
drivers/s390/net/ctcm_mpc.c
Normal file
2472
drivers/s390/net/ctcm_mpc.c
Normal file
File diff suppressed because it is too large
Load Diff
239
drivers/s390/net/ctcm_mpc.h
Normal file
239
drivers/s390/net/ctcm_mpc.h
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
/*
|
||||||
|
* drivers/s390/net/ctcm_mpc.h
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2007
|
||||||
|
* Authors: Peter Tiedemann (ptiedem@de.ibm.com)
|
||||||
|
*
|
||||||
|
* MPC additions:
|
||||||
|
* Belinda Thompson (belindat@us.ibm.com)
|
||||||
|
* Andy Richter (richtera@us.ibm.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CTC_MPC_H_
|
||||||
|
#define _CTC_MPC_H_
|
||||||
|
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include "fsm.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MPC external interface
|
||||||
|
* Note that ctc_mpc_xyz are called with a lock on ................
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* port_number is the mpc device 0, 1, 2 etc mpc2 is port_number 2 */
|
||||||
|
|
||||||
|
/* passive open Just wait for XID2 exchange */
|
||||||
|
extern int ctc_mpc_alloc_channel(int port,
|
||||||
|
void (*callback)(int port_num, int max_write_size));
|
||||||
|
/* active open Alloc then send XID2 */
|
||||||
|
extern void ctc_mpc_establish_connectivity(int port,
|
||||||
|
void (*callback)(int port_num, int rc, int max_write_size));
|
||||||
|
|
||||||
|
extern void ctc_mpc_dealloc_ch(int port);
|
||||||
|
extern void ctc_mpc_flow_control(int port, int flowc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* other MPC Group prototypes and structures
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ETH_P_SNA_DIX 0x80D5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Declaration of an XID2
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define ALLZEROS 0x0000000000000000
|
||||||
|
|
||||||
|
#define XID_FM2 0x20
|
||||||
|
#define XID2_0 0x00
|
||||||
|
#define XID2_7 0x07
|
||||||
|
#define XID2_WRITE_SIDE 0x04
|
||||||
|
#define XID2_READ_SIDE 0x05
|
||||||
|
|
||||||
|
struct xid2 {
|
||||||
|
__u8 xid2_type_id;
|
||||||
|
__u8 xid2_len;
|
||||||
|
__u32 xid2_adj_id;
|
||||||
|
__u8 xid2_rlen;
|
||||||
|
__u8 xid2_resv1;
|
||||||
|
__u8 xid2_flag1;
|
||||||
|
__u8 xid2_fmtt;
|
||||||
|
__u8 xid2_flag4;
|
||||||
|
__u16 xid2_resv2;
|
||||||
|
__u8 xid2_tgnum;
|
||||||
|
__u32 xid2_sender_id;
|
||||||
|
__u8 xid2_flag2;
|
||||||
|
__u8 xid2_option;
|
||||||
|
char xid2_resv3[8];
|
||||||
|
__u16 xid2_resv4;
|
||||||
|
__u8 xid2_dlc_type;
|
||||||
|
__u16 xid2_resv5;
|
||||||
|
__u8 xid2_mpc_flag;
|
||||||
|
__u8 xid2_resv6;
|
||||||
|
__u16 xid2_buf_len;
|
||||||
|
char xid2_buffer[255 - (13 * sizeof(__u8) +
|
||||||
|
2 * sizeof(__u32) +
|
||||||
|
4 * sizeof(__u16) +
|
||||||
|
8 * sizeof(char))];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#define XID2_LENGTH (sizeof(struct xid2))
|
||||||
|
|
||||||
|
struct th_header {
|
||||||
|
__u8 th_seg;
|
||||||
|
__u8 th_ch_flag;
|
||||||
|
#define TH_HAS_PDU 0xf0
|
||||||
|
#define TH_IS_XID 0x01
|
||||||
|
#define TH_SWEEP_REQ 0xfe
|
||||||
|
#define TH_SWEEP_RESP 0xff
|
||||||
|
__u8 th_blk_flag;
|
||||||
|
#define TH_DATA_IS_XID 0x80
|
||||||
|
#define TH_RETRY 0x40
|
||||||
|
#define TH_DISCONTACT 0xc0
|
||||||
|
#define TH_SEG_BLK 0x20
|
||||||
|
#define TH_LAST_SEG 0x10
|
||||||
|
#define TH_PDU_PART 0x08
|
||||||
|
__u8 th_is_xid; /* is 0x01 if this is XID */
|
||||||
|
__u32 th_seq_num;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct th_addon {
|
||||||
|
__u32 th_last_seq;
|
||||||
|
__u32 th_resvd;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct th_sweep {
|
||||||
|
struct th_header th;
|
||||||
|
struct th_addon sw;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#define TH_HEADER_LENGTH (sizeof(struct th_header))
|
||||||
|
#define TH_SWEEP_LENGTH (sizeof(struct th_sweep))
|
||||||
|
|
||||||
|
#define PDU_LAST 0x80
|
||||||
|
#define PDU_CNTL 0x40
|
||||||
|
#define PDU_FIRST 0x20
|
||||||
|
|
||||||
|
struct pdu {
|
||||||
|
__u32 pdu_offset;
|
||||||
|
__u8 pdu_flag;
|
||||||
|
__u8 pdu_proto; /* 0x01 is APPN SNA */
|
||||||
|
__u16 pdu_seq;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#define PDU_HEADER_LENGTH (sizeof(struct pdu))
|
||||||
|
|
||||||
|
struct qllc {
|
||||||
|
__u8 qllc_address;
|
||||||
|
#define QLLC_REQ 0xFF
|
||||||
|
#define QLLC_RESP 0x00
|
||||||
|
__u8 qllc_commands;
|
||||||
|
#define QLLC_DISCONNECT 0x53
|
||||||
|
#define QLLC_UNSEQACK 0x73
|
||||||
|
#define QLLC_SETMODE 0x93
|
||||||
|
#define QLLC_EXCHID 0xBF
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definition of one MPC group
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_MPCGCHAN 10
|
||||||
|
#define MPC_XID_TIMEOUT_VALUE 10000
|
||||||
|
#define MPC_CHANNEL_ADD 0
|
||||||
|
#define MPC_CHANNEL_REMOVE 1
|
||||||
|
#define MPC_CHANNEL_ATTN 2
|
||||||
|
#define XSIDE 1
|
||||||
|
#define YSIDE 0
|
||||||
|
|
||||||
|
struct mpcg_info {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
struct channel *ch;
|
||||||
|
struct xid2 *xid;
|
||||||
|
struct th_sweep *sweep;
|
||||||
|
struct th_header *th;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mpc_group {
|
||||||
|
struct tasklet_struct mpc_tasklet;
|
||||||
|
struct tasklet_struct mpc_tasklet2;
|
||||||
|
int changed_side;
|
||||||
|
int saved_state;
|
||||||
|
int channels_terminating;
|
||||||
|
int out_of_sequence;
|
||||||
|
int flow_off_called;
|
||||||
|
int port_num;
|
||||||
|
int port_persist;
|
||||||
|
int alloc_called;
|
||||||
|
__u32 xid2_adj_id;
|
||||||
|
__u8 xid2_tgnum;
|
||||||
|
__u32 xid2_sender_id;
|
||||||
|
int num_channel_paths;
|
||||||
|
int active_channels[2];
|
||||||
|
__u16 group_max_buflen;
|
||||||
|
int outstanding_xid2;
|
||||||
|
int outstanding_xid7;
|
||||||
|
int outstanding_xid7_p2;
|
||||||
|
int sweep_req_pend_num;
|
||||||
|
int sweep_rsp_pend_num;
|
||||||
|
struct sk_buff *xid_skb;
|
||||||
|
char *xid_skb_data;
|
||||||
|
struct th_header *xid_th;
|
||||||
|
struct xid2 *xid;
|
||||||
|
char *xid_id;
|
||||||
|
struct th_header *rcvd_xid_th;
|
||||||
|
struct sk_buff *rcvd_xid_skb;
|
||||||
|
char *rcvd_xid_data;
|
||||||
|
__u8 in_sweep;
|
||||||
|
__u8 roll;
|
||||||
|
struct xid2 *saved_xid2;
|
||||||
|
void (*allochanfunc)(int, int);
|
||||||
|
int allocchan_callback_retries;
|
||||||
|
void (*estconnfunc)(int, int, int);
|
||||||
|
int estconn_callback_retries;
|
||||||
|
int estconn_called;
|
||||||
|
int xidnogood;
|
||||||
|
int send_qllc_disc;
|
||||||
|
fsm_timer timer;
|
||||||
|
fsm_instance *fsm; /* group xid fsm */
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef DEBUGDATA
|
||||||
|
void ctcmpc_dumpit(char *buf, int len);
|
||||||
|
#else
|
||||||
|
static inline void ctcmpc_dumpit(char *buf, int len)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUGDATA
|
||||||
|
/*
|
||||||
|
* Dump header and first 16 bytes of an sk_buff for debugging purposes.
|
||||||
|
*
|
||||||
|
* skb The struct sk_buff to dump.
|
||||||
|
* offset Offset relative to skb-data, where to start the dump.
|
||||||
|
*/
|
||||||
|
void ctcmpc_dump_skb(struct sk_buff *skb, int offset);
|
||||||
|
#else
|
||||||
|
static inline void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
|
||||||
|
{}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void ctcmpc_dump32(char *buf, int len)
|
||||||
|
{
|
||||||
|
if (len < 32)
|
||||||
|
ctcmpc_dumpit(buf, len);
|
||||||
|
else
|
||||||
|
ctcmpc_dumpit(buf, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ctcmpc_open(struct net_device *);
|
||||||
|
void ctcm_ccw_check_rc(struct channel *, int, char *);
|
||||||
|
void mpc_group_ready(unsigned long adev);
|
||||||
|
int mpc_channel_action(struct channel *ch, int direction, int action);
|
||||||
|
void mpc_action_send_discontact(unsigned long thischan);
|
||||||
|
void mpc_action_discontact(fsm_instance *fi, int event, void *arg);
|
||||||
|
void ctcmpc_bh(unsigned long thischan);
|
||||||
|
#endif
|
||||||
|
/* --- This is the END my friend --- */
|
210
drivers/s390/net/ctcm_sysfs.c
Normal file
210
drivers/s390/net/ctcm_sysfs.c
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
/*
|
||||||
|
* drivers/s390/net/ctcm_sysfs.c
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2007, 2007
|
||||||
|
* Authors: Peter Tiedemann (ptiedem@de.ibm.com)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef DEBUG
|
||||||
|
#undef DEBUGDATA
|
||||||
|
#undef DEBUGCCW
|
||||||
|
|
||||||
|
#include <linux/sysfs.h>
|
||||||
|
#include "ctcm_main.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sysfs attributes
|
||||||
|
*/
|
||||||
|
|
||||||
|
static ssize_t ctcm_buffer_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct ctcm_priv *priv = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (!priv)
|
||||||
|
return -ENODEV;
|
||||||
|
return sprintf(buf, "%d\n", priv->buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t ctcm_buffer_write(struct device *dev,
|
||||||
|
struct device_attribute *attr, const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct net_device *ndev;
|
||||||
|
int bs1;
|
||||||
|
struct ctcm_priv *priv = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (!(priv && priv->channel[READ] &&
|
||||||
|
(ndev = priv->channel[READ]->netdev))) {
|
||||||
|
CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, "bfnondev");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
sscanf(buf, "%u", &bs1);
|
||||||
|
if (bs1 > CTCM_BUFSIZE_LIMIT)
|
||||||
|
goto einval;
|
||||||
|
if (bs1 < (576 + LL_HEADER_LENGTH + 2))
|
||||||
|
goto einval;
|
||||||
|
priv->buffer_size = bs1; /* just to overwrite the default */
|
||||||
|
|
||||||
|
if ((ndev->flags & IFF_RUNNING) &&
|
||||||
|
(bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
|
||||||
|
goto einval;
|
||||||
|
|
||||||
|
priv->channel[READ]->max_bufsize = bs1;
|
||||||
|
priv->channel[WRITE]->max_bufsize = bs1;
|
||||||
|
if (!(ndev->flags & IFF_RUNNING))
|
||||||
|
ndev->mtu = bs1 - LL_HEADER_LENGTH - 2;
|
||||||
|
priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
|
||||||
|
priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
|
||||||
|
|
||||||
|
CTCM_DBF_DEV(SETUP, ndev, buf);
|
||||||
|
return count;
|
||||||
|
|
||||||
|
einval:
|
||||||
|
CTCM_DBF_DEV(SETUP, ndev, "buff_err");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ctcm_print_statistics(struct ctcm_priv *priv)
|
||||||
|
{
|
||||||
|
char *sbuf;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (!priv)
|
||||||
|
return;
|
||||||
|
sbuf = kmalloc(2048, GFP_KERNEL);
|
||||||
|
if (sbuf == NULL)
|
||||||
|
return;
|
||||||
|
p = sbuf;
|
||||||
|
|
||||||
|
p += sprintf(p, " Device FSM state: %s\n",
|
||||||
|
fsm_getstate_str(priv->fsm));
|
||||||
|
p += sprintf(p, " RX channel FSM state: %s\n",
|
||||||
|
fsm_getstate_str(priv->channel[READ]->fsm));
|
||||||
|
p += sprintf(p, " TX channel FSM state: %s\n",
|
||||||
|
fsm_getstate_str(priv->channel[WRITE]->fsm));
|
||||||
|
p += sprintf(p, " Max. TX buffer used: %ld\n",
|
||||||
|
priv->channel[WRITE]->prof.maxmulti);
|
||||||
|
p += sprintf(p, " Max. chained SKBs: %ld\n",
|
||||||
|
priv->channel[WRITE]->prof.maxcqueue);
|
||||||
|
p += sprintf(p, " TX single write ops: %ld\n",
|
||||||
|
priv->channel[WRITE]->prof.doios_single);
|
||||||
|
p += sprintf(p, " TX multi write ops: %ld\n",
|
||||||
|
priv->channel[WRITE]->prof.doios_multi);
|
||||||
|
p += sprintf(p, " Netto bytes written: %ld\n",
|
||||||
|
priv->channel[WRITE]->prof.txlen);
|
||||||
|
p += sprintf(p, " Max. TX IO-time: %ld\n",
|
||||||
|
priv->channel[WRITE]->prof.tx_time);
|
||||||
|
|
||||||
|
printk(KERN_INFO "Statistics for %s:\n%s",
|
||||||
|
priv->channel[WRITE]->netdev->name, sbuf);
|
||||||
|
kfree(sbuf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t stats_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct ctcm_priv *priv = dev_get_drvdata(dev);
|
||||||
|
if (!priv)
|
||||||
|
return -ENODEV;
|
||||||
|
ctcm_print_statistics(priv);
|
||||||
|
return sprintf(buf, "0\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t stats_write(struct device *dev, struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct ctcm_priv *priv = dev_get_drvdata(dev);
|
||||||
|
if (!priv)
|
||||||
|
return -ENODEV;
|
||||||
|
/* Reset statistics */
|
||||||
|
memset(&priv->channel[WRITE]->prof, 0,
|
||||||
|
sizeof(priv->channel[WRITE]->prof));
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t ctcm_proto_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct ctcm_priv *priv = dev_get_drvdata(dev);
|
||||||
|
if (!priv)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
return sprintf(buf, "%d\n", priv->protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t ctcm_proto_store(struct device *dev,
|
||||||
|
struct device_attribute *attr, const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
struct ctcm_priv *priv = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (!priv)
|
||||||
|
return -ENODEV;
|
||||||
|
sscanf(buf, "%u", &value);
|
||||||
|
if (!((value == CTCM_PROTO_S390) ||
|
||||||
|
(value == CTCM_PROTO_LINUX) ||
|
||||||
|
(value == CTCM_PROTO_MPC) ||
|
||||||
|
(value == CTCM_PROTO_OS390)))
|
||||||
|
return -EINVAL;
|
||||||
|
priv->protocol = value;
|
||||||
|
CTCM_DBF_DEV(SETUP, dev, buf);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t ctcm_type_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct ccwgroup_device *cgdev;
|
||||||
|
|
||||||
|
cgdev = to_ccwgroupdev(dev);
|
||||||
|
if (!cgdev)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
return sprintf(buf, "%s\n",
|
||||||
|
cu3088_type[cgdev->cdev[0]->id.driver_info]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write);
|
||||||
|
static DEVICE_ATTR(protocol, 0644, ctcm_proto_show, ctcm_proto_store);
|
||||||
|
static DEVICE_ATTR(type, 0444, ctcm_type_show, NULL);
|
||||||
|
static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
|
||||||
|
|
||||||
|
static struct attribute *ctcm_attr[] = {
|
||||||
|
&dev_attr_protocol.attr,
|
||||||
|
&dev_attr_type.attr,
|
||||||
|
&dev_attr_buffer.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute_group ctcm_attr_group = {
|
||||||
|
.attrs = ctcm_attr,
|
||||||
|
};
|
||||||
|
|
||||||
|
int ctcm_add_attributes(struct device *dev)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = device_create_file(dev, &dev_attr_stats);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ctcm_remove_attributes(struct device *dev)
|
||||||
|
{
|
||||||
|
device_remove_file(dev, &dev_attr_stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ctcm_add_files(struct device *dev)
|
||||||
|
{
|
||||||
|
return sysfs_create_group(&dev->kobj, &ctcm_attr_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ctcm_remove_files(struct device *dev)
|
||||||
|
{
|
||||||
|
sysfs_remove_group(&dev->kobj, &ctcm_attr_group);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user