Commit 7747d41e authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] s390: network driver

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

Network driver changes:
 - lcs: Add missing irb error checking.
 - lcs: Fix multicasting.
 - lcs: Use a seperate lock (ipm_lock) for multicast list.
 - lcs: Add missing in_dev_put in multicase address list handling.
 - iucv: Set static variables to NULL after kfree.
 - iucv: Do bus_unregister if module initialization fails.
 - netiucv: Convert iucvMagic to EBCDIC in con_action_start.
 - netiucv: Remove administration of ifno-stuff for device name,
 - netiucv: Add attribute to remove a netiucv device.
 - qeth: Add version string that is displayed at driver load time.
 - qeth: Fix memory leak in qeth_arp_query.
 - qeth: Remove duplicate case statements in qeth_do_ioctl.
 - qeth: Fix OSA broadcast filtering.
 - qeth: Increase timeout for purge ARP cache IPA.
 - qeth: Fix hsi device naming.
 - qeth: Add do_QDIO count to qeth performance statistics.
 - qeth: Allow writing to IP address takeover attribute only in
         state DOWN or RECOVER.
 - qeth: Fix hang when removing a vlan device.
 - qeth: Cleanup error messages for ARP commands.
 - qeth: Return EOPNOTSUPP for purge ARP on HiperSockets.
 - qeth: Drop skbs if the net_device of a qeth device is down.
 - qeth: Simplify ip address list processing.
