mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -85,6 +87,6 @@ config QETH_VLAN
 | 
			
		|||
 | 
			
		||||
config CCWGROUP
 | 
			
		||||
	tristate
 | 
			
		||||
	default (LCS || CTC || QETH)
 | 
			
		||||
	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