Commit 7394c928 authored by Frank Pavlic's avatar Frank Pavlic Committed by Jeff Garzik
Browse files

[PATCH] s390: ctc code cleanup



[patch 5/10] s390: ctc code cleanup.

From: Peter Tiedemann <ptiedem@de.ibm.com>

ctc network driver changes:
 - Some code cleanup.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 7f81947b
/*
*
* linux/drivers/s390/net/ctcdbug.h ($Revision: 1.4 $)
* linux/drivers/s390/net/ctcdbug.h ($Revision: 1.5 $)
*
* CTC / ESCON network driver - s390 dbf exploit.
*
......@@ -9,7 +9,7 @@
* Author(s): Original Code written by
* Peter Tiedemann (ptiedem@de.ibm.com)
*
* $Revision: 1.4 $ $Date: 2004/10/15 09:26:58 $
* $Revision: 1.5 $ $Date: 2005/02/27 19:46:44 $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -25,9 +25,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _CTCDBUG_H_
#define _CTCDBUG_H_
#include <asm/debug.h>
#include "ctcmain.h"
/**
* Debug Facility stuff
*/
......@@ -41,7 +43,7 @@
#define CTC_DBF_DATA_LEN 128
#define CTC_DBF_DATA_INDEX 3
#define CTC_DBF_DATA_NR_AREAS 1
#define CTC_DBF_DATA_LEVEL 2
#define CTC_DBF_DATA_LEVEL 3
#define CTC_DBF_TRACE_NAME "ctc_trace"
#define CTC_DBF_TRACE_LEN 16
......@@ -121,3 +123,5 @@ hex_dump(unsigned char *buf, size_t len)
printk("\n");
}
#endif
/*
* $Id: ctcmain.c,v 1.72 2005/03/17 10:51:52 ptiedem Exp $
* $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $
*
* CTC / ESCON network driver
*
......@@ -37,12 +37,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* RELEASE-TAG: CTC/ESCON network driver $Revision: 1.72 $
* RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $
*
*/
#undef DEBUG
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
......@@ -74,288 +73,13 @@
#include "ctctty.h"
#include "fsm.h"
#include "cu3088.h"
#include "ctcdbug.h"
#include "ctcmain.h"
MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver");
MODULE_LICENSE("GPL");
/**
* CCW commands, used in this driver.
*/
#define CCW_CMD_WRITE 0x01
#define CCW_CMD_READ 0x02
#define CCW_CMD_SET_EXTENDED 0xc3
#define CCW_CMD_PREPARE 0xe3
#define CTC_PROTO_S390 0
#define CTC_PROTO_LINUX 1
#define CTC_PROTO_LINUX_TTY 2
#define CTC_PROTO_OS390 3
#define CTC_PROTO_MAX 3
#define CTC_BUFSIZE_LIMIT 65535
#define CTC_BUFSIZE_DEFAULT 32768
#define CTC_TIMEOUT_5SEC 5000
#define CTC_INITIAL_BLOCKLEN 2
#define READ 0
#define WRITE 1
#define CTC_ID_SIZE BUS_ID_SIZE+3
struct ctc_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 {
/**
* Pointer to next channel in list.
*/
struct channel *next;
char id[CTC_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;
/**
* The protocol of this channel
*/
__u16 protocol;
/**
* I/O and irq related stuff
*/
struct ccw1 *ccw;
struct irb *irb;
/**
* RX/TX buffer size
*/
int max_bufsize;
/**
* Transmit/Receive buffer.
*/
struct sk_buff *trans_skb;
/**
* Universal I/O queue.
*/
struct sk_buff_head io_queue;
/**
* 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;
/**
* Retry counter for misc. operations.
*/
int retry;
/**
* The finite state machine of this channel
*/
fsm_instance *fsm;
/**
* The corresponding net_device this channel
* belongs to.
*/
struct net_device *netdev;
struct ctc_profile prof;
unsigned char *trans_skb_data;
__u16 logflags;
};
#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 CTC_LOGLEVEL_INFO 1
#define CTC_LOGLEVEL_NOTICE 2
#define CTC_LOGLEVEL_WARN 4
#define CTC_LOGLEVEL_EMERG 8
#define CTC_LOGLEVEL_ERR 16
#define CTC_LOGLEVEL_DEBUG 32
#define CTC_LOGLEVEL_CRIT 64
#define CTC_LOGLEVEL_DEFAULT \
(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT)
#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1)
static int loglevel = CTC_LOGLEVEL_DEFAULT;
#define ctc_pr_debug(fmt, arg...) \
do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0)
#define ctc_pr_info(fmt, arg...) \
do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0)
#define ctc_pr_notice(fmt, arg...) \
do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0)
#define ctc_pr_warn(fmt, arg...) \
do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0)
#define ctc_pr_emerg(fmt, arg...) \
do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0)
#define ctc_pr_err(fmt, arg...) \
do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0)
#define ctc_pr_crit(fmt, arg...) \
do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0)
/**
* Linked list of all detected channels.
*/
static struct channel *channels = NULL;
struct ctc_priv {
struct net_device_stats stats;
unsigned long tbusy;
/**
* 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;
struct channel *channel[2];
};
/**
* Definition of our link level header.
*/
struct ll_header {
__u16 length;
__u16 type;
__u16 unused;
};
#define LL_HEADER_LENGTH (sizeof(struct ll_header))
/**
* Compatibility macros for busy handling
* of network devices.
*/
static __inline__ void
ctc_clear_busy(struct net_device * dev)
{
clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
netif_wake_queue(dev);
}
static __inline__ int
ctc_test_and_set_busy(struct net_device * dev)
{
if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
netif_stop_queue(dev);
return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
}
/**
* Print Banner.
*/
static void
print_banner(void)
{
static int printed = 0;
char vbuf[] = "$Revision: 1.72 $";
char *version = vbuf;
if (printed)
return;
if ((version = strchr(version, ':'))) {
char *p = strchr(version + 1, '$');
if (p)
*p = '\0';
} else
version = " ??? ";
printk(KERN_INFO "CTC driver Version%s"
#ifdef DEBUG
" (DEBUG-VERSION, " __DATE__ __TIME__ ")"
#endif
" initialized\n", version);
printed = 1;
}
/**
* Return type of a detected device.
*/
static enum channel_types
get_channel_type(struct ccw_device_id *id)
{
enum channel_types type = (enum channel_types) id->driver_info;
if (type == channel_type_ficon)
type = channel_type_escon;
return type;
}
/**
* States of the interface statemachine.
*/
......@@ -371,7 +95,7 @@ enum dev_states {
/**
* MUST be always the last element!!
*/
NR_DEV_STATES
CTC_NR_DEV_STATES
};
static const char *dev_state_names[] = {
......@@ -399,7 +123,7 @@ enum dev_events {
/**
* MUST be always the last element!!
*/
NR_DEV_EVENTS
CTC_NR_DEV_EVENTS
};
static const char *dev_event_names[] = {
......@@ -476,40 +200,6 @@ enum ch_events {
NR_CH_EVENTS,
};
static const char *ch_event_names[] = {
"ccw_device success",
"ccw_device busy",
"ccw_device enodev",
"ccw_device ioerr",
"ccw_device unknown",
"Status ATTN & BUSY",
"Status ATTN",
"Status BUSY",
"Unit check remote reset",
"Unit check remote system reset",
"Unit check TX timeout",
"Unit check TX parity",
"Unit check Hardware failure",
"Unit check RX parity",
"Unit check ZERO",
"Unit check Unknown",
"SubChannel check Unknown",
"Machine check failure",
"Machine check operational",
"IRQ normal",
"IRQ final",
"Timer",
"Start",
"Stop",
};
/**
* States of the channel statemachine.
*/
......@@ -545,6 +235,87 @@ enum ch_states {
NR_CH_STATES,
};
static int loglevel = CTC_LOGLEVEL_DEFAULT;
/**
* Linked list of all detected channels.
*/
static struct channel *channels = NULL;
/**
* Print Banner.
*/
static void
print_banner(void)
{
static int printed = 0;
char vbuf[] = "$Revision: 1.74 $";
char *version = vbuf;
if (printed)
return;
if ((version = strchr(version, ':'))) {
char *p = strchr(version + 1, '$');
if (p)
*p = '\0';
} else
version = " ??? ";
printk(KERN_INFO "CTC driver Version%s"
#ifdef DEBUG
" (DEBUG-VERSION, " __DATE__ __TIME__ ")"
#endif
" initialized\n", version);
printed = 1;
}
/**
* Return type of a detected device.
*/
static enum channel_types
get_channel_type(struct ccw_device_id *id)
{
enum channel_types type = (enum channel_types) id->driver_info;
if (type == channel_type_ficon)
type = channel_type_escon;
return type;
}
static const char *ch_event_names[] = {
"ccw_device success",
"ccw_device busy",
"ccw_device enodev",
"ccw_device ioerr",
"ccw_device unknown",
"Status ATTN & BUSY",
"Status ATTN",
"Status BUSY",
"Unit check remote reset",
"Unit check remote system reset",
"Unit check TX timeout",
"Unit check TX parity",
"Unit check Hardware failure",
"Unit check RX parity",
"Unit check ZERO",
"Unit check Unknown",
"SubChannel check Unknown",
"Machine check failure",
"Machine check operational",
"IRQ normal",
"IRQ final",
"Timer",
"Start",
"Stop",
};
static const char *ch_state_names[] = {
"Idle",
"Stopped",
......@@ -1934,7 +1705,6 @@ add_channel(struct ccw_device *cdev, enum channel_types type)
ch->cdev = cdev;
snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id);
ch->type = type;
loglevel = CTC_LOGLEVEL_DEFAULT;
ch->fsm = init_fsm(ch->id, ch_state_names,
ch_event_names, NR_CH_STATES, NR_CH_EVENTS,
ch_fsm, CH_FSM_LEN, GFP_KERNEL);
......@@ -2697,6 +2467,7 @@ ctc_stats(struct net_device * dev)
/*
* sysfs attributes
*/
static ssize_t
buffer_show(struct device *dev, char *buf)
{
......@@ -2715,57 +2486,61 @@ buffer_write(struct device *dev, const char *buf, size_t count)
struct ctc_priv *priv;
struct net_device *ndev;
int bs1;
char buffer[16];
DBF_TEXT(trace, 3, __FUNCTION__);
DBF_TEXT(trace, 3, buf);
priv = dev->driver_data;
if (!priv)
if (!priv) {
DBF_TEXT(trace, 3, "bfnopriv");
return -ENODEV;
}
sscanf(buf, "%u", &bs1);
if (bs1 > CTC_BUFSIZE_LIMIT)
goto einval;
if (bs1 < (576 + LL_HEADER_LENGTH + 2))
goto einval;
priv->buffer_size = bs1; // just to overwrite the default
ndev = priv->channel[READ]->netdev;
if (!ndev)
if (!ndev) {
DBF_TEXT(trace, 3, "bfnondev");
return -ENODEV;
sscanf(buf, "%u", &bs1);
}
if (bs1 > CTC_BUFSIZE_LIMIT)
return -EINVAL;
if ((ndev->flags & IFF_RUNNING) &&
(bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
return -EINVAL;
if (bs1 < (576 + LL_HEADER_LENGTH + 2))
return -EINVAL;
goto einval;
priv->buffer_size = bs1;
priv->channel[READ]->max_bufsize =
priv->channel[WRITE]->max_bufsize = bs1;
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;
sprintf(buffer, "%d",priv->buffer_size);
DBF_TEXT(trace, 3, buffer);
return count;
einval:
DBF_TEXT(trace, 3, "buff_err");
return -EINVAL;
}
static ssize_t
loglevel_show(struct device *dev, char *buf)
{
struct ctc_priv *priv;
priv = dev->driver_data;
if (!priv)
return -ENODEV;
return sprintf(buf, "%d\n", loglevel);
}
static ssize_t
loglevel_write(struct device *dev, const char *buf, size_t count)
{
struct ctc_priv *priv;
int ll1;
DBF_TEXT(trace, 5, __FUNCTION__);
priv = dev->driver_data;
if (!priv)
return -ENODEV;
sscanf(buf, "%i", &ll1);
if ((ll1 > CTC_LOGLEVEL_MAX) || (ll1 < 0))
......@@ -2835,27 +2610,6 @@ stats_write(struct device *dev, const char *buf, size_t count)
return count;
}
static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write);
static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
static int
ctc_add_attributes(struct device *dev)
{
// device_create_file(dev, &dev_attr_buffer);
device_create_file(dev, &dev_attr_loglevel);
device_create_file(dev, &dev_attr_stats);
return 0;
}
static void
ctc_remove_attributes(struct device *dev)
{
device_remove_file(dev, &dev_attr_stats);
device_remove_file(dev, &dev_attr_loglevel);
// device_remove_file(dev, &dev_attr_buffer);
}
static void
ctc_netdev_unregister(struct net_device * dev)
......@@ -2899,52 +2653,6 @@ ctc_free_netdevice(struct net_device * dev, int free_dev)
#endif
}
/**
* Initialize everything of the net device except the name and the
* channel structs.
*/
static struct net_device *
ctc_init_netdevice(struct net_device * dev, int alloc_device,
struct ctc_priv *privptr)
{
if (!privptr)
return NULL;
DBF_TEXT(setup, 3, __FUNCTION__);
if (alloc_device) {
dev = kmalloc(sizeof (struct net_device), GFP_KERNEL);
if (!dev)
return NULL;