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 changed files with 7920 additions and 8 deletions
|
@ -11,15 +11,17 @@ config LCS
|
|||
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.
|
||||
|
||||
config CTC
|
||||
tristate "CTC device support"
|
||||
config CTCM
|
||||
tristate "CTC and MPC SNA device support"
|
||||
depends on CCW && NETDEVICES
|
||||
help
|
||||
Select this option if you want to use channel-to-channel
|
||||
point-to-point networking on IBM System z.
|
||||
This device driver supports real CTC coupling using ESCON.
|
||||
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.
|
||||
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.
|
||||
|
||||
config CCWGROUP
|
||||
tristate
|
||||
default (LCS || CTC || QETH)
|
||||
tristate
|
||||
default (LCS || CTCM || QETH)
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
# 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_SMSGIUCV) += smsgiucv.o
|
||||
obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.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
|
||||
|
|
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 a new issue