parent a7a53392
/*
* $Id: iucv.c,v 1.28 2004/04/15 06:34:58 braunu Exp $
* $Id: iucv.c,v 1.30 2004/05/13 09:21:23 braunu Exp $
*
* IUCV network driver
*
......@@ -29,7 +29,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* RELEASE-TAG: IUCV lowlevel driver $Revision: 1.28 $
* RELEASE-TAG: IUCV lowlevel driver $Revision: 1.30 $
*
*/
......@@ -98,7 +98,7 @@ typedef struct {
__u8 res3[24];
} iucv_GeneralInterrupt;
static iucv_GeneralInterrupt *iucv_external_int_buffer;
static iucv_GeneralInterrupt *iucv_external_int_buffer = NULL;
/* Spin Lock declaration */
......@@ -351,7 +351,7 @@ do { \
static void
iucv_banner(void)
{
char vbuf[] = "$Revision: 1.28 $";
char vbuf[] = "$Revision: 1.30 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
......@@ -403,6 +403,7 @@ iucv_init(void)
"%s: Could not allocate external interrupt buffer\n",
__FUNCTION__);
s390_root_dev_unregister(iucv_root);
bus_unregister(&iucv_bus);
return -ENOMEM;
}
memset(iucv_external_int_buffer, 0, sizeof(iucv_GeneralInterrupt));
......@@ -416,6 +417,7 @@ iucv_init(void)
kfree(iucv_external_int_buffer);
iucv_external_int_buffer = NULL;
s390_root_dev_unregister(iucv_root);
bus_unregister(&iucv_bus);
return -ENOMEM;
}
memset(iucv_param_pool, 0, sizeof(iucv_param) * PARAM_POOL_SIZE);
......@@ -441,10 +443,14 @@ static void
iucv_exit(void)
{
iucv_retrieve_buffer();
if (iucv_external_int_buffer)
if (iucv_external_int_buffer) {
kfree(iucv_external_int_buffer);
if (iucv_param_pool)
iucv_external_int_buffer = NULL;
}
if (iucv_param_pool) {
kfree(iucv_param_pool);
iucv_param_pool = NULL;
}
s390_root_dev_unregister(iucv_root);
bus_unregister(&iucv_bus);
printk(KERN_INFO "IUCV lowlevel driver unloaded\n");
......
......@@ -11,7 +11,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*
* $Revision: 1.74 $ $Date: 2004/04/05 00:01:04 $
* $Revision: 1.80 $ $Date: 2004/05/13 08:22:06 $
*
* 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
......@@ -58,7 +58,7 @@
/**
* initialization string for output
*/
#define VERSION_LCS_C "$Revision: 1.74 $"
#define VERSION_LCS_C "$Revision: 1.80 $"
static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
static char debug_buffer[255];
......@@ -99,9 +99,9 @@ lcs_register_debug_facility(void)
return -ENOMEM;
}
debug_register_view(lcs_dbf_setup, &debug_hex_ascii_view);
debug_set_level(lcs_dbf_setup, 5);
debug_set_level(lcs_dbf_setup, 2);
debug_register_view(lcs_dbf_trace, &debug_hex_ascii_view);
debug_set_level(lcs_dbf_trace, 5);
debug_set_level(lcs_dbf_trace, 2);
return 0;
}
......@@ -338,6 +338,7 @@ lcs_setup_card(struct lcs_card *card)
(void *)lcs_start_kernel_thread,card);
card->thread_mask = 0;
spin_lock_init(&card->lock);
spin_lock_init(&card->ipm_lock);
#ifdef CONFIG_IP_MULTICAST
INIT_LIST_HEAD(&card->ipm_list);
#endif
......@@ -935,18 +936,14 @@ lcs_check_multicast_support(struct lcs_card *card)
/**
* set or del multicast address on LCS card
*/
static int
lcs_fix_multicast_list(void *data)
static void
lcs_fix_multicast_list(struct lcs_card *card)
{
struct list_head *l, *n;
struct lcs_ipm_list *ipm;
struct lcs_card *card;
card = (struct lcs_card *) data;
daemonize("fixipm");
LCS_DBF_TEXT(4,trace, "fixipm");
spin_lock(&card->lock);
spin_lock(&card->ipm_lock);
list_for_each_safe(l, n, &card->ipm_list) {
ipm = list_entry(l, struct lcs_ipm_list, list);
switch (ipm->ipm_state) {
......@@ -968,8 +965,7 @@ lcs_fix_multicast_list(void *data)
}
if (card->state == DEV_STATE_UP)
netif_wake_queue(card->dev);
spin_unlock(&card->lock);
return 0;
spin_unlock(&card->ipm_lock);
}
/**
......@@ -988,28 +984,30 @@ lcs_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev)
/**
* function called by net device to handle multicast address relevant things
*/
static void
lcs_set_multicast_list(struct net_device *dev)
static int
lcs_register_mc_addresses(void *data)
{
struct lcs_card *card;
char buf[MAX_ADDR_LEN];
struct list_head *l;
struct ip_mc_list *im4;
struct in_device *in4_dev;
struct lcs_ipm_list *ipm, *tmp;
struct lcs_card *card;
LCS_DBF_TEXT(4, trace, "setmulti");
in4_dev = in_dev_get(dev);
daemonize("regipm");
LCS_DBF_TEXT(4, trace, "regmulti");
card = (struct lcs_card *) data;
in4_dev = in_dev_get(card->dev);
if (in4_dev == NULL)
return;
return 0;
read_lock(&in4_dev->lock);
card = (struct lcs_card *) dev->priv;
spin_lock(&card->lock);
spin_lock(&card->ipm_lock);
/* Check for multicast addresses to be removed. */
list_for_each(l, &card->ipm_list) {
ipm = list_entry(l, struct lcs_ipm_list, list);
for (im4 = in4_dev->mc_list; im4 != NULL; im4 = im4->next) {
lcs_get_mac_for_ipm(im4->multiaddr, buf, dev);
lcs_get_mac_for_ipm(im4->multiaddr, buf, card->dev);
if (memcmp(buf, &ipm->ipm.mac_addr,
LCS_MAC_LENGTH) == 0 &&
ipm->ipm.ip_addr == im4->multiaddr)
......@@ -1020,7 +1018,7 @@ lcs_set_multicast_list(struct net_device *dev)
}
/* Check for multicast addresses to be added. */
for (im4 = in4_dev->mc_list; im4; im4 = im4->next) {
lcs_get_mac_for_ipm(im4->multiaddr, buf, dev);
lcs_get_mac_for_ipm(im4->multiaddr, buf, card->dev);
ipm = NULL;
list_for_each(l, &card->ipm_list) {
tmp = list_entry(l, struct lcs_ipm_list, list);
......@@ -1046,14 +1044,56 @@ lcs_set_multicast_list(struct net_device *dev)
ipm->ipm_state = LCS_IPM_STATE_SET_REQUIRED;
list_add(&ipm->list, &card->ipm_list);
}
spin_unlock(&card->lock);
spin_unlock(&card->ipm_lock);
read_unlock(&in4_dev->lock);
set_bit(3, &card->thread_mask);
schedule_work(&card->kernel_thread_starter);
lcs_fix_multicast_list(card);
in_dev_put(in4_dev);
return 0;
}
/**
* function called by net device to
* handle multicast address relevant things
*/
static void
lcs_set_multicast_list(struct net_device *dev)
{
struct lcs_card *card;
LCS_DBF_TEXT(4, trace, "setmulti");
card = (struct lcs_card *) dev->priv;
set_bit(3, &card->thread_mask);
schedule_work(&card->kernel_thread_starter);
}
#endif /* CONFIG_IP_MULTICAST */
static long
lcs_check_irb_error(struct ccw_device *cdev, struct irb *irb)
{
if (!IS_ERR(irb))
return 0;
switch (PTR_ERR(irb)) {
case -EIO:
PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id);
LCS_DBF_TEXT(2, trace, "ckirberr");
LCS_DBF_TEXT_(2, trace, " rc%d", -EIO);
break;
case -ETIMEDOUT:
PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
LCS_DBF_TEXT(2, trace, "ckirberr");
LCS_DBF_TEXT_(2, trace, " rc%d", -ETIMEDOUT);
break;
default:
PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
cdev->dev.bus_id);
LCS_DBF_TEXT(2, trace, "ckirberr");
LCS_DBF_TEXT(2, trace, " rc???");
}
return PTR_ERR(irb);
}
/**
* IRQ Handler for LCS channels
*/
......@@ -1064,6 +1104,9 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
struct lcs_channel *channel;
int index;
if (lcs_check_irb_error(cdev, irb))
return;
card = CARD_FROM_DEV(cdev);
if (card->read.ccwdev == cdev)
channel = &card->read;
......@@ -1513,7 +1556,7 @@ lcs_start_kernel_thread(struct lcs_card *card)
kernel_thread(lcs_lgw_stoplan_thread, (void *) card, SIGCHLD);
#ifdef CONFIG_IP_MULTICAST
if (test_and_clear_bit(3, &card->thread_mask))
kernel_thread(lcs_fix_multicast_list, (void *) card, SIGCHLD);
kernel_thread(lcs_register_mc_addresses, (void *) card, SIGCHLD);
#endif
}
......@@ -1903,7 +1946,7 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
goto out;
memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH);
#ifdef CONFIG_IP_MULTICAST
if (lcs_check_multicast_support(card))
if (!lcs_check_multicast_support(card))
card->dev->set_multicast_list = lcs_set_multicast_list;
#endif
netif_stop_queue(card->dev);
......
......@@ -6,7 +6,7 @@
#include <linux/workqueue.h>
#include <asm/ccwdev.h>
#define VERSION_LCS_H "$Revision: 1.15 $"
#define VERSION_LCS_H "$Revision: 1.16 $"
#define LCS_DBF_TEXT(level, name, text) \
do { \
......@@ -273,6 +273,7 @@ struct lcs_channel {
*/
struct lcs_card {
spinlock_t lock;
spinlock_t ipm_lock;
enum lcs_dev_states state;
struct net_device *dev;
struct net_device_stats stats;
......
/*
* $Id: netiucv.c,v 1.51 2004/04/23 08:11:21 mschwide Exp $
* $Id: netiucv.c,v 1.53 2004/05/07 14:29:37 mschwide Exp $
*
* IUCV network driver
*
......@@ -30,7 +30,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* RELEASE-TAG: IUCV network driver $Revision: 1.51 $
* RELEASE-TAG: IUCV network driver $Revision: 1.53 $
*
*/
......@@ -60,6 +60,7 @@
#include <asm/io.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/ebcdic.h>
#include "iucv.h"
#include "fsm.h"
......@@ -113,9 +114,6 @@ struct iucv_connection {
*/
static struct iucv_connection *connections;
/* Keep track of interfaces. */
static int ifno;
/**
* Representation of event-data for the
* connection state machine.
......@@ -549,7 +547,7 @@ conn_action_rx(fsm_instance *fi, int event, void *arg)
iucv_MessagePending *eib = (iucv_MessagePending *)ev->data;
struct netiucv_priv *privptr = (struct netiucv_priv *)conn->netdev->priv;
__u16 msglen = eib->ln1msg2.ipbfln1f;
__u32 msglen = eib->ln1msg2.ipbfln1f;
int rc;
pr_debug("%s() called\n", __FUNCTION__);
......@@ -571,6 +569,7 @@ conn_action_rx(fsm_instance *fi, int event, void *arg)
conn->rx_buff->data, msglen, NULL, NULL, NULL);
if (rc != 0 || msglen < 5) {
privptr->stats.rx_errors++;
printk(KERN_INFO "iucv_receive returned %08x\n", rc);
return;
}
netiucv_unpack_skb(conn, conn->rx_buff);
......@@ -647,7 +646,7 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg)
fsm_newstate(fi, CONN_STATE_IDLE);
if (privptr)
privptr->stats.tx_errors += txpackets;
printk(KERN_DEBUG "iucv_send returned %08x\n",
printk(KERN_INFO "iucv_send returned %08x\n",
rc);
} else {
if (privptr) {
......@@ -770,7 +769,7 @@ conn_action_start(fsm_instance *fi, int event, void *arg)
struct iucv_event *ev = (struct iucv_event *)arg;
struct iucv_connection *conn = ev->conn;
__u16 msglimit;
int rc;
int rc, len;
__u8 iucvMagic[16] = {
0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
......@@ -778,7 +777,10 @@ conn_action_start(fsm_instance *fi, int event, void *arg)
pr_debug("%s() called\n", __FUNCTION__);
memcpy(iucvMagic, conn->netdev->name, IFNAMSIZ);
len = (IFNAMSIZ < sizeof(conn->netdev->name)) ?
IFNAMSIZ : sizeof(conn->netdev->name);
memcpy(iucvMagic, conn->netdev->name, len);
ASCEBC (iucvMagic, len);
if (conn->handle == 0) {
conn->handle =
iucv_register_program(iucvMagic, conn->userid, mask,
......@@ -992,6 +994,7 @@ static void
dev_action_connup(fsm_instance *fi, int event, void *arg)
{
struct net_device *dev = (struct net_device *)arg;
struct netiucv_priv *privptr = dev->priv;
pr_debug("%s() called\n", __FUNCTION__);
......@@ -999,8 +1002,8 @@ dev_action_connup(fsm_instance *fi, int event, void *arg)
case DEV_STATE_STARTWAIT:
fsm_newstate(fi, DEV_STATE_RUNNING);
printk(KERN_INFO
"%s: connected with remote side\n",
dev->name);
"%s: connected with remote side %s\n",
dev->name, privptr->conn->userid);
break;
case DEV_STATE_STOPWAIT:
printk(KERN_INFO
......@@ -1140,7 +1143,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
skb_pull(skb, NETIUCV_HDRLEN);
skb_trim(skb, skb->len - NETIUCV_HDRLEN);
}
printk(KERN_DEBUG "iucv_send returned %08x\n",
printk(KERN_INFO "iucv_send returned %08x\n",
rc);
} else {
if (copied)
......@@ -1612,7 +1615,7 @@ netiucv_remove_files(struct device *dev)
}
static int
netiucv_register_device(struct net_device *ndev, int ifno)
netiucv_register_device(struct net_device *ndev)
{
struct netiucv_priv *priv = ndev->priv;
struct device *dev = kmalloc(sizeof(struct device), GFP_KERNEL);
......@@ -1623,7 +1626,7 @@ netiucv_register_device(struct net_device *ndev, int ifno)
if (dev) {
memset(dev, 0, sizeof(struct device));
snprintf(dev->bus_id, BUS_ID_SIZE, "netiucv%x", ifno);
snprintf(dev->bus_id, BUS_ID_SIZE, "net%s", ndev->name);
dev->bus = &iucv_bus;
dev->parent = iucv_root;
/*
......@@ -1801,16 +1804,15 @@ netiucv_setup_netdevice(struct net_device *dev)
* Allocate and initialize everything of a net device.
*/
static struct net_device *
netiucv_init_netdevice(int ifno, char *username)
netiucv_init_netdevice(char *username)
{
struct netiucv_priv *privptr;
struct net_device *dev;
dev = alloc_netdev(sizeof(struct netiucv_priv), "",
dev = alloc_netdev(sizeof(struct netiucv_priv), "iucv%d",
netiucv_setup_netdevice);
if (!dev)
return NULL;
sprintf(dev->name, "iucv%d", ifno);
privptr = (struct netiucv_priv *)dev->priv;
privptr->fsm = init_fsm("netiucvdev", dev_state_names,
......@@ -1861,7 +1863,7 @@ conn_write(struct device_driver *drv, const char *buf, size_t count)
while (i<9)
username[i++] = ' ';
username[9] = '\0';
dev = netiucv_init_netdevice(ifno, username);
dev = netiucv_init_netdevice(username);
if (!dev) {
printk(KERN_WARNING
"netiucv: Could not allocate network device structure "
......@@ -1869,16 +1871,18 @@ conn_write(struct device_driver *drv, const char *buf, size_t count)
return -ENODEV;
}
if ((ret = netiucv_register_device(dev, ifno)))
goto out_free_ndev;
/* sysfs magic */
SET_NETDEV_DEV(dev, (struct device*)((struct netiucv_priv*)dev->priv)->dev);
if ((ret = register_netdev(dev))) {
netiucv_unregister_device((struct device*)((struct netiucv_priv*)dev->priv)->dev);
goto out_free_ndev;
}
if ((ret = netiucv_register_device(dev))) {
unregister_netdev(dev);
goto out_free_ndev;
}
/* sysfs magic */
SET_NETDEV_DEV(dev, (struct device*)((struct netiucv_priv*)dev->priv)->dev);
printk(KERN_INFO "%s: '%s'\n", dev->name, netiucv_printname(username));
ifno++;
return count;
......@@ -1891,6 +1895,61 @@ conn_write(struct device_driver *drv, const char *buf, size_t count)
DRIVER_ATTR(connection, 0200, NULL, conn_write);
static ssize_t
remove_write (struct device_driver *drv, const char *buf, size_t count)
{
struct iucv_connection **clist = &connections;
struct net_device *ndev;
struct netiucv_priv *priv;
struct device *dev;
char name[IFNAMSIZ];
char *p;
int i;
pr_debug("%s() called\n", __FUNCTION__);
if (count >= IFNAMSIZ)
count = IFNAMSIZ-1;
for (i=0, p=(char *)buf; i<count && *p; i++, p++) {
if ((*p == '\n') | (*p == ' ')) {
/* trailing lf, grr */
break;
} else {
name[i]=*p;
}
}
name[i] = '\0';
while (*clist) {
ndev = (*clist)->netdev;
priv = (struct netiucv_priv*)ndev->priv;
dev = priv->dev;
if (strncmp(name, ndev->name, count)) {
clist = &((*clist)->next);
continue;
}
if (ndev->flags & (IFF_UP | IFF_RUNNING)) {
printk(KERN_WARNING
"netiucv: net device %s active with peer %s\n",
ndev->name, priv->conn->userid);
printk(KERN_WARNING
"netiucv: %s cannot be removed\n",
ndev->name);
return -EBUSY;
}
unregister_netdev(ndev);
netiucv_unregister_device(dev);
return count;
}
printk(KERN_WARNING
"netiucv: net device %s unknown\n", name);
return -EINVAL;
}
DRIVER_ATTR(remove, 0200, NULL, remove_write);
static struct device_driver netiucv_driver = {
.name = "netiucv",
.bus = &iucv_bus,
......@@ -1899,7 +1958,7 @@ static struct device_driver netiucv_driver = {
static void
netiucv_banner(void)
{
char vbuf[] = "$Revision: 1.51 $";
char vbuf[] = "$Revision: 1.53 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
......@@ -1924,6 +1983,7 @@ netiucv_exit(void)
}
driver_remove_file(&netiucv_driver, &driver_attr_connection);
driver_remove_file(&netiucv_driver, &driver_attr_remove);
driver_unregister(&netiucv_driver);
printk(KERN_INFO "NETIUCV driver unloaded\n");
......@@ -1943,10 +2003,10 @@ netiucv_init(void)
/* Add entry for specifying connections. */
ret = driver_create_file(&netiucv_driver, &driver_attr_connection);
if (ret == 0)
if (ret == 0) {
ret = driver_create_file(&netiucv_driver, &driver_attr_remove);
netiucv_banner();
else {
} else {
printk(KERN_ERR "NETIUCV: failed to add driver attribute.\n");
driver_unregister(&netiucv_driver);
}
......
......@@ -23,7 +23,7 @@
#include "qeth_mpc.h"
#define VERSION_QETH_H "$Revision: 1.102 $"
#define VERSION_QETH_H "$Revision: 1.107 $"
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
......@@ -186,6 +186,8 @@ struct qeth_perf_stats {
__u64 outbound_start_time;
unsigned int outbound_cnt;
unsigned int outbound_time;
unsigned int inbound_do_qdio;
unsigned int outbound_do_qdio;
};
#endif /* CONFIG_QETH_PERF_STATS */
......@@ -279,7 +281,7 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
#define QETH_IN_BUF_COUNT_MAX 128
#define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
#define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \
((card)->qdio.in_buf_pool.buf_count / 4)
((card)->qdio.in_buf_pool.buf_count / 2)
/* buffers we have to be behind before we get a PCI */
#define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1)
......@@ -606,6 +608,7 @@ struct qeth_reply {
wait_queue_head_t wait_q;
int (*callback)(struct qeth_card *,struct qeth_reply *,unsigned long);
int seqno;
unsigned long offset;
int received;
int rc;
void *param;
......@@ -613,8 +616,10 @@ struct qeth_reply {
atomic_t refcnt;
};
struct qeth_card_info {
#define QETH_BROADCAST_WITH_ECHO 1
#define QETH_BROADCAST_WITHOUT_ECHO 2
struct qeth_card_info {
char if_name[IF_NAME_LEN];
unsigned short unit_addr2;
unsigned short cula;
......@@ -646,7 +651,6 @@ struct qeth_card_options {
enum qeth_checksum_types checksum_type;
int broadcast_mode;
int macaddr_mode;
int enable_takeover;
int fake_broadcast;
int add_hhlen;
int fake_ll;
......
......@@ -12,6 +12,11 @@
#ifndef __QETH_FS_H__
#define __QETH_FS_H__
#define VERSION_QETH_FS_H "$Revision: 1.8 $"
extern const char *VERSION_QETH_PROC_C;
extern const char *VERSION_QETH_SYS_C;
#ifdef CONFIG_PROC_FS
extern int
qeth_create_procfs_entries(void);
......
This diff is collapsed.
......@@ -11,6 +11,8 @@
#include <asm/cio.h>
#include "qeth_mpc.h"
const char *VERSION_QETH_MPC_C = "$Revision: 1.11 $";
unsigned char IDX_ACTIVATE_READ[]={
0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
0x19,0x01,0x01,0x80, 0x00,0x00,0x00,0x00,
......@@ -129,8 +131,7 @@ unsigned char IPA_PDU_HEADER[]={
0x00,0x00,0x00,0x14, 0x00,0x00,
(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd))/256,
(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd))%256,
0x10,0x00,0x00,0x01,
0x00,0x00,0x00,0x00,
0x10,0x00,0x00,0x01, 0x00,0x00,0x00,0x00,
0xc1,0x03,0x00,0x01, 0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, 0x00,0x24,
sizeof(struct qeth_ipa_cmd)/256,
......
......@@ -14,7 +14,9 @@
#include <asm/qeth.h>
#define VERSION_QETH_MPC_H "$Revision: 1.27 $"
#define VERSION_QETH_MPC_H "$Revision: 1.34 $"
extern const char *VERSION_QETH_MPC_C;
#define IPA_PDU_HEADER_SIZE 0x40
#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer+0x0e)
......@@ -33,6 +35,7 @@ extern unsigned char IPA_PDU_HEADER[];
#define OSA_ADDR_LEN 6
#define QETH_TIMEOUT (10 * HZ)
#define QETH_IPA_TIMEOUT (45 * HZ)
#define QETH_IDX_COMMAND_SEQNO -1
#define SR_INFO_LEN 16
......@@ -245,12 +248,28 @@ struct qeth_ipacmd_setassparms_hdr {
__u8 seq_no;
} __attribute__((packed));
struct qeth_arp_query_data {
__u16 request_bits;
__u16 reply_bits;
__u32 no_entries;
char data;
} __attribute__((packed));
/* used as parameter for arp_query reply */
struct qeth_arp_query_info {
__u32 udata_len;
__u32 udata_offset;
__u32 no_entries;
char *udata;
};
/* SETASSPARMS IPA Command: */
struct qeth_ipacmd_setassparms {
struct qeth_ipacmd_setassparms_hdr hdr;
union {
__u32 flags_32bit;
struct qeth_arp_cache_entry add_arp_entry;
struct qeth_arp_query_data query_arp;
__u8 ip[16];
} data;
} __attribute__ ((packed));
......@@ -277,16 +296,20 @@ struct qeth_change_addr {
__u8 addr[OSA_ADDR_LEN];
} __attribute__ ((packed));
struct qeth_ipacmd_setadpparms {
struct qeth_ipacmd_setadpparms_hdr {
__u32 supp_hw_cmds;
__u32 reserved1;
__u16 cmdlength;
__u16 reserved2;
__u32 command_code;
__u16 return_code;
__u8 frames_used_total;
__u8 frame_seq_no;
__u8 used_total;
__u8 seq_no;
__u32 reserved3;
} __attribute__ ((packed));
struct qeth_ipacmd_setadpparms {
struct qeth_ipacmd_setadpparms_hdr hdr;
union {
struct qeth_query_cmds_supp query_cmds_supp;
struct qeth_change_addr change_addr;
......@@ -357,36 +380,16 @@ enum qeth_ipa_arp_return_codes {
QETH_IPA_ARP_RC_Q_NO_DATA = 0x0008,
};
#define QETH_QARP_DATA_SIZE 3968
struct qeth_arp_query_data {
__u16 request_bits;
__u16 reply_bits;
__u32 no_entries;
char data[QETH_QARP_DATA_SIZE];
} __attribute__((packed));
/* used as parameter for arp_query reply */
struct qeth_arp_query_info {
__u32 udata_len;
__u32 udata_offset;
__u32 no_entries;
char *udata;
};
#define IPA_ARP_CMD_LEN (IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_arp_cmd))
#define QETH_ARP_CMD_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
#define QETH_SETASS_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
sizeof(struct qeth_ipacmd_setassparms_hdr))
#define QETH_IPA_ARP_DATA_POS(buffer) (buffer + IPA_PDU_HEADER_SIZE + \
QETH_ARP_CMD_BASE_LEN)
struct qeth_ipa_arp_cmd {
struct qeth_ipacmd_hdr ihdr;
struct qeth_ipacmd_setassparms_hdr shdr;
union {
struct qeth_arp_query_data query_arp;
} data;
} __attribute__((packed));
QETH_SETASS_BASE_LEN)
#define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
sizeof(struct qeth_ipacmd_setadpparms_hdr))
#define QETH_SNMP_SETADP_CMDLENGTH 16
#define QETH_ARP_DATA_SIZE 3968
#define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8)
/* Helper functions */
#define IS_IPA_REPLY(cmd) (cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST)
......
/*
*
* linux/drivers/s390/net/qeth_fs.c ($Revision: 1.5 $)
* linux/drivers/s390/net/qeth_fs.c ($Revision: 1.9 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to procfs.
......@@ -21,6 +21,8 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
const char *VERSION_QETH_PROC_C = "$Revision: 1.9 $";
/***** /proc/qeth *****/
#define QETH_PROCFILE_NAME "qeth"
static struct proc_dir_entry *qeth_procfile;
......@@ -91,13 +93,19 @@ qeth_get_router_str(struct qeth_card *card, int ipv)
return "pri";
else if (routing_type == SECONDARY_ROUTER)
return "sec";
else if (routing_type == MULTICAST_ROUTER)
else if (routing_type == MULTICAST_ROUTER) {
if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
return "mc+";
return "mc";
else if (routing_type == PRIMARY_CONNECTOR)
} else if (routing_type == PRIMARY_CONNECTOR) {
if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
return "p+c";
return "p.c";
else if (routing_type == SECONDARY_CONNECTOR)
} else if (routing_type == SECONDARY_CONNECTOR) {
if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
return "s+c";
return "s.c";
else if (routing_type == NO_ROUTER)
} else if (routing_type == NO_ROUTER)
return "no";
else
return "unk";
......@@ -244,14 +252,18 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
: 0
);
seq_printf(s, " Inbound time (in us) : %i\n"
" Inbound cnt : %i\n"
" Inbound count : %i\n"
" Inboud do_QDIO count : %i\n"
" Outbound time (in us, incl QDIO) : %i\n"
" Outbound cnt : %i\n"
" Outbound count : %i\n"
" Outbound do_QDIO count : %i\n"
" Watermarks L/H : %i/%i\n\n",
card->perf_stats.inbound_time,
card->perf_stats.inbound_cnt,
card->perf_stats.inbound_do_qdio,
card->perf_stats.outbound_time,
card->perf_stats.outbound_cnt,
card->perf_stats.outbound_do_qdio,
QETH_LOW_WATERMARK_PACK, QETH_HIGH_WATERMARK_PACK
);
......
/*
*
* linux/drivers/s390/net/qeth_sys.c ($Revision: 1.24 $)
* linux/drivers/s390/net/qeth_sys.c ($Revision: 1.29 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs.
......@@ -20,6 +20,8 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
const char *VERSION_QETH_SYS_C = "$Revision: 1.29 $";
/*****************************************************************************/
/* */
/* /sys-fs stuff UNDER DEVELOPMENT !!! */
......@@ -737,6 +739,10 @@ qeth_dev_ipato_enable_store(struct device *dev, const char *buf, size_t count)
if (!card)
return -EINVAL;
if ((card->state != CARD_STATE_DOWN) &&
(card->state != CARD_STATE_RECOVER))
return -EPERM;
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "toggle")){
card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
......
......@@ -12,15 +12,13 @@
#define __ASM_S390_IOCTL_H__
#include <linux/ioctl.h>
#define QETH_IOCTL_LETTER 'Q'
#define SIOC_QETH_ARP_SET_NO_ENTRIES _IOWR(QETH_IOCTL_LETTER, 1, int)
#define SIOC_QETH_ARP_QUERY_INFO _IOWR(QETH_IOCTL_LETTER, 2, int)
#define SIOC_QETH_ARP_ADD_ENTRY _IOWR(QETH_IOCTL_LETTER, 3, int)
#define SIOC_QETH_ARP_REMOVE_ENTRY _IOWR(QETH_IOCTL_LETTER, 4, int)
#define SIOC_QETH_ARP_FLUSH_CACHE _IOWR(QETH_IOCTL_LETTER, 5, int)
#define SIOC_QETH_ADP_SET_SNMP_CONTROL _IOWR(QETH_IOCTL_LETTER, 6, int)
#define SIOC_QETH_GET_CARD_TYPE _IOWR(QETH_IOCTL_LETTER, 7, int)
#define SIOC_QETH_ARP_SET_NO_ENTRIES (SIOCDEVPRIVATE)
#define SIOC_QETH_ARP_QUERY_INFO (SIOCDEVPRIVATE + 1)
#define SIOC_QETH_ARP_ADD_ENTRY (SIOCDEVPRIVATE + 2)
#define SIOC_QETH_ARP_REMOVE_ENTRY (SIOCDEVPRIVATE + 3)
#define SIOC_QETH_ARP_FLUSH_CACHE (SIOCDEVPRIVATE + 4)
#define SIOC_QETH_ADP_SET_SNMP_CONTROL (SIOCDEVPRIVATE + 5)
#define SIOC_QETH_GET_CARD_TYPE (SIOCDEVPRIVATE + 6)
struct qeth_arp_cache_entry {
__u8 macaddr[6];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment