summaryrefslogtreecommitdiff
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/dasd.c5
-rw-r--r--drivers/s390/block/dasd_devmap.c10
-rw-r--r--drivers/s390/block/dasd_int.h2
-rw-r--r--drivers/s390/block/dasd_proc.c16
-rw-r--r--drivers/s390/char/con3215.c5
-rw-r--r--drivers/s390/char/sclp_config.c17
-rw-r--r--drivers/s390/char/sclp_tty.c4
-rw-r--r--drivers/s390/char/sclp_vt220.c6
-rw-r--r--drivers/s390/char/tape_core.c31
-rw-r--r--drivers/s390/char/tape_proc.c9
-rw-r--r--drivers/s390/char/tty3270.c14
-rw-r--r--drivers/s390/char/vmlogrdr.c2
-rw-r--r--drivers/s390/cio/blacklist.c329
-rw-r--r--drivers/s390/cio/ccwgroup.c103
-rw-r--r--drivers/s390/cio/cio.c48
-rw-r--r--drivers/s390/cio/cio.h5
-rw-r--r--drivers/s390/cio/cio_debug.h6
-rw-r--r--drivers/s390/cio/cmf.c11
-rw-r--r--drivers/s390/cio/css.c14
-rw-r--r--drivers/s390/cio/device.c42
-rw-r--r--drivers/s390/cio/device_fsm.c54
-rw-r--r--drivers/s390/cio/device_id.c4
-rw-r--r--drivers/s390/cio/device_ops.c2
-rw-r--r--drivers/s390/cio/device_pgid.c24
-rw-r--r--drivers/s390/cio/qdio.c12
-rw-r--r--drivers/s390/kvm/kvm_virtio.c23
-rw-r--r--drivers/s390/net/cu3088.c20
-rw-r--r--drivers/s390/net/lcs.c3
-rw-r--r--drivers/s390/net/netiucv.c3
-rw-r--r--drivers/s390/net/qeth_core.h50
-rw-r--r--drivers/s390/net/qeth_core_main.c200
-rw-r--r--drivers/s390/net/qeth_l2_main.c30
-rw-r--r--drivers/s390/net/qeth_l3.h3
-rw-r--r--drivers/s390/net/qeth_l3_main.c30
-rw-r--r--drivers/s390/s390mach.c3
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c2
37 files changed, 588 insertions, 556 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index ac6d4d3218b3..8ba3f135da22 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -925,6 +925,8 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
struct dasd_ccw_req *cqr;
struct dasd_device *device;
+ if (!intparm)
+ return;
cqr = (struct dasd_ccw_req *) intparm;
if (cqr->status != DASD_CQR_IN_IO) {
MESSAGE(KERN_DEBUG,
@@ -976,17 +978,16 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
if (IS_ERR(irb)) {
switch (PTR_ERR(irb)) {
case -EIO:
- dasd_handle_killed_request(cdev, intparm);
break;
case -ETIMEDOUT:
printk(KERN_WARNING"%s(%s): request timed out\n",
__func__, cdev->dev.bus_id);
- //FIXME - dasd uses own timeout interface...
break;
default:
printk(KERN_WARNING"%s(%s): unknown error %ld\n",
__func__, cdev->dev.bus_id, PTR_ERR(irb));
}
+ dasd_handle_killed_request(cdev, intparm);
return;
}
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index f4fb40257348..d774e79476fe 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -86,10 +86,10 @@ static DEFINE_SPINLOCK(dasd_devmap_lock);
static struct list_head dasd_hashlists[256];
int dasd_max_devindex;
-static struct dasd_devmap *dasd_add_busid(char *, int);
+static struct dasd_devmap *dasd_add_busid(const char *, int);
static inline int
-dasd_hash_busid(char *bus_id)
+dasd_hash_busid(const char *bus_id)
{
int hash, i;
@@ -394,7 +394,7 @@ dasd_parse(void)
* devices.
*/
static struct dasd_devmap *
-dasd_add_busid(char *bus_id, int features)
+dasd_add_busid(const char *bus_id, int features)
{
struct dasd_devmap *devmap, *new, *tmp;
int hash;
@@ -430,7 +430,7 @@ dasd_add_busid(char *bus_id, int features)
* Find devmap for device with given bus_id.
*/
static struct dasd_devmap *
-dasd_find_busid(char *bus_id)
+dasd_find_busid(const char *bus_id)
{
struct dasd_devmap *devmap, *tmp;
int hash;
@@ -452,7 +452,7 @@ dasd_find_busid(char *bus_id)
* Check if busid has been added to the list of dasd ranges.
*/
int
-dasd_busid_known(char *bus_id)
+dasd_busid_known(const char *bus_id)
{
return IS_ERR(dasd_find_busid(bus_id)) ? -ENOENT : 0;
}
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 6c624bf44617..fb2f931cf844 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -598,7 +598,7 @@ struct dasd_device *dasd_device_from_cdev_locked(struct ccw_device *);
struct dasd_device *dasd_device_from_devindex(int);
int dasd_parse(void);
-int dasd_busid_known(char *);
+int dasd_busid_known(const char *);
/* externals in dasd_gendisk.c */
int dasd_gendisk_init(void);
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 556063e8f7a9..03c0e40a92ff 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -157,6 +157,7 @@ static int dasd_devices_open(struct inode *inode, struct file *file)
}
static const struct file_operations dasd_devices_file_ops = {
+ .owner = THIS_MODULE,
.open = dasd_devices_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -311,17 +312,16 @@ out_error:
int
dasd_proc_init(void)
{
- dasd_proc_root_entry = proc_mkdir("dasd", &proc_root);
+ dasd_proc_root_entry = proc_mkdir("dasd", NULL);
if (!dasd_proc_root_entry)
goto out_nodasd;
dasd_proc_root_entry->owner = THIS_MODULE;
- dasd_devices_entry = create_proc_entry("devices",
- S_IFREG | S_IRUGO | S_IWUSR,
- dasd_proc_root_entry);
+ dasd_devices_entry = proc_create("devices",
+ S_IFREG | S_IRUGO | S_IWUSR,
+ dasd_proc_root_entry,
+ &dasd_devices_file_ops);
if (!dasd_devices_entry)
goto out_nodevices;
- dasd_devices_entry->proc_fops = &dasd_devices_file_ops;
- dasd_devices_entry->owner = THIS_MODULE;
dasd_statistics_entry = create_proc_entry("statistics",
S_IFREG | S_IRUGO | S_IWUSR,
dasd_proc_root_entry);
@@ -335,7 +335,7 @@ dasd_proc_init(void)
out_nostatistics:
remove_proc_entry("devices", dasd_proc_root_entry);
out_nodevices:
- remove_proc_entry("dasd", &proc_root);
+ remove_proc_entry("dasd", NULL);
out_nodasd:
return -ENOENT;
}
@@ -345,5 +345,5 @@ dasd_proc_exit(void)
{
remove_proc_entry("devices", dasd_proc_root_entry);
remove_proc_entry("statistics", dasd_proc_root_entry);
- remove_proc_entry("dasd", &proc_root);
+ remove_proc_entry("dasd", NULL);
}
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 0e1f35c9ed9d..3e5653c92f4b 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -982,15 +982,16 @@ tty3215_write(struct tty_struct * tty,
/*
* Put character routine for 3215 ttys
*/
-static void
+static int
tty3215_put_char(struct tty_struct *tty, unsigned char ch)
{
struct raw3215_info *raw;
if (!tty)
- return;
+ return 0;
raw = (struct raw3215_info *) tty->driver_data;
raw3215_putchar(raw, ch);
+ return 1;
}
static void
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index b8f35bc52b7b..9e784d5f7f57 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -10,6 +10,7 @@
#include <linux/cpu.h>
#include <linux/sysdev.h>
#include <linux/workqueue.h>
+#include <asm/smp.h>
#include "sclp.h"
#define TAG "sclp_config: "
@@ -19,9 +20,11 @@ struct conf_mgm_data {
u8 ev_qualifier;
} __attribute__((packed));
+#define EV_QUAL_CPU_CHANGE 1
#define EV_QUAL_CAP_CHANGE 3
static struct work_struct sclp_cpu_capability_work;
+static struct work_struct sclp_cpu_change_work;
static void sclp_cpu_capability_notify(struct work_struct *work)
{
@@ -37,13 +40,24 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
put_online_cpus();
}
+static void sclp_cpu_change_notify(struct work_struct *work)
+{
+ smp_rescan_cpus();
+}
+
static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
{
struct conf_mgm_data *cdata;
cdata = (struct conf_mgm_data *)(evbuf + 1);
- if (cdata->ev_qualifier == EV_QUAL_CAP_CHANGE)
+ switch (cdata->ev_qualifier) {
+ case EV_QUAL_CPU_CHANGE:
+ schedule_work(&sclp_cpu_change_work);
+ break;
+ case EV_QUAL_CAP_CHANGE:
schedule_work(&sclp_cpu_capability_work);
+ break;
+ }
}
static struct sclp_register sclp_conf_register =
@@ -57,6 +71,7 @@ static int __init sclp_conf_init(void)
int rc;
INIT_WORK(&sclp_cpu_capability_work, sclp_cpu_capability_notify);
+ INIT_WORK(&sclp_cpu_change_work, sclp_cpu_change_notify);
rc = sclp_register(&sclp_conf_register);
if (rc) {
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index e3b3d390b4a3..40b11521cd20 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -412,14 +412,14 @@ sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
* - including previous characters from sclp_tty_put_char() and strings from
* sclp_write() without final '\n' - will be written.
*/
-static void
+static int
sclp_tty_put_char(struct tty_struct *tty, unsigned char ch)
{
sclp_tty_chars[sclp_tty_chars_count++] = ch;
if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) {
sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
sclp_tty_chars_count = 0;
- }
+ } return 1;
}
/*
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index ed507594e62b..35707c04e613 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -524,11 +524,15 @@ sclp_vt220_close(struct tty_struct *tty, struct file *filp)
* NOTE: include/linux/tty_driver.h specifies that a character should be
* ignored if there is no room in the queue. This driver implements a different
* semantic in that it will block when there is no more room left.
+ *
+ * FIXME: putchar can currently be called from BH and other non blocking
+ * handlers so this semantic isn't a good idea.
*/
-static void
+static int
sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch)
{
__sclp_vt220_write(&ch, 1, 0, 0, 1);
+ return 1;
}
/*
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 7ad8cf157641..76e44eb7c47f 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -76,32 +76,9 @@ const char *tape_op_verbose[TO_SIZE] =
[TO_KEKL_QUERY] = "KLQ",[TO_RDC] = "RDC",
};
-static int
-busid_to_int(char *bus_id)
+static int devid_to_int(struct ccw_dev_id *dev_id)
{
- int dec;
- int d;
- char * s;
-
- for(s = bus_id, d = 0; *s != '\0' && *s != '.'; s++)
- d = (d * 10) + (*s - '0');
- dec = d;
- for(s++, d = 0; *s != '\0' && *s != '.'; s++)
- d = (d * 10) + (*s - '0');
- dec = (dec << 8) + d;
-
- for(s++; *s != '\0'; s++) {
- if (*s >= '0' && *s <= '9') {
- d = *s - '0';
- } else if (*s >= 'a' && *s <= 'f') {
- d = *s - 'a' + 10;
- } else {
- d = *s - 'A' + 10;
- }
- dec = (dec << 4) + d;
- }
-
- return dec;
+ return dev_id->devno + (dev_id->ssid << 16);
}
/*
@@ -551,6 +528,7 @@ tape_generic_probe(struct ccw_device *cdev)
{
struct tape_device *device;
int ret;
+ struct ccw_dev_id dev_id;
device = tape_alloc_device();
if (IS_ERR(device))
@@ -565,7 +543,8 @@ tape_generic_probe(struct ccw_device *cdev)
cdev->dev.driver_data = device;
cdev->handler = __tape_do_irq;
device->cdev = cdev;
- device->cdev_id = busid_to_int(cdev->dev.bus_id);
+ ccw_device_get_id(cdev, &dev_id);
+ device->cdev_id = devid_to_int(&dev_id);
PRINT_INFO("tape device %s found\n", cdev->dev.bus_id);
return ret;
}
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
index c9b96d51b28f..e7c888c14e71 100644
--- a/drivers/s390/char/tape_proc.c
+++ b/drivers/s390/char/tape_proc.c
@@ -111,6 +111,7 @@ static int tape_proc_open(struct inode *inode, struct file *file)
static const struct file_operations tape_proc_ops =
{
+ .owner = THIS_MODULE,
.open = tape_proc_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -124,14 +125,12 @@ void
tape_proc_init(void)
{
tape_proc_devices =
- create_proc_entry ("tapedevices", S_IFREG | S_IRUGO | S_IWUSR,
- &proc_root);
+ proc_create("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, NULL,
+ &tape_proc_ops);
if (tape_proc_devices == NULL) {
PRINT_WARN("tape: Cannot register procfs entry tapedevices\n");
return;
}
- tape_proc_devices->proc_fops = &tape_proc_ops;
- tape_proc_devices->owner = THIS_MODULE;
}
/*
@@ -141,5 +140,5 @@ void
tape_proc_cleanup(void)
{
if (tape_proc_devices != NULL)
- remove_proc_entry ("tapedevices", &proc_root);
+ remove_proc_entry ("tapedevices", NULL);
}
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 70b1980a08b6..5043150019ac 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -965,8 +965,7 @@ tty3270_write_room(struct tty_struct *tty)
* Insert character into the screen at the current position with the
* current color and highlight. This function does NOT do cursor movement.
*/
-static void
-tty3270_put_character(struct tty3270 *tp, char ch)
+static void tty3270_put_character(struct tty3270 *tp, char ch)
{
struct tty3270_line *line;
struct tty3270_cell *cell;
@@ -1611,16 +1610,15 @@ tty3270_write(struct tty_struct * tty,
/*
* Put single characters to the ttys character buffer
*/
-static void
-tty3270_put_char(struct tty_struct *tty, unsigned char ch)
+static int tty3270_put_char(struct tty_struct *tty, unsigned char ch)
{
struct tty3270 *tp;
tp = tty->driver_data;
- if (!tp)
- return;
- if (tp->char_count < TTY3270_CHAR_BUF_SIZE)
- tp->char_buf[tp->char_count++] = ch;
+ if (!tp || tp->char_count >= TTY3270_CHAR_BUF_SIZE)
+ return 0;
+ tp->char_buf[tp->char_count++] = ch;
+ return 1;
}
/*
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index d364e0bfae12..e8487347e4d4 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -858,7 +858,7 @@ static int __init vmlogrdr_init(void)
for (i=0; i < MAXMINOR; ++i ) {
sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL);
if (!sys_ser[i].buffer) {
- rc = ENOMEM;
+ rc = -ENOMEM;
break;
}
sys_ser[i].current_position = sys_ser[i].buffer;
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index e8597ec92247..a4a5f2efea48 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -43,164 +43,169 @@ typedef enum {add, free} range_action;
* Function: blacklist_range
* (Un-)blacklist the devices from-to
*/
-static void
-blacklist_range (range_action action, unsigned int from, unsigned int to,
- unsigned int ssid)
+static int blacklist_range(range_action action, unsigned int from_ssid,
+ unsigned int to_ssid, unsigned int from,
+ unsigned int to, int msgtrigger)
{
- if (!to)
- to = from;
-
- if (from > to || to > __MAX_SUBCHANNEL || ssid > __MAX_SSID) {
- printk (KERN_WARNING "cio: Invalid blacklist range "
- "0.%x.%04x to 0.%x.%04x, skipping\n",
- ssid, from, ssid, to);
- return;
+ if ((from_ssid > to_ssid) || ((from_ssid == to_ssid) && (from > to))) {
+ if (msgtrigger)
+ printk(KERN_WARNING "cio: Invalid cio_ignore range "
+ "0.%x.%04x-0.%x.%04x\n", from_ssid, from,
+ to_ssid, to);
+ return 1;
}
- for (; from <= to; from++) {
+
+ while ((from_ssid < to_ssid) || ((from_ssid == to_ssid) &&
+ (from <= to))) {
if (action == add)
- set_bit (from, bl_dev[ssid]);
+ set_bit(from, bl_dev[from_ssid]);
else
- clear_bit (from, bl_dev[ssid]);
+ clear_bit(from, bl_dev[from_ssid]);
+ from++;
+ if (from > __MAX_SUBCHANNEL) {
+ from_ssid++;
+ from = 0;
+ }
}
+
+ return 0;
}
-/*
- * Function: blacklist_busid
- * Get devno/busid from given string.
- * Shamelessly grabbed from dasd_devmap.c.
- */
-static int
-blacklist_busid(char **str, int *id0, int *ssid, int *devno)
+static int pure_hex(char **cp, unsigned int *val, int min_digit,
+ int max_digit, int max_val)
{
- int val, old_style;
- char *sav;
+ int diff;
+ unsigned int value;
- sav = *str;
+ diff = 0;
+ *val = 0;
- /* check for leading '0x' */
- old_style = 0;
- if ((*str)[0] == '0' && (*str)[1] == 'x') {
- *str += 2;
- old_style = 1;
- }
- if (!isxdigit((*str)[0])) /* We require at least one hex digit */
- goto confused;
- val = simple_strtoul(*str, str, 16);
- if (old_style || (*str)[0] != '.') {
- *id0 = *ssid = 0;
- if (val < 0 || val > 0xffff)
- goto confused;
- *devno = val;
- if ((*str)[0] != ',' && (*str)[0] != '-' &&
- (*str)[0] != '\n' && (*str)[0] != '\0')
- goto confused;
- return 0;
+ while (isxdigit(**cp) && (diff <= max_digit)) {
+
+ if (isdigit(**cp))
+ value = **cp - '0';
+ else
+ value = tolower(**cp) - 'a' + 10;
+ *val = *val * 16 + value;
+ (*cp)++;
+ diff++;
}
- /* New style x.y.z busid */
- if (val < 0 || val > 0xff)
- goto confused;
- *id0 = val;
- (*str)++;
- if (!isxdigit((*str)[0])) /* We require at least one hex digit */
- goto confused;
- val = simple_strtoul(*str, str, 16);
- if (val < 0 || val > 0xff || (*str)++[0] != '.')
- goto confused;
- *ssid = val;
- if (!isxdigit((*str)[0])) /* We require at least one hex digit */
- goto confused;
- val = simple_strtoul(*str, str, 16);
- if (val < 0 || val > 0xffff)
- goto confused;
- *devno = val;
- if ((*str)[0] != ',' && (*str)[0] != '-' &&
- (*str)[0] != '\n' && (*str)[0] != '\0')
- goto confused;
+
+ if ((diff < min_digit) || (diff > max_digit) || (*val > max_val))
+ return 1;
+
return 0;
-confused:
- strsep(str, ",\n");
- printk(KERN_WARNING "cio: Invalid cio_ignore parameter '%s'\n", sav);
- return 1;
}
-static int
-blacklist_parse_parameters (char *str, range_action action)
+static int parse_busid(char *str, int *cssid, int *ssid, int *devno,
+ int msgtrigger)
{
- int from, to, from_id0, to_id0, from_ssid, to_ssid;
-
- while (*str != 0 && *str != '\n') {
- range_action ra = action;
- while(*str == ',')
- str++;
- if (*str == '!') {
- ra = !action;
- ++str;
+ char *str_work;
+ int val, rc, ret;
+
+ rc = 1;
+
+ if (*str == '\0')
+ goto out;
+
+ /* old style */
+ str_work = str;
+ val = simple_strtoul(str, &str_work, 16);
+
+ if (*str_work == '\0') {
+ if (val <= __MAX_SUBCHANNEL) {
+ *devno = val;
+ *ssid = 0;
+ *cssid = 0;
+ rc = 0;
}
+ goto out;
+ }
- /*
- * Since we have to parse the proc commands and the
- * kernel arguments we have to check four cases
- */
- if (strncmp(str,"all,",4) == 0 || strcmp(str,"all") == 0 ||
- strncmp(str,"all\n",4) == 0 || strncmp(str,"all ",4) == 0) {
- int j;
-
- str += 3;
- for (j=0; j <= __MAX_SSID; j++)
- blacklist_range(ra, 0, __MAX_SUBCHANNEL, j);
- } else {
- int rc;
+ /* new style */
+ str_work = str;
+ ret = pure_hex(&str_work, cssid, 1, 2, __MAX_CSSID);
+ if (ret || (str_work[0] != '.'))
+ goto out;
+ str_work++;
+ ret = pure_hex(&str_work, ssid, 1, 1, __MAX_SSID);
+ if (ret || (str_work[0] != '.'))
+ goto out;
+ str_work++;
+ ret = pure_hex(&str_work, devno, 4, 4, __MAX_SUBCHANNEL);
+ if (ret || (str_work[0] != '\0'))
+ goto out;
+
+ rc = 0;
+out:
+ if (rc && msgtrigger)
+ printk(KERN_WARNING "cio: Invalid cio_ignore device '%s'\n",
+ str);
+
+ return rc;
+}
- rc = blacklist_busid(&str, &from_id0,
- &from_ssid, &from);
- if (rc)
- continue;
- to = from;
- to_id0 = from_id0;
- to_ssid = from_ssid;
- if (*str == '-') {
- str++;
- rc = blacklist_busid(&str, &to_id0,
- &to_ssid, &to);
- if (rc)
- continue;
- }
- if (*str == '-') {
- printk(KERN_WARNING "cio: invalid cio_ignore "
- "parameter '%s'\n",
- strsep(&str, ",\n"));
- continue;
- }
- if ((from_id0 != to_id0) ||
- (from_ssid != to_ssid)) {
- printk(KERN_WARNING "cio: invalid cio_ignore "
- "range %x.%x.%04x-%x.%x.%04x\n",
- from_id0, from_ssid, from,
- to_id0, to_ssid, to);
- continue;
+static int blacklist_parse_parameters(char *str, range_action action,
+ int msgtrigger)
+{
+ int from_cssid, to_cssid, from_ssid, to_ssid, from, to;
+ int rc, totalrc;
+ char *parm;
+ range_action ra;
+
+ totalrc = 0;
+
+ while ((parm = strsep(&str, ","))) {
+ rc = 0;
+ ra = action;
+ if (*parm == '!') {
+ if (ra == add)
+ ra = free;
+ else
+ ra = add;
+ parm++;
+ }
+ if (strcmp(parm, "all") == 0) {
+ from_cssid = 0;
+ from_ssid = 0;
+ from = 0;
+ to_cssid = __MAX_CSSID;
+ to_ssid = __MAX_SSID;
+ to = __MAX_SUBCHANNEL;
+ } else {
+ rc = parse_busid(strsep(&parm, "-"), &from_cssid,
+ &from_ssid, &from, msgtrigger);
+ if (!rc) {
+ if (parm != NULL)
+ rc = parse_busid(parm, &to_cssid,
+ &to_ssid, &to,
+ msgtrigger);
+ else {
+ to_cssid = from_cssid;
+ to_ssid = from_ssid;
+ to = from;
+ }
}
- blacklist_range (ra, from, to, to_ssid);
}
+ if (!rc) {
+ rc = blacklist_range(ra, from_ssid, to_ssid, from, to,
+ msgtrigger);
+ if (rc)
+ totalrc = 1;
+ } else
+ totalrc = 1;
}
- return 1;
+
+ return totalrc;
}
-/* Parsing the commandline for blacklist parameters, e.g. to blacklist
- * bus ids 0.0.1234, 0.0.1235 and 0.0.1236, you could use any of:
- * - cio_ignore=1234-1236
- * - cio_ignore=0x1234-0x1235,1236
- * - cio_ignore=0x1234,1235-1236
- * - cio_ignore=1236 cio_ignore=1234-0x1236
- * - cio_ignore=1234 cio_ignore=1236 cio_ignore=0x1235
- * - cio_ignore=0.0.1234-0.0.1236
- * - cio_ignore=0.0.1234,0x1235,1236
- * - ...
- */
static int __init
blacklist_setup (char *str)
{
CIO_MSG_EVENT(6, "Reading blacklist parameters\n");
- return blacklist_parse_parameters (str, add);
+ if (blacklist_parse_parameters(str, add, 1))
+ return 0;
+ return 1;
}
__setup ("cio_ignore=", blacklist_setup);
@@ -224,27 +229,23 @@ is_blacklisted (int ssid, int devno)
* Function: blacklist_parse_proc_parameters
* parse the stuff which is piped to /proc/cio_ignore
*/
-static void
-blacklist_parse_proc_parameters (char *buf)
+static int blacklist_parse_proc_parameters(char *buf)
{
- if (strncmp (buf, "free ", 5) == 0) {
- blacklist_parse_parameters (buf + 5, free);
- } else if (strncmp (buf, "add ", 4) == 0) {
- /*
- * We don't need to check for known devices since
- * css_probe_device will handle this correctly.
- */
- blacklist_parse_parameters (buf + 4, add);
- } else {
- printk (KERN_WARNING "cio: cio_ignore: Parse error; \n"
- KERN_WARNING "try using 'free all|<devno-range>,"
- "<devno-range>,...'\n"
- KERN_WARNING "or 'add <devno-range>,"
- "<devno-range>,...'\n");
- return;
- }
+ int rc;
+ char *parm;
+
+ parm = strsep(&buf, " ");
+
+ if (strcmp("free", parm) == 0)
+ rc = blacklist_parse_parameters(buf, free, 0);
+ else if (strcmp("add", parm) == 0)
+ rc = blacklist_parse_parameters(buf, add, 0);
+ else
+ return 1;
css_schedule_reprobe();
+
+ return rc;
}
/* Iterator struct for all devices. */
@@ -328,6 +329,8 @@ cio_ignore_write(struct file *file, const char __user *user_buf,
size_t user_len, loff_t *offset)
{
char *buf;
+ size_t i;
+ ssize_t rc, ret;
if (*offset)
return -EINVAL;
@@ -336,16 +339,27 @@ cio_ignore_write(struct file *file, const char __user *user_buf,
buf = vmalloc (user_len + 1); /* maybe better use the stack? */
if (buf == NULL)
return -ENOMEM;
+ memset(buf, 0, user_len + 1);
+
if (strncpy_from_user (buf, user_buf, user_len) < 0) {
- vfree (buf);
- return -EFAULT;
+ rc = -EFAULT;
+ goto out_free;
}
- buf[user_len] = '\0';
- blacklist_parse_proc_parameters (buf);
+ i = user_len - 1;
+ while ((i >= 0) && (isspace(buf[i]) || (buf[i] == 0))) {
+ buf[i] = '\0';
+ i--;
+ }
+ ret = blacklist_parse_proc_parameters(buf);
+ if (ret)
+ rc = -EINVAL;
+ else
+ rc = user_len;
+out_free:
vfree (buf);
- return user_len;
+ return rc;
}
static const struct seq_operations cio_ignore_proc_seq_ops = {
@@ -374,13 +388,10 @@ cio_ignore_proc_init (void)
{
struct proc_dir_entry *entry;
- entry = create_proc_entry ("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR,
- &proc_root);
+ entry = proc_create("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR, NULL,
+ &cio_ignore_proc_fops);
if (!entry)
return -ENOENT;
-
- entry->proc_fops = &cio_ignore_proc_fops;
-
return 0;
}
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index fe1ad1722158..26a930e832bd 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -152,44 +152,89 @@ __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
return 0;
}
+static int __get_next_bus_id(const char **buf, char *bus_id)
+{
+ int rc, len;
+ char *start, *end;
+
+ start = (char *)*buf;
+ end = strchr(start, ',');
+ if (!end) {
+ /* Last entry. Strip trailing newline, if applicable. */
+ end = strchr(start, '\n');
+ if (end)
+ *end = '\0';
+ len = strlen(start) + 1;
+ } else {
+ len = end - start + 1;
+ end++;
+ }
+ if (len < BUS_ID_SIZE) {
+ strlcpy(bus_id, start, len);
+ rc = 0;
+ } else
+ rc = -EINVAL;
+ *buf = end;
+ return rc;
+}
+
+static int __is_valid_bus_id(char bus_id[BUS_ID_SIZE])
+{
+ int cssid, ssid, devno;
+
+ /* Must be of form %x.%x.%04x */
+ if (sscanf(bus_id, "%x.%1x.%04x", &cssid, &ssid, &devno) != 3)
+ return 0;
+ return 1;
+}
+
/**
- * ccwgroup_create() - create and register a ccw group device
+ * ccwgroup_create_from_string() - create and register a ccw group device
* @root: parent device for the new device
* @creator_id: identifier of creating driver
* @cdrv: ccw driver of slave devices
- * @argc: number of slave devices
- * @argv: bus ids of slave devices
+ * @num_devices: number of slave devices
+ * @buf: buffer containing comma separated bus ids of slave devices
*
* Create and register a new ccw group device as a child of @root. Slave
- * devices are obtained from the list of bus ids given in @argv[] and must all
+ * devices are obtained from the list of bus ids given in @buf and must all
* belong to @cdrv.
* Returns:
* %0 on success and an error code on failure.
* Context:
* non-atomic
*/
-int ccwgroup_create(struct device *root, unsigned int creator_id,
- struct ccw_driver *cdrv, int argc, char *argv[])
+int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
+ struct ccw_driver *cdrv, int num_devices,
+ const char *buf)
{
struct ccwgroup_device *gdev;
- int i;
- int rc;
+ int rc, i;
+ char tmp_bus_id[BUS_ID_SIZE];
+ const char *curr_buf;
- if (argc > 256) /* disallow dumb users */
- return -EINVAL;
-
- gdev = kzalloc(sizeof(*gdev) + argc*sizeof(gdev->cdev[0]), GFP_KERNEL);
+ gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]),
+ GFP_KERNEL);
if (!gdev)
return -ENOMEM;
atomic_set(&gdev->onoff, 0);
mutex_init(&gdev->reg_mutex);
mutex_lock(&gdev->reg_mutex);
- for (i = 0; i < argc; i++) {
- gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]);
-
- /* all devices have to be of the same type in
- * order to be grouped */
+ curr_buf = buf;
+ for (i = 0; i < num_devices && curr_buf; i++) {
+ rc = __get_next_bus_id(&curr_buf, tmp_bus_id);
+ if (rc != 0)
+ goto error;
+ if (!__is_valid_bus_id(tmp_bus_id)) {
+ rc = -EINVAL;
+ goto error;
+ }
+ gdev->cdev[i] = get_ccwdev_by_busid(cdrv, tmp_bus_id);
+ /*
+ * All devices have to be of the same type in
+ * order to be grouped.
+ */
if (!gdev->cdev[i]
|| gdev->cdev[i]->id.driver_info !=
gdev->cdev[0]->id.driver_info) {
@@ -203,9 +248,18 @@ int ccwgroup_create(struct device *root, unsigned int creator_id,
}
dev_set_drvdata(&gdev->cdev[i]->dev, gdev);
}
-
+ /* Check for sufficient number of bus ids. */
+ if (i < num_devices && !curr_buf) {
+ rc = -EINVAL;
+ goto error;
+ }
+ /* Check for trailing stuff. */
+ if (i == num_devices && strlen(curr_buf) > 0) {
+ rc = -EINVAL;
+ goto error;
+ }
gdev->creator_id = creator_id;
- gdev->count = argc;
+ gdev->count = num_devices;
gdev->dev.bus = &ccwgroup_bus_type;
gdev->dev.parent = root;
gdev->dev.release = ccwgroup_release;
@@ -233,7 +287,7 @@ int ccwgroup_create(struct device *root, unsigned int creator_id,
device_remove_file(&gdev->dev, &dev_attr_ungroup);
device_unregister(&gdev->dev);
error:
- for (i = 0; i < argc; i++)
+ for (i = 0; i < num_devices; i++)
if (gdev->cdev[i]) {
if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev)
dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
@@ -243,6 +297,7 @@ error:
put_device(&gdev->dev);
return rc;
}
+EXPORT_SYMBOL(ccwgroup_create_from_string);
static int __init
init_ccwgroup (void)
@@ -318,7 +373,7 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
{
struct ccwgroup_device *gdev;
struct ccwgroup_driver *gdrv;
- unsigned int value;
+ unsigned long value;
int ret;
gdev = to_ccwgroupdev(dev);
@@ -329,7 +384,9 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
if (!try_module_get(gdrv->owner))
return -EINVAL;
- value = simple_strtoul(buf, NULL, 0);
+ ret = strict_strtoul(buf, 0, &value);
+ if (ret)
+ goto out;
ret = count;
if (value == 1)
ccwgroup_set_online(gdev);
@@ -337,6 +394,7 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
ccwgroup_set_offline(gdev);
else
ret = -EINVAL;
+out:
module_put(gdrv->owner);
return ret;
}
@@ -518,6 +576,5 @@ void ccwgroup_remove_ccwdev(struct ccw_device *cdev)
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(ccwgroup_driver_register);
EXPORT_SYMBOL(ccwgroup_driver_unregister);
-EXPORT_SYMBOL(ccwgroup_create);
EXPORT_SYMBOL(ccwgroup_probe_ccwdev);
EXPORT_SYMBOL(ccwgroup_remove_ccwdev);
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 23ffcc4768a7..82c6a2d45128 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -39,23 +39,6 @@ debug_info_t *cio_debug_msg_id;
debug_info_t *cio_debug_trace_id;
debug_info_t *cio_debug_crw_id;
-int cio_show_msg;
-
-static int __init
-cio_setup (char *parm)
-{
- if (!strcmp (parm, "yes"))
- cio_show_msg = 1;
- else if (!strcmp (parm, "no"))
- cio_show_msg = 0;
- else
- printk(KERN_ERR "cio: cio_setup: "
- "invalid cio_msg parameter '%s'", parm);
- return 1;
-}
-
-__setup ("cio_msg=", cio_setup);
-
/*
* Function: cio_debug_init
* Initializes three debug logs for common I/O:
@@ -166,7 +149,7 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
stsch (sch->schid, &sch->schib);
- CIO_MSG_EVENT(0, "cio_start: 'not oper' status for "
+ CIO_MSG_EVENT(2, "cio_start: 'not oper' status for "
"subchannel 0.%x.%04x!\n", sch->schid.ssid,
sch->schid.sch_no);
sprintf(dbf_text, "no%s", sch->dev.bus_id);
@@ -407,8 +390,7 @@ cio_modify (struct subchannel *sch)
/*
* Enable subchannel.
*/
-int cio_enable_subchannel(struct subchannel *sch, unsigned int isc,
- u32 intparm)
+int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
{
char dbf_txt[15];
int ccode;
@@ -426,7 +408,7 @@ int cio_enable_subchannel(struct subchannel *sch, unsigned int isc,
for (retry = 5, ret = 0; retry > 0; retry--) {
sch->schib.pmcw.ena = 1;
- sch->schib.pmcw.isc = isc;
+ sch->schib.pmcw.isc = sch->isc;
sch->schib.pmcw.intparm = intparm;
ret = cio_modify(sch);
if (ret == -ENODEV)
@@ -568,10 +550,9 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
* ... just being curious we check for non I/O subchannels
*/
if (sch->st != 0) {
- CIO_DEBUG(KERN_INFO, 0,
- "Subchannel 0.%x.%04x reports "
- "non-I/O subchannel type %04X\n",
- sch->schid.ssid, sch->schid.sch_no, sch->st);
+ CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports "
+ "non-I/O subchannel type %04X\n",
+ sch->schid.ssid, sch->schid.sch_no, sch->st);
/* We stop here for non-io subchannels. */
err = sch->st;
goto out;
@@ -589,7 +570,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
* This device must not be known to Linux. So we simply
* say that there is no device and return ENODEV.
*/
- CIO_MSG_EVENT(4, "Blacklisted device detected "
+ CIO_MSG_EVENT(6, "Blacklisted device detected "
"at devno %04X, subchannel set %x\n",
sch->schib.pmcw.dev, sch->schid.ssid);
err = -ENODEV;
@@ -600,23 +581,21 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
else
sch->opm = chp_get_sch_opm(sch);
sch->lpm = sch->schib.pmcw.pam & sch->opm;
+ sch->isc = 3;
- CIO_DEBUG(KERN_INFO, 0,
- "Detected device %04x on subchannel 0.%x.%04X"
- " - PIM = %02X, PAM = %02X, POM = %02X\n",
- sch->schib.pmcw.dev, sch->schid.ssid,
- sch->schid.sch_no, sch->schib.pmcw.pim,
- sch->schib.pmcw.pam, sch->schib.pmcw.pom);
+ CIO_MSG_EVENT(6, "Detected device %04x on subchannel 0.%x.%04X "
+ "- PIM = %02X, PAM = %02X, POM = %02X\n",
+ sch->schib.pmcw.dev, sch->schid.ssid,
+ sch->schid.sch_no, sch->schib.pmcw.pim,
+ sch->schib.pmcw.pam, sch->schib.pmcw.pom);
/*
* We now have to initially ...
- * ... set "interruption subclass"
* ... enable "concurrent sense"
* ... enable "multipath mode" if more than one
* CHPID is available. This is done regardless
* whether multiple paths are available for us.
*/
- sch->schib.pmcw.isc = 3; /* could be smth. else */
sch->schib.pmcw.csense = 1; /* concurrent sense */
sch->schib.pmcw.ena = 0;
if ((sch->lpm & (sch->lpm - 1)) != 0)
@@ -812,6 +791,7 @@ cio_probe_console(void)
* enable console I/O-interrupt subclass 7
*/
ctl_set_bit(6, 24);
+ console_subchannel.isc = 7;
console_subchannel.schib.pmcw.isc = 7;
console_subchannel.schib.pmcw.intparm =
(u32)(addr_t)&console_subchannel;
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 08f2235c5a6f..6e933aebe013 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -74,6 +74,7 @@ struct subchannel {
__u8 lpm; /* logical path mask */
__u8 opm; /* operational path mask */
struct schib schib; /* subchannel information block */
+ int isc; /* desired interruption subclass */
struct chsc_ssd_info ssd_info; /* subchannel description */
struct device dev; /* entry in device tree */
struct css_driver *driver;
@@ -85,7 +86,7 @@ struct subchannel {
#define to_subchannel(n) container_of(n, struct subchannel, dev)
extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
-extern int cio_enable_subchannel(struct subchannel *, unsigned int, u32);
+extern int cio_enable_subchannel(struct subchannel *, u32);
extern int cio_disable_subchannel (struct subchannel *);
extern int cio_cancel (struct subchannel *);
extern int cio_clear (struct subchannel *);
@@ -117,6 +118,4 @@ extern void *cio_get_console_priv(void);
#define cio_get_console_priv() NULL
#endif
-extern int cio_show_msg;
-
#endif
diff --git a/drivers/s390/cio/cio_debug.h b/drivers/s390/cio/cio_debug.h
index d7429ef6c666..e64e8278c42e 100644
--- a/drivers/s390/cio/cio_debug.h
+++ b/drivers/s390/cio/cio_debug.h
@@ -31,10 +31,4 @@ static inline void CIO_HEX_EVENT(int level, void *data, int length)
}
}
-#define CIO_DEBUG(printk_level, event_level, msg...) do { \
- if (cio_show_msg) \
- printk(printk_level "cio: " msg); \
- CIO_MSG_EVENT(event_level, msg); \
- } while (0)
-
#endif
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index f4c132ab39ed..2808b6833b9e 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -1219,16 +1219,21 @@ static ssize_t cmb_enable_store(struct device *dev,
{
struct ccw_device *cdev;
int ret;
+ unsigned long val;
+
+ ret = strict_strtoul(buf, 16, &val);
+ if (ret)
+ return ret;
cdev = to_ccwdev(dev);
- switch (buf[0]) {
- case '0':
+ switch (val) {
+ case 0:
ret = disable_cmf(cdev);
if (ret)
dev_info(&cdev->dev, "disable_cmf failed (%d)\n", ret);
break;
- case '1':
+ case 1:
ret = enable_cmf(cdev);
if (ret && ret != -EBUSY)
dev_info(&cdev->dev, "enable_cmf failed (%d)\n", ret);
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index c1afab5f72d6..a76956512b2d 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -570,7 +570,7 @@ static void reprobe_all(struct work_struct *unused)
{
int ret;
- CIO_MSG_EVENT(2, "reprobe start\n");
+ CIO_MSG_EVENT(4, "reprobe start\n");
need_reprobe = 0;
/* Make sure initial subchannel scan is done. */
@@ -578,7 +578,7 @@ static void reprobe_all(struct work_struct *unused)
atomic_read(&ccw_device_init_count) == 0);
ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL);
- CIO_MSG_EVENT(2, "reprobe done (rc=%d, need_reprobe=%d)\n", ret,
+ CIO_MSG_EVENT(4, "reprobe done (rc=%d, need_reprobe=%d)\n", ret,
need_reprobe);
}
@@ -705,13 +705,17 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
{
struct channel_subsystem *css = to_css(dev);
int ret;
+ unsigned long val;
+ ret = strict_strtoul(buf, 16, &val);
+ if (ret)
+ return ret;
mutex_lock(&css->mutex);
- switch (buf[0]) {
- case '0':
+ switch (val) {
+ case 0:
ret = css->cm_enabled ? chsc_secm(css, 0) : 0;
break;
- case '1':
+ case 1:
ret = css->cm_enabled ? 0 : chsc_secm(css, 1);
break;
default:
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index e0c7adb8958e..e22813db74a2 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -341,7 +341,7 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
rc = device_schedule_callback(&cdev->dev,
ccw_device_remove_orphan_cb);
if (rc)
- CIO_MSG_EVENT(2, "Couldn't unregister orphan "
+ CIO_MSG_EVENT(0, "Couldn't unregister orphan "
"0.%x.%04x\n",
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
@@ -351,7 +351,7 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
rc = device_schedule_callback(cdev->dev.parent,
ccw_device_remove_sch_cb);
if (rc)
- CIO_MSG_EVENT(2, "Couldn't unregister disconnected device "
+ CIO_MSG_EVENT(0, "Couldn't unregister disconnected device "
"0.%x.%04x\n",
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
@@ -397,7 +397,7 @@ int ccw_device_set_offline(struct ccw_device *cdev)
if (ret == 0)
wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
else {
- CIO_MSG_EVENT(2, "ccw_device_offline returned %d, "
+ CIO_MSG_EVENT(0, "ccw_device_offline returned %d, "
"device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
@@ -433,7 +433,7 @@ int ccw_device_set_online(struct ccw_device *cdev)
if (ret == 0)
wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
else {
- CIO_MSG_EVENT(2, "ccw_device_online returned %d, "
+ CIO_MSG_EVENT(0, "ccw_device_online returned %d, "
"device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
@@ -451,7 +451,7 @@ int ccw_device_set_online(struct ccw_device *cdev)
if (ret == 0)
wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
else
- CIO_MSG_EVENT(2, "ccw_device_offline returned %d, "
+ CIO_MSG_EVENT(0, "ccw_device_offline returned %d, "
"device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
@@ -512,8 +512,8 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct ccw_device *cdev = to_ccwdev(dev);
- int i, force;
- char *tmp;
+ int force, ret;
+ unsigned long i;
if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0)
return -EAGAIN;
@@ -525,25 +525,30 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
if (!strncmp(buf, "force\n", count)) {
force = 1;
i = 1;
+ ret = 0;
} else {
force = 0;
- i = simple_strtoul(buf, &tmp, 16);
+ ret = strict_strtoul(buf, 16, &i);
}
-
+ if (ret)
+ goto out;
switch (i) {
case 0:
online_store_handle_offline(cdev);
+ ret = count;
break;
case 1:
online_store_handle_online(cdev, force);
+ ret = count;
break;
default:
- count = -EINVAL;
+ ret = -EINVAL;
}
+out:
if (cdev->drv)
module_put(cdev->drv->owner);
atomic_set(&cdev->private->onoff, 0);
- return count;
+ return ret;
}
static ssize_t
@@ -798,7 +803,7 @@ static void sch_attach_disconnected_device(struct subchannel *sch,
other_sch = to_subchannel(get_device(cdev->dev.parent));
ret = device_move(&cdev->dev, &sch->dev);
if (ret) {
- CIO_MSG_EVENT(2, "Moving disconnected device 0.%x.%04x failed "
+ CIO_MSG_EVENT(0, "Moving disconnected device 0.%x.%04x failed "
"(ret=%d)!\n", cdev->private->dev_id.ssid,
cdev->private->dev_id.devno, ret);
put_device(&other_sch->dev);
@@ -928,7 +933,7 @@ io_subchannel_register(struct work_struct *work)
ret = device_reprobe(&cdev->dev);
if (ret)
/* We can't do much here. */
- CIO_MSG_EVENT(2, "device_reprobe() returned"
+ CIO_MSG_EVENT(0, "device_reprobe() returned"
" %d for 0.%x.%04x\n", ret,
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
@@ -1081,7 +1086,7 @@ static void ccw_device_move_to_sch(struct work_struct *work)
rc = device_move(&cdev->dev, &sch->dev);
mutex_unlock(&sch->reg_mutex);
if (rc) {
- CIO_MSG_EVENT(2, "Moving device 0.%x.%04x to subchannel "
+ CIO_MSG_EVENT(0, "Moving device 0.%x.%04x to subchannel "
"0.%x.%04x failed (ret=%d)!\n",
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno, sch->schid.ssid,
@@ -1441,8 +1446,7 @@ ccw_device_remove (struct device *dev)
wait_event(cdev->private->wait_q,
dev_fsm_final_state(cdev));
else
- //FIXME: we can't fail!
- CIO_MSG_EVENT(2, "ccw_device_offline returned %d, "
+ CIO_MSG_EVENT(0, "ccw_device_offline returned %d, "
"device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
@@ -1519,7 +1523,7 @@ static int recovery_check(struct device *dev, void *data)
spin_lock_irq(cdev->ccwlock);
switch (cdev->private->state) {
case DEV_STATE_DISCONNECTED:
- CIO_MSG_EVENT(3, "recovery: trigger 0.%x.%04x\n",
+ CIO_MSG_EVENT(4, "recovery: trigger 0.%x.%04x\n",
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
dev_fsm_event(cdev, DEV_EVENT_VERIFY);
@@ -1549,7 +1553,7 @@ static void recovery_work_func(struct work_struct *unused)
}
spin_unlock_irq(&recovery_lock);
} else
- CIO_MSG_EVENT(2, "recovery: end\n");
+ CIO_MSG_EVENT(4, "recovery: end\n");
}
static DECLARE_WORK(recovery_work, recovery_work_func);
@@ -1567,7 +1571,7 @@ void ccw_device_schedule_recovery(void)
{
unsigned long flags;
- CIO_MSG_EVENT(2, "recovery: schedule\n");
+ CIO_MSG_EVENT(4, "recovery: schedule\n");
spin_lock_irqsave(&recovery_lock, flags);
if (!timer_pending(&recovery_timer) || (recovery_phase != 0)) {
recovery_phase = 0;
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 4b92c84fb438..e268d5a77c12 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -322,10 +322,10 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
same_dev = 0; /* Keep the compiler quiet... */
switch (state) {
case DEV_STATE_NOT_OPER:
- CIO_DEBUG(KERN_WARNING, 2,
- "SenseID : unknown device %04x on subchannel "
- "0.%x.%04x\n", cdev->private->dev_id.devno,
- sch->schid.ssid, sch->schid.sch_no);
+ CIO_MSG_EVENT(2, "SenseID : unknown device %04x on "
+ "subchannel 0.%x.%04x\n",
+ cdev->private->dev_id.devno,
+ sch->schid.ssid, sch->schid.sch_no);
break;
case DEV_STATE_OFFLINE:
if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) {
@@ -348,20 +348,19 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
return;
}
/* Issue device info message. */
- CIO_DEBUG(KERN_INFO, 2,
- "SenseID : device 0.%x.%04x reports: "
- "CU Type/Mod = %04X/%02X, Dev Type/Mod = "
- "%04X/%02X\n",
- cdev->private->dev_id.ssid,
- cdev->private->dev_id.devno,
- cdev->id.cu_type, cdev->id.cu_model,
- cdev->id.dev_type, cdev->id.dev_model);
+ CIO_MSG_EVENT(4, "SenseID : device 0.%x.%04x reports: "
+ "CU Type/Mod = %04X/%02X, Dev Type/Mod = "
+ "%04X/%02X\n",
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno,
+ cdev->id.cu_type, cdev->id.cu_model,
+ cdev->id.dev_type, cdev->id.dev_model);
break;
case DEV_STATE_BOXED:
- CIO_DEBUG(KERN_WARNING, 2,
- "SenseID : boxed device %04x on subchannel "
- "0.%x.%04x\n", cdev->private->dev_id.devno,
- sch->schid.ssid, sch->schid.sch_no);
+ CIO_MSG_EVENT(0, "SenseID : boxed device %04x on "
+ " subchannel 0.%x.%04x\n",
+ cdev->private->dev_id.devno,
+ sch->schid.ssid, sch->schid.sch_no);
break;
}
cdev->private->state = state;
@@ -443,9 +442,8 @@ ccw_device_done(struct ccw_device *cdev, int state)
if (state == DEV_STATE_BOXED)
- CIO_DEBUG(KERN_WARNING, 2,
- "Boxed device %04x on subchannel %04x\n",
- cdev->private->dev_id.devno, sch->schid.sch_no);
+ CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n",
+ cdev->private->dev_id.devno, sch->schid.sch_no);
if (cdev->private->flags.donotify) {
cdev->private->flags.donotify = 0;
@@ -555,8 +553,7 @@ ccw_device_recognition(struct ccw_device *cdev)
(cdev->private->state != DEV_STATE_BOXED))
return -EINVAL;
sch = to_subchannel(cdev->dev.parent);
- ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
- (u32)(addr_t)sch);
+ ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
if (ret != 0)
/* Couldn't enable the subchannel for i/o. Sick device. */
return ret;
@@ -667,8 +664,7 @@ ccw_device_online(struct ccw_device *cdev)
sch = to_subchannel(cdev->dev.parent);
if (css_init_done && !get_device(&cdev->dev))
return -ENODEV;
- ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc,
- (u32)(addr_t)sch);
+ ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
if (ret != 0) {
/* Couldn't enable the subchannel for i/o. Sick device. */
if (ret == -ENODEV)
@@ -902,7 +898,7 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
/* Basic sense hasn't started. Try again. */
ccw_device_do_sense(cdev, irb);
else {
- CIO_MSG_EVENT(2, "Huh? 0.%x.%04x: unsolicited "
+ CIO_MSG_EVENT(0, "0.%x.%04x: unsolicited "
"interrupt during w4sense...\n",
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
@@ -1048,8 +1044,7 @@ ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event)
struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent);
- if (cio_enable_subchannel(sch, sch->schib.pmcw.isc,
- (u32)(addr_t)sch) != 0)
+ if (cio_enable_subchannel(sch, (u32)(addr_t)sch) != 0)
/* Couldn't enable the subchannel for i/o. Sick device. */
return;
@@ -1082,7 +1077,6 @@ device_trigger_reprobe(struct subchannel *sch)
*/
sch->lpm = sch->schib.pmcw.pam & sch->opm;
/* Re-set some bits in the pmcw that were lost. */
- sch->schib.pmcw.isc = 3;
sch->schib.pmcw.csense = 1;
sch->schib.pmcw.ena = 0;
if ((sch->lpm & (sch->lpm - 1)) != 0)
@@ -1173,8 +1167,10 @@ ccw_device_nop(struct ccw_device *cdev, enum dev_event dev_event)
static void
ccw_device_bug(struct ccw_device *cdev, enum dev_event dev_event)
{
- CIO_MSG_EVENT(0, "dev_jumptable[%i][%i] == NULL\n",
- cdev->private->state, dev_event);
+ CIO_MSG_EVENT(0, "Internal state [%i][%i] not handled for device "
+ "0.%x.%04x\n", cdev->private->state, dev_event,
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno);
BUG();
}
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index dc4d87f77f6c..cba7020517ed 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -214,7 +214,7 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
* sense id information. So, for intervention required,
* we use the "whack it until it talks" strategy...
*/
- CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel "
+ CIO_MSG_EVENT(0, "SenseID : device %04x on Subchannel "
"0.%x.%04x reports cmd reject\n",
cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no);
@@ -239,7 +239,7 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
lpm = to_io_private(sch)->orb.lpm;
if ((lpm & sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0)
- CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x "
+ CIO_MSG_EVENT(4, "SenseID : path %02X for device %04x "
"on subchannel 0.%x.%04x is "
"'not operational'\n", lpm,
cdev->private->dev_id.devno,
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index a1718a0aa539..f308ad55a6d5 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -508,7 +508,7 @@ ccw_device_stlck(struct ccw_device *cdev)
return -ENOMEM;
}
spin_lock_irqsave(sch->lock, flags);
- ret = cio_enable_subchannel(sch, 3, (u32)(addr_t)sch);
+ ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
if (ret)
goto out_unlock;
/*
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index c52449a1f9fc..5cf7be008e98 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -79,7 +79,7 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
/* ret is 0, -EBUSY, -EACCES or -ENODEV */
if (ret != -EACCES)
return ret;
- CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
+ CIO_MSG_EVENT(3, "SNID - Device %04x on Subchannel "
"0.%x.%04x, lpm %02X, became 'not "
"operational'\n",
cdev->private->dev_id.devno,
@@ -159,7 +159,7 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
u8 lpm;
lpm = to_io_private(sch)->orb.lpm;
- CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x,"
+ CIO_MSG_EVENT(3, "SNID - Device %04x on Subchannel 0.%x.%04x,"
" lpm %02X, became 'not operational'\n",
cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, lpm);
@@ -243,16 +243,10 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
/* Setup sense path group id channel program. */
cdev->private->pgid[0].inf.fc = func;
ccw = cdev->private->iccws;
- if (!cdev->private->flags.pgid_single) {
- cdev->private->pgid[0].inf.fc |= SPID_FUNC_MULTI_PATH;
- ccw->cmd_code = CCW_CMD_SUSPEND_RECONN;
- ccw->cda = 0;
- ccw->count = 0;
- ccw->flags = CCW_FLAG_SLI | CCW_FLAG_CC;
- ccw++;
- } else
+ if (cdev->private->flags.pgid_single)
cdev->private->pgid[0].inf.fc |= SPID_FUNC_SINGLE_PATH;
-
+ else
+ cdev->private->pgid[0].inf.fc |= SPID_FUNC_MULTI_PATH;
ccw->cmd_code = CCW_CMD_SET_PGID;
ccw->cda = (__u32) __pa (&cdev->private->pgid[0]);
ccw->count = sizeof (struct pgid);
@@ -275,7 +269,7 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
return ret;
}
/* PGID command failed on this path. */
- CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
+ CIO_MSG_EVENT(3, "SPID - Device %04x on Subchannel "
"0.%x.%04x, lpm %02X, became 'not operational'\n",
cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, cdev->private->imask);
@@ -317,7 +311,7 @@ static int __ccw_device_do_nop(struct ccw_device *cdev)
return ret;
}
/* nop command failed on this path. */
- CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel "
+ CIO_MSG_EVENT(3, "NOP - Device %04x on Subchannel "
"0.%x.%04x, lpm %02X, became 'not operational'\n",
cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, cdev->private->imask);
@@ -362,7 +356,7 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
return -EAGAIN;
}
if (irb->scsw.cc == 3) {
- CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x,"
+ CIO_MSG_EVENT(3, "SPID - Device %04x on Subchannel 0.%x.%04x,"
" lpm %02X, became 'not operational'\n",
cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, cdev->private->imask);
@@ -391,7 +385,7 @@ static int __ccw_device_check_nop(struct ccw_device *cdev)
return -ETIME;
}
if (irb->scsw.cc == 3) {
- CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel 0.%x.%04x,"
+ CIO_MSG_EVENT(3, "NOP - Device %04x on Subchannel 0.%x.%04x,"
" lpm %02X, became 'not operational'\n",
cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, cdev->private->imask);
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 10aa1e780801..445cf364e461 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -3632,7 +3632,7 @@ qdio_add_procfs_entry(void)
{
proc_perf_file_registration=0;
qdio_perf_proc_file=create_proc_entry(QDIO_PERF,
- S_IFREG|0444,&proc_root);
+ S_IFREG|0444,NULL);
if (qdio_perf_proc_file) {
qdio_perf_proc_file->read_proc=&qdio_perf_procfile_read;
} else proc_perf_file_registration=-1;
@@ -3647,7 +3647,7 @@ static void
qdio_remove_procfs_entry(void)
{
if (!proc_perf_file_registration) /* means if it went ok earlier */
- remove_proc_entry(QDIO_PERF,&proc_root);
+ remove_proc_entry(QDIO_PERF,NULL);
}
/**
@@ -3663,11 +3663,11 @@ qdio_performance_stats_show(struct bus_type *bus, char *buf)
static ssize_t
qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count)
{
- char *tmp;
- int i;
+ unsigned long i;
+ int ret;
- i = simple_strtoul(buf, &tmp, 16);
- if ((i == 0) || (i == 1)) {
+ ret = strict_strtoul(buf, 16, &i);
+ if (!ret && ((i == 0) || (i == 1))) {
if (i == qdio_performance_stats)
return count;
qdio_performance_stats = i;
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index bbef3764fbf8..47a7e6200b26 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -17,6 +17,7 @@
#include <linux/virtio_config.h>
#include <linux/interrupt.h>
#include <linux/virtio_ring.h>
+#include <linux/pfn.h>
#include <asm/io.h>
#include <asm/kvm_para.h>
#include <asm/kvm_virtio.h>
@@ -180,11 +181,10 @@ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev,
config = kvm_vq_config(kdev->desc)+index;
- if (add_shared_memory(config->address,
- vring_size(config->num, PAGE_SIZE))) {
- err = -ENOMEM;
+ err = vmem_add_mapping(config->address,
+ vring_size(config->num, PAGE_SIZE));
+ if (err)
goto out;
- }
vq = vring_new_virtqueue(config->num, vdev, (void *) config->address,
kvm_notify, callback);
@@ -202,8 +202,8 @@ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev,
vq->priv = config;
return vq;
unmap:
- remove_shared_memory(config->address, vring_size(config->num,
- PAGE_SIZE));
+ vmem_remove_mapping(config->address,
+ vring_size(config->num, PAGE_SIZE));
out:
return ERR_PTR(err);
}
@@ -213,8 +213,8 @@ static void kvm_del_vq(struct virtqueue *vq)
struct kvm_vqconfig *config = vq->priv;
vring_del_virtqueue(vq);
- remove_shared_memory(config->address,
- vring_size(config->num, PAGE_SIZE));
+ vmem_remove_mapping(config->address,
+ vring_size(config->num, PAGE_SIZE));
}
/*
@@ -318,12 +318,13 @@ static int __init kvm_devices_init(void)
return rc;
}
- if (add_shared_memory((max_pfn) << PAGE_SHIFT, PAGE_SIZE)) {
+ rc = vmem_add_mapping(PFN_PHYS(max_pfn), PAGE_SIZE);
+ if (rc) {
device_unregister(&kvm_root);
- return -ENOMEM;
+ return rc;
}
- kvm_devices = (void *) (max_pfn << PAGE_SHIFT);
+ kvm_devices = (void *) PFN_PHYS(max_pfn);
ctl_set_bit(0, 9);
register_external_interrupt(0x2603, kvm_extint_handler);
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
index 76728ae4b843..8e7697305a4c 100644
--- a/drivers/s390/net/cu3088.c
+++ b/drivers/s390/net/cu3088.c
@@ -62,30 +62,14 @@ static struct device *cu3088_root_dev;
static ssize_t
group_write(struct device_driver *drv, const char *buf, size_t count)
{
- const char *start, *end;
- char bus_ids[2][BUS_ID_SIZE], *argv[2];
- int i;
int ret;
struct ccwgroup_driver *cdrv;
cdrv = to_ccwgroupdrv(drv);
if (!cdrv)
return -EINVAL;
- start = buf;
- for (i=0; i<2; i++) {
- static const char delim[] = {',', '\n'};
- int len;
-
- if (!(end = strchr(start, delim[i])))
- return -EINVAL;
- len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start + 1);
- strlcpy (bus_ids[i], start, len);
- argv[i] = bus_ids[i];
- start = end + 1;
- }
-
- ret = ccwgroup_create(cu3088_root_dev, cdrv->driver_id,
- &cu3088_driver, 2, argv);
+ ret = ccwgroup_create_from_string(cu3088_root_dev, cdrv->driver_id,
+ &cu3088_driver, 2, buf);
return (ret == 0) ? count : ret;
}
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index f51ed9972587..dd22f4b37037 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -1793,7 +1793,8 @@ lcs_get_skb(struct lcs_card *card, char *skb_data, unsigned int skb_len)
skb->protocol = card->lan_type_trans(skb, card->dev);
card->stats.rx_bytes += skb_len;
card->stats.rx_packets++;
- *((__u32 *)skb->cb) = ++card->pkt_seq;
+ if (skb->protocol == htons(ETH_P_802_2))
+ *((__u32 *)skb->cb) = ++card->pkt_seq;
netif_rx(skb);
}
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 8f876f6ab367..e4ba6a0372ac 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1313,8 +1313,6 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
* and throw away packet.
*/
if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
- if (!in_atomic())
- fsm_event(privptr->fsm, DEV_EVENT_START, dev);
dev_kfree_skb(skb);
privptr->stats.tx_dropped++;
privptr->stats.tx_errors++;
@@ -2147,6 +2145,7 @@ static int __init netiucv_init(void)
if (rc)
goto out_dbf;
IUCV_DBF_TEXT(trace, 3, __func__);
+ netiucv_driver.groups = netiucv_drv_attr_groups;
rc = driver_register(&netiucv_driver);
if (rc) {
PRINT_ERR("NETIUCV: failed to register driver.\n");
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 66f4f12503c9..699ac11debd8 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -72,22 +72,7 @@ struct qeth_dbf_info {
debug_sprintf_event(qeth_dbf[QETH_DBF_MSG].id, level, text)
#define QETH_DBF_TEXT_(name, level, text...) \
- do { \
- if (qeth_dbf_passes(qeth_dbf[QETH_DBF_##name].id, level)) { \
- char *dbf_txt_buf = \
- get_cpu_var(QETH_DBF_TXT_BUF); \
- sprintf(dbf_txt_buf, text); \
- debug_text_event(qeth_dbf[QETH_DBF_##name].id, \
- level, dbf_txt_buf); \
- put_cpu_var(QETH_DBF_TXT_BUF); \
- } \
- } while (0)
-
-/* Allow to sort out low debug levels early to avoid wasted sprints */
-static inline int qeth_dbf_passes(debug_info_t *dbf_grp, int level)
-{
- return (level <= dbf_grp->level);
-}
+ qeth_dbf_longtext(QETH_DBF_##name, level, text)
/**
* some more debug stuff
@@ -773,27 +758,6 @@ static inline int qeth_get_micros(void)
return (int) (get_clock() >> 12);
}
-static inline void *qeth_push_skb(struct qeth_card *card, struct sk_buff *skb,
- int size)
-{
- void *hdr;
-
- hdr = (void *) skb_push(skb, size);
- /*
- * sanity check, the Linux memory allocation scheme should
- * never present us cases like this one (the qdio header size plus
- * the first 40 bytes of the paket cross a 4k boundary)
- */
- if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) !=
- (((unsigned long) hdr + size +
- QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
- PRINT_ERR("Misaligned packet on interface %s. Discarded.",
- QETH_CARD_IFNAME(card));
- return NULL;
- }
- return hdr;
-}
-
static inline int qeth_get_ip_version(struct sk_buff *skb)
{
switch (skb->protocol) {
@@ -806,6 +770,12 @@ static inline int qeth_get_ip_version(struct sk_buff *skb)
}
}
+static inline void qeth_put_buffer_pool_entry(struct qeth_card *card,
+ struct qeth_buffer_pool_entry *entry)
+{
+ list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list);
+}
+
struct qeth_eddp_context;
extern struct ccwgroup_driver qeth_l2_ccwgroup_driver;
extern struct ccwgroup_driver qeth_l3_ccwgroup_driver;
@@ -843,8 +813,6 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *,
int qeth_query_setadapterparms(struct qeth_card *);
int qeth_check_qdio_errors(struct qdio_buffer *, unsigned int,
unsigned int, const char *);
-void qeth_put_buffer_pool_entry(struct qeth_card *,
- struct qeth_buffer_pool_entry *);
void qeth_queue_input_buffer(struct qeth_card *, int);
struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
struct qdio_buffer *, struct qdio_buffer_element **, int *,
@@ -880,8 +848,6 @@ int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
void *reply_param);
int qeth_get_cast_type(struct qeth_card *, struct sk_buff *);
int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int);
-struct sk_buff *qeth_prepare_skb(struct qeth_card *, struct sk_buff *,
- struct qeth_hdr **);
int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int);
int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *,
struct sk_buff *, struct qeth_hdr *, int,
@@ -894,6 +860,8 @@ void qeth_core_get_ethtool_stats(struct net_device *,
struct ethtool_stats *, u64 *);
void qeth_core_get_strings(struct net_device *, u32, u8 *);
void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
+void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *text, ...);
+int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *);
/* exports for OSN */
int qeth_osn_assist(struct net_device *, void *, int);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 055f5c3e7b56..436bf1f6d4a6 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -26,9 +26,6 @@
#include "qeth_core.h"
#include "qeth_core_offl.h"
-static DEFINE_PER_CPU(char[256], qeth_core_dbf_txt_buf);
-#define QETH_DBF_TXT_BUF qeth_core_dbf_txt_buf
-
struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS] = {
/* define dbf - Name, Pages, Areas, Maxlen, Level, View, Handle */
/* N P A M L V H */
@@ -2255,14 +2252,6 @@ void qeth_print_status_message(struct qeth_card *card)
}
EXPORT_SYMBOL_GPL(qeth_print_status_message);
-void qeth_put_buffer_pool_entry(struct qeth_card *card,
- struct qeth_buffer_pool_entry *entry)
-{
- QETH_DBF_TEXT(TRACE, 6, "ptbfplen");
- list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list);
-}
-EXPORT_SYMBOL_GPL(qeth_put_buffer_pool_entry);
-
static void qeth_initialize_working_pool_list(struct qeth_card *card)
{
struct qeth_buffer_pool_entry *entry;
@@ -2603,7 +2592,6 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index)
int rc;
int newcount = 0;
- QETH_DBF_TEXT(TRACE, 6, "queinbuf");
count = (index < queue->next_buf_to_init)?
card->qdio.in_buf_pool.buf_count -
(queue->next_buf_to_init - index) :
@@ -2792,8 +2780,6 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
int i;
unsigned int qdio_flags;
- QETH_DBF_TEXT(TRACE, 6, "flushbuf");
-
for (i = index; i < index + count; ++i) {
buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
buf->buffer->element[buf->next_element_to_fill - 1].flags |=
@@ -3037,49 +3023,6 @@ int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(qeth_get_priority_queue);
-static void __qeth_free_new_skb(struct sk_buff *orig_skb,
- struct sk_buff *new_skb)
-{
- if (orig_skb != new_skb)
- dev_kfree_skb_any(new_skb);
-}
-
-static inline struct sk_buff *qeth_realloc_headroom(struct qeth_card *card,
- struct sk_buff *skb, int size)
-{
- struct sk_buff *new_skb = skb;
-
- if (skb_headroom(skb) >= size)
- return skb;
- new_skb = skb_realloc_headroom(skb, size);
- if (!new_skb)
- PRINT_ERR("Could not realloc headroom for qeth_hdr "
- "on interface %s", QETH_CARD_IFNAME(card));
- return new_skb;
-}
-
-struct sk_buff *qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
- struct qeth_hdr **hdr)
-{
- struct sk_buff *new_skb;
-
- QETH_DBF_TEXT(TRACE, 6, "prepskb");
-
- new_skb = qeth_realloc_headroom(card, skb,
- sizeof(struct qeth_hdr));
- if (!new_skb)
- return NULL;
-
- *hdr = ((struct qeth_hdr *)qeth_push_skb(card, new_skb,
- sizeof(struct qeth_hdr)));
- if (*hdr == NULL) {
- __qeth_free_new_skb(skb, new_skb);
- return NULL;
- }
- return new_skb;
-}
-EXPORT_SYMBOL_GPL(qeth_prepare_skb);
-
int qeth_get_elements_no(struct qeth_card *card, void *hdr,
struct sk_buff *skb, int elems)
{
@@ -3100,8 +3043,8 @@ int qeth_get_elements_no(struct qeth_card *card, void *hdr,
}
EXPORT_SYMBOL_GPL(qeth_get_elements_no);
-static void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
- int is_tso, int *next_element_to_fill)
+static inline void __qeth_fill_buffer(struct sk_buff *skb,
+ struct qdio_buffer *buffer, int is_tso, int *next_element_to_fill)
{
int length = skb->len;
int length_here;
@@ -3143,15 +3086,13 @@ static void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
*next_element_to_fill = element;
}
-static int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
+static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
struct qeth_qdio_out_buffer *buf, struct sk_buff *skb)
{
struct qdio_buffer *buffer;
struct qeth_hdr_tso *hdr;
int flush_cnt = 0, hdr_len, large_send = 0;
- QETH_DBF_TEXT(TRACE, 6, "qdfillbf");
-
buffer = buf->buffer;
atomic_inc(&skb->users);
skb_queue_tail(&buf->skb_list, skb);
@@ -3210,8 +3151,6 @@ int qeth_do_send_packet_fast(struct qeth_card *card,
int flush_cnt = 0;
int index;
- QETH_DBF_TEXT(TRACE, 6, "dosndpfa");
-
/* spin until we get the queue ... */
while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
@@ -3263,8 +3202,6 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
int tmp;
int rc = 0;
- QETH_DBF_TEXT(TRACE, 6, "dosndpkt");
-
/* spin until we get the queue ... */
while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
@@ -3827,27 +3764,8 @@ static struct ccw_driver qeth_ccw_driver = {
static int qeth_core_driver_group(const char *buf, struct device *root_dev,
unsigned long driver_id)
{
- const char *start, *end;
- char bus_ids[3][BUS_ID_SIZE], *argv[3];
- int i;
-
- start = buf;
- for (i = 0; i < 3; i++) {
- static const char delim[] = { ',', ',', '\n' };
- int len;
-
- end = strchr(start, delim[i]);
- if (!end)
- return -EINVAL;
- len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start);
- strncpy(bus_ids[i], start, len);
- bus_ids[i][len] = '\0';
- start = end + 1;
- argv[i] = bus_ids[i];
- }
-
- return (ccwgroup_create(root_dev, driver_id,
- &qeth_ccw_driver, 3, argv));
+ return ccwgroup_create_from_string(root_dev, driver_id,
+ &qeth_ccw_driver, 3, buf);
}
int qeth_core_hardsetup_card(struct qeth_card *card)
@@ -3885,8 +3803,9 @@ retry:
QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
return rc;
}
-
- mpno = QETH_MAX_PORTNO;
+ mpno = qdio_get_ssqd_pct(CARD_DDEV(card));
+ if (mpno)
+ mpno = min(mpno - 1, QETH_MAX_PORTNO);
if (card->info.portno > mpno) {
PRINT_ERR("Device %s does not offer port number %d \n.",
CARD_BUS_ID(card), card->info.portno);
@@ -3980,7 +3899,6 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
int use_rx_sg = 0;
int frag = 0;
- QETH_DBF_TEXT(TRACE, 6, "nextskb");
/* qeth_hdr must not cross element boundaries */
if (element->length < offset + sizeof(struct qeth_hdr)) {
if (qeth_is_last_sbale(element))
@@ -4086,6 +4004,18 @@ static void qeth_unregister_dbf_views(void)
}
}
+void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *text, ...)
+{
+ char dbf_txt_buf[32];
+
+ if (level > (qeth_dbf[dbf_nix].id)->level)
+ return;
+ snprintf(dbf_txt_buf, sizeof(dbf_txt_buf), text);
+ debug_text_event(qeth_dbf[dbf_nix].id, level, dbf_txt_buf);
+
+}
+EXPORT_SYMBOL_GPL(qeth_dbf_longtext);
+
static int qeth_register_dbf_views(void)
{
int ret;
@@ -4433,6 +4363,96 @@ void qeth_core_get_drvinfo(struct net_device *dev,
}
EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo);
+int qeth_core_ethtool_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct qeth_card *card = netdev_priv(netdev);
+ enum qeth_link_types link_type;
+
+ if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan))
+ link_type = QETH_LINK_TYPE_10GBIT_ETH;
+ else
+ link_type = card->info.link_type;
+
+ ecmd->transceiver = XCVR_INTERNAL;
+ ecmd->supported = SUPPORTED_Autoneg;
+ ecmd->advertising = ADVERTISED_Autoneg;
+ ecmd->duplex = DUPLEX_FULL;
+ ecmd->autoneg = AUTONEG_ENABLE;
+
+ switch (link_type) {
+ case QETH_LINK_TYPE_FAST_ETH:
+ case QETH_LINK_TYPE_LANE_ETH100:
+ ecmd->supported |= SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_TP;
+ ecmd->advertising |= ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_TP;
+ ecmd->speed = SPEED_100;
+ ecmd->port = PORT_TP;
+ break;
+
+ case QETH_LINK_TYPE_GBIT_ETH:
+ case QETH_LINK_TYPE_LANE_ETH1000:
+ ecmd->supported |= SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE;
+ ecmd->advertising |= ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full |
+ ADVERTISED_FIBRE;
+ ecmd->speed = SPEED_1000;
+ ecmd->port = PORT_FIBRE;
+ break;
+
+ case QETH_LINK_TYPE_10GBIT_ETH:
+ ecmd->supported |= SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_FIBRE;
+ ecmd->advertising |= ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full |
+ ADVERTISED_10000baseT_Full |
+ ADVERTISED_FIBRE;
+ ecmd->speed = SPEED_10000;
+ ecmd->port = PORT_FIBRE;
+ break;
+
+ default:
+ ecmd->supported |= SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_TP;
+ ecmd->advertising |= ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_TP;
+ ecmd->speed = SPEED_10;
+ ecmd->port = PORT_TP;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_settings);
+
static int __init qeth_core_init(void)
{
int rc;
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 3921d1631a78..86ec50ddae13 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -22,9 +22,6 @@
#include "qeth_core.h"
#include "qeth_core_offl.h"
-#define QETH_DBF_TXT_BUF qeth_l2_dbf_txt_buf
-static DEFINE_PER_CPU(char[256], qeth_l2_dbf_txt_buf);
-
static int qeth_l2_set_offline(struct ccwgroup_device *);
static int qeth_l2_stop(struct net_device *);
static int qeth_l2_send_delmac(struct qeth_card *, __u8 *);
@@ -635,8 +632,6 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
struct qeth_eddp_context *ctx = NULL;
- QETH_DBF_TEXT(TRACE, 6, "l2xmit");
-
if ((card->state != CARD_STATE_UP) || !card->lan_online) {
card->stats.tx_carrier_errors++;
goto tx_drop;
@@ -658,9 +653,12 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (card->info.type == QETH_CARD_TYPE_OSN)
hdr = (struct qeth_hdr *)skb->data;
else {
- new_skb = qeth_prepare_skb(card, skb, &hdr);
+ /* create a clone with writeable headroom */
+ new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr));
if (!new_skb)
goto tx_drop;
+ hdr = (struct qeth_hdr *)skb_push(new_skb,
+ sizeof(struct qeth_hdr));
qeth_l2_fill_header(card, hdr, new_skb, ipv, cast_type);
}
@@ -747,7 +745,6 @@ static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
int index;
int i;
- QETH_DBF_TEXT(TRACE, 6, "qdinput");
card = (struct qeth_card *) card_ptr;
net_dev = card->dev;
if (card->options.performance_stats) {
@@ -852,6 +849,22 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
return;
}
+static int qeth_l2_ethtool_set_tso(struct net_device *dev, u32 data)
+{
+ struct qeth_card *card = netdev_priv(dev);
+
+ if (data) {
+ if (card->options.large_send == QETH_LARGE_SEND_NO) {
+ card->options.large_send = QETH_LARGE_SEND_EDDP;
+ dev->features |= NETIF_F_TSO;
+ }
+ } else {
+ dev->features &= ~NETIF_F_TSO;
+ card->options.large_send = QETH_LARGE_SEND_NO;
+ }
+ return 0;
+}
+
static struct ethtool_ops qeth_l2_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_tx_csum = ethtool_op_get_tx_csum,
@@ -859,11 +872,12 @@ static struct ethtool_ops qeth_l2_ethtool_ops = {
.get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg,
.get_tso = ethtool_op_get_tso,
- .set_tso = ethtool_op_set_tso,
+ .set_tso = qeth_l2_ethtool_set_tso,
.get_strings = qeth_core_get_strings,
.get_ethtool_stats = qeth_core_get_ethtool_stats,
.get_stats_count = qeth_core_get_stats_count,
.get_drvinfo = qeth_core_get_drvinfo,
+ .get_settings = qeth_core_ethtool_get_settings,
};
static struct ethtool_ops qeth_l2_osn_ops = {
diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h
index 1be353593a59..9f143c83bba3 100644
--- a/drivers/s390/net/qeth_l3.h
+++ b/drivers/s390/net/qeth_l3.h
@@ -13,9 +13,6 @@
#include "qeth_core.h"
-#define QETH_DBF_TXT_BUF qeth_l3_dbf_txt_buf
-DECLARE_PER_CPU(char[256], qeth_l3_dbf_txt_buf);
-
struct qeth_ipaddr {
struct list_head entry;
enum qeth_ip_types type;
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index e1bfe56087d6..94a8ead64ed4 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -28,8 +28,6 @@
#include "qeth_l3.h"
#include "qeth_core_offl.h"
-DEFINE_PER_CPU(char[256], qeth_l3_dbf_txt_buf);
-
static int qeth_l3_set_offline(struct ccwgroup_device *);
static int qeth_l3_recover(void *);
static int qeth_l3_stop(struct net_device *);
@@ -2093,6 +2091,11 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
(card->state == CARD_STATE_UP)) {
if (recovery_mode)
qeth_l3_stop(card->dev);
+ else {
+ rtnl_lock();
+ dev_close(card->dev);
+ rtnl_unlock();
+ }
if (!card->use_hard_stop) {
rc = qeth_send_stoplan(card);
if (rc)
@@ -2559,8 +2562,6 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb, int ipv, int cast_type)
{
- QETH_DBF_TEXT(TRACE, 6, "fillhdr");
-
memset(hdr, 0, sizeof(struct qeth_hdr));
hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
hdr->hdr.l3.ext_flags = 0;
@@ -2570,9 +2571,10 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
* v6 uses passthrough, v4 sets the tag in the QDIO header.
*/
if (card->vlangrp && vlan_tx_tag_present(skb)) {
- hdr->hdr.l3.ext_flags = (ipv == 4) ?
- QETH_HDR_EXT_VLAN_FRAME :
- QETH_HDR_EXT_INCLUDE_VLAN_TAG;
+ if ((ipv == 4) || (card->info.type == QETH_CARD_TYPE_IQD))
+ hdr->hdr.l3.ext_flags = QETH_HDR_EXT_VLAN_FRAME;
+ else
+ hdr->hdr.l3.ext_flags = QETH_HDR_EXT_INCLUDE_VLAN_TAG;
hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb);
}
@@ -2638,8 +2640,6 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
struct qeth_eddp_context *ctx = NULL;
- QETH_DBF_TEXT(TRACE, 6, "l3xmit");
-
if ((card->info.type == QETH_CARD_TYPE_IQD) &&
(skb->protocol != htons(ETH_P_IPV6)) &&
(skb->protocol != htons(ETH_P_IP)))
@@ -2890,6 +2890,7 @@ static struct ethtool_ops qeth_l3_ethtool_ops = {
.get_ethtool_stats = qeth_core_get_ethtool_stats,
.get_stats_count = qeth_core_get_stats_count,
.get_drvinfo = qeth_core_get_drvinfo,
+ .get_settings = qeth_core_ethtool_get_settings,
};
/*
@@ -2982,7 +2983,6 @@ static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev,
int index;
int i;
- QETH_DBF_TEXT(TRACE, 6, "qdinput");
card = (struct qeth_card *) card_ptr;
net_dev = card->dev;
if (card->options.performance_stats) {
@@ -3140,9 +3140,15 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
netif_carrier_on(card->dev);
qeth_set_allowed_threads(card, 0xffffffff, 0);
- if ((recover_flag == CARD_STATE_RECOVER) && recovery_mode) {
+ if (recover_flag == CARD_STATE_RECOVER) {
+ if (recovery_mode)
qeth_l3_open(card->dev);
- qeth_l3_set_multicast_list(card->dev);
+ else {
+ rtnl_lock();
+ dev_open(card->dev);
+ rtnl_unlock();
+ }
+ qeth_l3_set_multicast_list(card->dev);
}
/* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 4d4b54277c43..5080f343ad74 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -48,10 +48,11 @@ s390_collect_crw_info(void *param)
int ccode;
struct semaphore *sem;
unsigned int chain;
+ int ignore;
sem = (struct semaphore *)param;
repeat:
- down_interruptible(sem);
+ ignore = down_interruptible(sem);
chain = 0;
while (1) {
if (unlikely(chain > 1)) {
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 37b85c67b11d..c8bad675dbd1 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -1055,7 +1055,7 @@ static void zfcp_scsi_dbf_event(const char *tag, const char *tag2, int level,
rec->scsi_result = scsi_cmnd->result;
rec->scsi_cmnd = (unsigned long)scsi_cmnd;
rec->scsi_serial = scsi_cmnd->serial_number;
- memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd,
+ memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
min((int)scsi_cmnd->cmd_len,
ZFCP_DBF_SCSI_OPCODE));
rec->scsi_retries = scsi_cmnd->retries;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 9af2330f07a2..b2ea4ea051f5 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -4014,7 +4014,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n",
scpnt->result);
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
- (void *) &scpnt->cmnd, scpnt->cmd_len);
+ scpnt->cmnd, scpnt->cmd_len);
ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n",
fcp_rsp_iu->fcp_sns_len);