Commit 2c81f2e4 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:
 - iucv: Make grab_param function SMP safe.
 - lcs: Fix null-pointer dereference after unsuccessful set_online.
 - qeth: Fix kmalloc flags in qeth_alloc_reply.
 - qeth: Show broadcase capability also in route4/6 sysfs attributes.
 - qeth: Remove debug code.
 - qeth: Add option to qetharp user space interface to strip unused
         fields from query arp records.
 - qeth: Add shortcut in outbound path for HiperSockets.
 - qeth: Add more info to qeth_perf_stats.
 - qeth: Add support for direct SNMP interface to OSA express cards.
parent b874ee07
/*
* $Id: iucv.c,v 1.30 2004/05/13 09:21:23 braunu Exp $
* $Id: iucv.c,v 1.32 2004/05/18 09:28:43 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.30 $
* RELEASE-TAG: IUCV lowlevel driver $Revision: 1.32 $
*
*/
......@@ -285,6 +285,7 @@ typedef struct {
iparml_set_mask p_set_mask;
} param;
atomic_t in_use;
__u32 res;
} __attribute__ ((aligned(8))) iucv_param;
#define PARAM_POOL_SIZE (PAGE_SIZE / sizeof(iucv_param))
......@@ -351,7 +352,7 @@ do { \
static void
iucv_banner(void)
{
char vbuf[] = "$Revision: 1.30 $";
char vbuf[] = "$Revision: 1.32 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
......@@ -469,17 +470,19 @@ iucv_exit(void)
static __inline__ iucv_param *
grab_param(void)
{
iucv_param *ret;
static int i = 0;
while (atomic_compare_and_swap(0, 1, &iucv_param_pool[i].in_use)) {
i++;
if (i >= PARAM_POOL_SIZE)
i = 0;
}
ret = &iucv_param_pool[i];
memset(&ret->param, 0, sizeof(ret->param));
return ret;
iucv_param *ptr;
static int hint = 0;
ptr = iucv_param_pool + hint;
do {
ptr++;
if (ptr >= iucv_param_pool + PARAM_POOL_SIZE)
ptr = iucv_param_pool;
} while (atomic_compare_and_swap(0, 1, &ptr->in_use));
hint = ptr - iucv_param_pool;
memset(&ptr->param, 0, sizeof(ptr->param));
return ptr;
}
/**
......
......@@ -11,7 +11,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*
* $Revision: 1.80 $ $Date: 2004/05/13 08:22:06 $
* $Revision: 1.81 $ $Date: 2004/05/14 13:54:33 $
*
* 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.80 $"
#define VERSION_LCS_C "$Revision: 1.81 $"
static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
static char debug_buffer[255];
......@@ -1898,8 +1898,10 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
lcs_setup_card(card);
rc = lcs_detect(card);
if (rc) {
LCS_DBF_TEXT(2, setup, "dtctfail");
PRINT_WARN("Detection of LCS card failed with return code "
"%d (0x%x)\n", rc, rc);
lcs_stopcard(card);
lcs_cleanup_card(card);
goto out;
}
if (card->dev) {
......@@ -1962,7 +1964,6 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
ccw_device_set_offline(card->read.ccwdev);
ccw_device_set_offline(card->write.ccwdev);
lcs_cleanup_card(card);
return -ENODEV;
}
......
......@@ -23,7 +23,7 @@
#include "qeth_mpc.h"
#define VERSION_QETH_H "$Revision: 1.107 $"
#define VERSION_QETH_H "$Revision: 1.108 $"
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
......@@ -179,15 +179,26 @@ struct qeth_perf_stats {
unsigned int sc_dp_p;
unsigned int sc_p_dp;
/* qdio_input_handler: number of times called, time spent in */
__u64 inbound_start_time;
unsigned int inbound_cnt;
unsigned int inbound_time;
/* qeth_send_packet: number of times called, time spent in */
__u64 outbound_start_time;
unsigned int outbound_cnt;
unsigned int outbound_time;
unsigned int inbound_do_qdio;
unsigned int outbound_do_qdio;
/* qdio_output_handler: number of times called, time spent in */
__u64 outbound_handler_start_time;
unsigned int outbound_handler_cnt;
unsigned int outbound_handler_time;
/* number of calls to and time spent in do_QDIO for inbound queue */
__u64 inbound_do_qdio_start_time;
unsigned int inbound_do_qdio_cnt;
unsigned int inbound_do_qdio_time;
/* number of calls to and time spent in do_QDIO for outbound queues */
__u64 outbound_do_qdio_start_time;
unsigned int outbound_do_qdio_cnt;
unsigned int outbound_do_qdio_time;
};
#endif /* CONFIG_QETH_PERF_STATS */
......@@ -714,6 +725,15 @@ struct qeth_card_list_struct {
extern struct qeth_card_list_struct qeth_card_list;
/*notifier list */
struct qeth_notify_list_struct {
struct list_head list;
struct task_struct *task;
int signum;
};
extern spinlock_t qeth_notify_lock;
extern struct list_head qeth_notify_list;
/*some helper functions*/
inline static __u8
......@@ -997,6 +1017,12 @@ qeth_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
extern void
qeth_del_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
extern int
qeth_notifier_register(struct task_struct *, int );
extern int
qeth_notifier_unregister(struct task_struct * );
extern void
qeth_schedule_recovery(struct qeth_card *);
......
This diff is collapsed.
......@@ -14,7 +14,7 @@
#include <asm/qeth.h>
#define VERSION_QETH_MPC_H "$Revision: 1.34 $"
#define VERSION_QETH_MPC_H "$Revision: 1.35 $"
extern const char *VERSION_QETH_MPC_C;
......@@ -258,6 +258,7 @@ struct qeth_arp_query_data {
/* used as parameter for arp_query reply */
struct qeth_arp_query_info {
__u32 udata_len;
__u16 mask_bits;
__u32 udata_offset;
__u32 no_entries;
char *udata;
......@@ -296,6 +297,29 @@ struct qeth_change_addr {
__u8 addr[OSA_ADDR_LEN];
} __attribute__ ((packed));
struct qeth_snmp_cmd {
__u8 token[16];
__u32 request;
__u32 interface;
__u32 returncode;
__u32 firmwarelevel;
__u32 seqno;
__u8 data;
} __attribute__ ((packed));
struct qeth_snmp_ureq_hdr {
__u32 data_len;
__u32 req_len;
__u32 reserved1;
__u32 reserved2;
} __attribute__ ((packed));
struct qeth_snmp_ureq {
struct qeth_snmp_ureq_hdr hdr;
struct qeth_snmp_cmd cmd;
} __attribute__((packed));
struct qeth_ipacmd_setadpparms_hdr {
__u32 supp_hw_cmds;
__u32 reserved1;
......@@ -313,6 +337,7 @@ struct qeth_ipacmd_setadpparms {
union {
struct qeth_query_cmds_supp query_cmds_supp;
struct qeth_change_addr change_addr;
struct qeth_snmp_cmd snmp;
__u32 mode;
} data;
} __attribute__ ((packed));
......
/*
*
* linux/drivers/s390/net/qeth_fs.c ($Revision: 1.9 $)
* linux/drivers/s390/net/qeth_fs.c ($Revision: 1.10 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to procfs.
......@@ -21,7 +21,7 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
const char *VERSION_QETH_PROC_C = "$Revision: 1.9 $";
const char *VERSION_QETH_PROC_C = "$Revision: 1.10 $";
/***** /proc/qeth *****/
#define QETH_PROCFILE_NAME "qeth"
......@@ -237,9 +237,11 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
card->perf_stats.bufs_sent_pack
);
seq_printf(s, " Packing state changes no pkg.->packing : %i/%i\n"
" Watermarks L/H : %i/%i\n"
" Current buffer usage (outbound q's) : "
"%i/%i/%i/%i\n\n",
card->perf_stats.sc_dp_p, card->perf_stats.sc_p_dp,
QETH_LOW_WATERMARK_PACK, QETH_HIGH_WATERMARK_PACK,
atomic_read(&card->qdio.out_qs[0]->used_buffers),
(card->qdio.no_out_queues > 1)?
atomic_read(&card->qdio.out_qs[1]->used_buffers)
......@@ -251,20 +253,26 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
atomic_read(&card->qdio.out_qs[3]->used_buffers)
: 0
);
seq_printf(s, " Inbound time (in us) : %i\n"
" Inbound count : %i\n"
" Inboud do_QDIO count : %i\n"
seq_printf(s, " Inbound handler time (in us) : %i\n"
" Inbound handler count : %i\n"
" Inbound do_QDIO time (in us) : %i\n"
" Inbound do_QDIO count : %i\n\n"
" Outbound handler time (in us) : %i\n"
" Outbound handler count : %i\n\n"
" Outbound time (in us, incl QDIO) : %i\n"
" Outbound count : %i\n"
" Outbound do_QDIO count : %i\n"
" Watermarks L/H : %i/%i\n\n",
" Outbound do_QDIO time (in us) : %i\n"
" Outbound do_QDIO count : %i\n",
card->perf_stats.inbound_time,
card->perf_stats.inbound_cnt,
card->perf_stats.inbound_do_qdio,
card->perf_stats.inbound_do_qdio_time,
card->perf_stats.inbound_do_qdio_cnt,
card->perf_stats.outbound_handler_time,
card->perf_stats.outbound_handler_cnt,
card->perf_stats.outbound_time,
card->perf_stats.outbound_cnt,
card->perf_stats.outbound_do_qdio,
QETH_LOW_WATERMARK_PACK, QETH_HIGH_WATERMARK_PACK
card->perf_stats.outbound_do_qdio_time,
card->perf_stats.outbound_do_qdio_cnt
);
return 0;
......
/*
*
* linux/drivers/s390/net/qeth_sys.c ($Revision: 1.29 $)
* linux/drivers/s390/net/qeth_sys.c ($Revision: 1.30 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs.
......@@ -20,7 +20,7 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
const char *VERSION_QETH_SYS_C = "$Revision: 1.29 $";
const char *VERSION_QETH_SYS_C = "$Revision: 1.30 $";
/*****************************************************************************/
/* */
......@@ -322,7 +322,8 @@ static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
qeth_dev_bufcnt_store);
static inline ssize_t
qeth_dev_route_show(struct qeth_routing_info *route, char *buf)
qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route,
char *buf)
{
switch (route->type) {
case PRIMARY_ROUTER:
......@@ -330,11 +331,20 @@ qeth_dev_route_show(struct qeth_routing_info *route, char *buf)
case SECONDARY_ROUTER:
return sprintf(buf, "%s\n", "secondary router");
case MULTICAST_ROUTER:
return sprintf(buf, "%s\n", "multicast router");
if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
return sprintf(buf, "%s\n", "multicast router+");
else
return sprintf(buf, "%s\n", "multicast router");
case PRIMARY_CONNECTOR:
return sprintf(buf, "%s\n", "primary connector");
if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
return sprintf(buf, "%s\n", "primary connector+");
else
return sprintf(buf, "%s\n", "primary connector");
case SECONDARY_CONNECTOR:
return sprintf(buf, "%s\n", "secondary connector");
if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
return sprintf(buf, "%s\n", "secondary connector+");
else
return sprintf(buf, "%s\n", "secondary connector");
default:
return sprintf(buf, "%s\n", "no");
}
......@@ -348,7 +358,7 @@ qeth_dev_route4_show(struct device *dev, char *buf)
if (!card)
return -EINVAL;
return qeth_dev_route_show(&card->options.route4, buf);
return qeth_dev_route_show(card, &card->options.route4, buf);
}
static inline ssize_t
......@@ -416,7 +426,7 @@ qeth_dev_route6_show(struct device *dev, char *buf)
if (!qeth_is_supported(card, IPA_IPV6))
return sprintf(buf, "%s\n", "n/a");
return qeth_dev_route_show(&card->options.route6, buf);
return qeth_dev_route_show(card, &card->options.route6, buf);
}
static ssize_t
......@@ -1432,22 +1442,31 @@ qeth_driver_group_store(struct device_driver *ddrv, const char *buf,
static DRIVER_ATTR(group, 0200, 0, qeth_driver_group_store);
static ssize_t
qeth_driver_snmp_register_show(struct device_driver *ddrv, char *buf)
{
/* TODO */
return 0;
}
static ssize_t
qeth_driver_snmp_register_store(struct device_driver *ddrv, const char *buf,
qeth_driver_notifier_register_store(struct device_driver *ddrv, const char *buf,
size_t count)
{
/* TODO */
int rc;
int signum;
char *tmp;
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "unregister")){
return qeth_notifier_unregister(current);
}
signum = simple_strtoul(buf, &tmp, 10);
if ((signum < 0) || (signum > 32)){
PRINT_WARN("Signal number %d is out of range\n", signum);
return -EINVAL;
}
if ((rc = qeth_notifier_register(current, signum)))
return rc;
return count;
}
static DRIVER_ATTR(snmp_register, 0644, qeth_driver_snmp_register_show,
qeth_driver_snmp_register_store);
static DRIVER_ATTR(notifier_register, 0644, 0,
qeth_driver_notifier_register_store);
int
qeth_create_driver_attributes(void)
......@@ -1458,7 +1477,7 @@ qeth_create_driver_attributes(void)
&driver_attr_group)))
return rc;
return driver_create_file(&qeth_ccwgroup_driver.driver,
&driver_attr_snmp_register);
&driver_attr_notifier_register);
}
void
......@@ -1467,5 +1486,5 @@ qeth_remove_driver_attributes(void)
driver_remove_file(&qeth_ccwgroup_driver.driver,
&driver_attr_group);
driver_remove_file(&qeth_ccwgroup_driver.driver,
&driver_attr_snmp_register);
&driver_attr_notifier_register);
}
......@@ -8,8 +8,8 @@
* Author(s): Thomas Spatzier <tspat@de.ibm.com>
*
*/
#ifndef __ASM_S390_IOCTL_H__
#define __ASM_S390_IOCTL_H__
#ifndef __ASM_S390_QETH_IOCTL_H__
#define __ASM_S390_QETH_IOCTL_H__
#include <linux/ioctl.h>
#define SIOC_QETH_ARP_SET_NO_ENTRIES (SIOCDEVPRIVATE)
......@@ -35,6 +35,13 @@ struct qeth_arp_qi_entry7 {
__u8 ipaddr[4];
} __attribute__((packed));
struct qeth_arp_qi_entry7_short {
__u8 macaddr_type;
__u8 ipaddr_type;
__u8 macaddr[6];
__u8 ipaddr[4];
} __attribute__((packed));
struct qeth_arp_qi_entry5 {
__u8 media_specific[32];
__u8 macaddr_type;
......@@ -42,6 +49,19 @@ struct qeth_arp_qi_entry5 {
__u8 ipaddr[4];
} __attribute__((packed));
struct qeth_arp_qi_entry5_short {
__u8 macaddr_type;
__u8 ipaddr_type;
__u8 ipaddr[4];
} __attribute__((packed));
/*
* can be set by user if no "media specific information" is wanted
* -> saves a lot of space in user space buffer
*/
#define QETH_QARP_STRIP_ENTRIES 0x8000
#define QETH_QARP_REQUEST_MASK 0x00ff
/* data sent to user space as result of query arp ioctl */
#define QETH_QARP_USER_DATA_SIZE 20000
#define QETH_QARP_MASK_OFFSET 4
......@@ -55,4 +75,4 @@ struct qeth_arp_query_user_data {
char *entries;
} __attribute__((packed));
#endif /* __ASM_S390_IOCTL_H__ */
#endif /* __ASM_S390_QETH_IOCTL_H__ */
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