aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2008-05-06 10:57:55 -0400
committerJiri Kosina <jkosina@suse.cz>2008-05-06 10:57:55 -0400
commit7022b15e2a9f878fd5184586064c63352c3dd225 (patch)
tree5365c2f5bc82ae1946636ee8d5cd5d3b7e804f1b /drivers/s390
parentaaad2b0c757f3e6e02552cb0bdcd91a5ec0d6305 (diff)
parenta15306365a16380f3bafee9e181ba01231d4acd7 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/Makefile2
-rw-r--r--drivers/s390/block/dasd_proc.c16
-rw-r--r--drivers/s390/block/dcssblk.c8
-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_proc.c9
-rw-r--r--drivers/s390/char/tty3270.c3
-rw-r--r--drivers/s390/cio/blacklist.c7
-rw-r--r--drivers/s390/cio/ccwgroup.c103
-rw-r--r--drivers/s390/cio/cio.c9
-rw-r--r--drivers/s390/cio/cio.h3
-rw-r--r--drivers/s390/cio/cmf.c11
-rw-r--r--drivers/s390/cio/css.c10
-rw-r--r--drivers/s390/cio/device.c17
-rw-r--r--drivers/s390/cio/device_fsm.c10
-rw-r--r--drivers/s390/cio/device_ops.c2
-rw-r--r--drivers/s390/cio/qdio.c12
-rw-r--r--drivers/s390/kvm/Makefile9
-rw-r--r--drivers/s390/kvm/kvm_virtio.c339
-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/scsi/zfcp_dbf.c2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c41
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h18
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c114
33 files changed, 835 insertions, 281 deletions
diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile
index 5a888704a8d0..4f4e7cf105d4 100644
--- a/drivers/s390/Makefile
+++ b/drivers/s390/Makefile
@@ -5,7 +5,7 @@
5CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w 5CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
6 6
7obj-y += s390mach.o sysinfo.o s390_rdev.o 7obj-y += s390mach.o sysinfo.o s390_rdev.o
8obj-y += cio/ block/ char/ crypto/ net/ scsi/ 8obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/
9 9
10drivers-y += drivers/s390/built-in.o 10drivers-y += drivers/s390/built-in.o
11 11
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)
157} 157}
158 158
159static const struct file_operations dasd_devices_file_ops = { 159static const struct file_operations dasd_devices_file_ops = {
160 .owner = THIS_MODULE,
160 .open = dasd_devices_open, 161 .open = dasd_devices_open,
161 .read = seq_read, 162 .read = seq_read,
162 .llseek = seq_lseek, 163 .llseek = seq_lseek,
@@ -311,17 +312,16 @@ out_error:
311int 312int
312dasd_proc_init(void) 313dasd_proc_init(void)
313{ 314{
314 dasd_proc_root_entry = proc_mkdir("dasd", &proc_root); 315 dasd_proc_root_entry = proc_mkdir("dasd", NULL);
315 if (!dasd_proc_root_entry) 316 if (!dasd_proc_root_entry)
316 goto out_nodasd; 317 goto out_nodasd;
317 dasd_proc_root_entry->owner = THIS_MODULE; 318 dasd_proc_root_entry->owner = THIS_MODULE;
318 dasd_devices_entry = create_proc_entry("devices", 319 dasd_devices_entry = proc_create("devices",
319 S_IFREG | S_IRUGO | S_IWUSR, 320 S_IFREG | S_IRUGO | S_IWUSR,
320 dasd_proc_root_entry); 321 dasd_proc_root_entry,
322 &dasd_devices_file_ops);
321 if (!dasd_devices_entry) 323 if (!dasd_devices_entry)
322 goto out_nodevices; 324 goto out_nodevices;
323 dasd_devices_entry->proc_fops = &dasd_devices_file_ops;
324 dasd_devices_entry->owner = THIS_MODULE;
325 dasd_statistics_entry = create_proc_entry("statistics", 325 dasd_statistics_entry = create_proc_entry("statistics",
326 S_IFREG | S_IRUGO | S_IWUSR, 326 S_IFREG | S_IRUGO | S_IWUSR,
327 dasd_proc_root_entry); 327 dasd_proc_root_entry);
@@ -335,7 +335,7 @@ dasd_proc_init(void)
335 out_nostatistics: 335 out_nostatistics:
336 remove_proc_entry("devices", dasd_proc_root_entry); 336 remove_proc_entry("devices", dasd_proc_root_entry);
337 out_nodevices: 337 out_nodevices:
338 remove_proc_entry("dasd", &proc_root); 338 remove_proc_entry("dasd", NULL);
339 out_nodasd: 339 out_nodasd:
340 return -ENOENT; 340 return -ENOENT;
341} 341}
@@ -345,5 +345,5 @@ dasd_proc_exit(void)
345{ 345{
346 remove_proc_entry("devices", dasd_proc_root_entry); 346 remove_proc_entry("devices", dasd_proc_root_entry);
347 remove_proc_entry("statistics", dasd_proc_root_entry); 347 remove_proc_entry("statistics", dasd_proc_root_entry);
348 remove_proc_entry("dasd", &proc_root); 348 remove_proc_entry("dasd", NULL);
349} 349}
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 04787eab1016..bb52d2fbac18 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -36,7 +36,7 @@ static int dcssblk_open(struct inode *inode, struct file *filp);
36static int dcssblk_release(struct inode *inode, struct file *filp); 36static int dcssblk_release(struct inode *inode, struct file *filp);
37static int dcssblk_make_request(struct request_queue *q, struct bio *bio); 37static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
38static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum, 38static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
39 unsigned long *data); 39 void **kaddr, unsigned long *pfn);
40 40
41static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0"; 41static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
42 42
@@ -636,7 +636,7 @@ fail:
636 636
637static int 637static int
638dcssblk_direct_access (struct block_device *bdev, sector_t secnum, 638dcssblk_direct_access (struct block_device *bdev, sector_t secnum,
639 unsigned long *data) 639 void **kaddr, unsigned long *pfn)
640{ 640{
641 struct dcssblk_dev_info *dev_info; 641 struct dcssblk_dev_info *dev_info;
642 unsigned long pgoff; 642 unsigned long pgoff;
@@ -649,7 +649,9 @@ dcssblk_direct_access (struct block_device *bdev, sector_t secnum,
649 pgoff = secnum / (PAGE_SIZE / 512); 649 pgoff = secnum / (PAGE_SIZE / 512);
650 if ((pgoff+1)*PAGE_SIZE-1 > dev_info->end - dev_info->start) 650 if ((pgoff+1)*PAGE_SIZE-1 > dev_info->end - dev_info->start)
651 return -ERANGE; 651 return -ERANGE;
652 *data = (unsigned long) (dev_info->start+pgoff*PAGE_SIZE); 652 *kaddr = (void *) (dev_info->start+pgoff*PAGE_SIZE);
653 *pfn = virt_to_phys(*kaddr) >> PAGE_SHIFT;
654
653 return 0; 655 return 0;
654} 656}
655 657
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,
982/* 982/*
983 * Put character routine for 3215 ttys 983 * Put character routine for 3215 ttys
984 */ 984 */
985static void 985static int
986tty3215_put_char(struct tty_struct *tty, unsigned char ch) 986tty3215_put_char(struct tty_struct *tty, unsigned char ch)
987{ 987{
988 struct raw3215_info *raw; 988 struct raw3215_info *raw;
989 989
990 if (!tty) 990 if (!tty)
991 return; 991 return 0;
992 raw = (struct raw3215_info *) tty->driver_data; 992 raw = (struct raw3215_info *) tty->driver_data;
993 raw3215_putchar(raw, ch); 993 raw3215_putchar(raw, ch);
994 return 1;
994} 995}
995 996
996static void 997static 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 @@
10#include <linux/cpu.h> 10#include <linux/cpu.h>
11#include <linux/sysdev.h> 11#include <linux/sysdev.h>
12#include <linux/workqueue.h> 12#include <linux/workqueue.h>
13#include <asm/smp.h>
13#include "sclp.h" 14#include "sclp.h"
14 15
15#define TAG "sclp_config: " 16#define TAG "sclp_config: "
@@ -19,9 +20,11 @@ struct conf_mgm_data {
19 u8 ev_qualifier; 20 u8 ev_qualifier;
20} __attribute__((packed)); 21} __attribute__((packed));
21 22
23#define EV_QUAL_CPU_CHANGE 1
22#define EV_QUAL_CAP_CHANGE 3 24#define EV_QUAL_CAP_CHANGE 3
23 25
24static struct work_struct sclp_cpu_capability_work; 26static struct work_struct sclp_cpu_capability_work;
27static struct work_struct sclp_cpu_change_work;
25 28
26static void sclp_cpu_capability_notify(struct work_struct *work) 29static void sclp_cpu_capability_notify(struct work_struct *work)
27{ 30{
@@ -37,13 +40,24 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
37 put_online_cpus(); 40 put_online_cpus();
38} 41}
39 42
43static void sclp_cpu_change_notify(struct work_struct *work)
44{
45 smp_rescan_cpus();
46}
47
40static void sclp_conf_receiver_fn(struct evbuf_header *evbuf) 48static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
41{ 49{
42 struct conf_mgm_data *cdata; 50 struct conf_mgm_data *cdata;
43 51
44 cdata = (struct conf_mgm_data *)(evbuf + 1); 52 cdata = (struct conf_mgm_data *)(evbuf + 1);
45 if (cdata->ev_qualifier == EV_QUAL_CAP_CHANGE) 53 switch (cdata->ev_qualifier) {
54 case EV_QUAL_CPU_CHANGE:
55 schedule_work(&sclp_cpu_change_work);
56 break;
57 case EV_QUAL_CAP_CHANGE:
46 schedule_work(&sclp_cpu_capability_work); 58 schedule_work(&sclp_cpu_capability_work);
59 break;
60 }
47} 61}
48 62
49static struct sclp_register sclp_conf_register = 63static struct sclp_register sclp_conf_register =
@@ -57,6 +71,7 @@ static int __init sclp_conf_init(void)
57 int rc; 71 int rc;
58 72
59 INIT_WORK(&sclp_cpu_capability_work, sclp_cpu_capability_notify); 73 INIT_WORK(&sclp_cpu_capability_work, sclp_cpu_capability_notify);
74 INIT_WORK(&sclp_cpu_change_work, sclp_cpu_change_notify);
60 75
61 rc = sclp_register(&sclp_conf_register); 76 rc = sclp_register(&sclp_conf_register);
62 if (rc) { 77 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)
412 * - including previous characters from sclp_tty_put_char() and strings from 412 * - including previous characters from sclp_tty_put_char() and strings from
413 * sclp_write() without final '\n' - will be written. 413 * sclp_write() without final '\n' - will be written.
414 */ 414 */
415static void 415static int
416sclp_tty_put_char(struct tty_struct *tty, unsigned char ch) 416sclp_tty_put_char(struct tty_struct *tty, unsigned char ch)
417{ 417{
418 sclp_tty_chars[sclp_tty_chars_count++] = ch; 418 sclp_tty_chars[sclp_tty_chars_count++] = ch;
419 if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) { 419 if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) {
420 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count); 420 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
421 sclp_tty_chars_count = 0; 421 sclp_tty_chars_count = 0;
422 } 422 } return 1;
423} 423}
424 424
425/* 425/*
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)
524 * NOTE: include/linux/tty_driver.h specifies that a character should be 524 * NOTE: include/linux/tty_driver.h specifies that a character should be
525 * ignored if there is no room in the queue. This driver implements a different 525 * ignored if there is no room in the queue. This driver implements a different
526 * semantic in that it will block when there is no more room left. 526 * semantic in that it will block when there is no more room left.
527 *
528 * FIXME: putchar can currently be called from BH and other non blocking
529 * handlers so this semantic isn't a good idea.
527 */ 530 */
528static void 531static int
529sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch) 532sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch)
530{ 533{
531 __sclp_vt220_write(&ch, 1, 0, 0, 1); 534 __sclp_vt220_write(&ch, 1, 0, 0, 1);
535 return 1;
532} 536}
533 537
534/* 538/*
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)
111 111
112static const struct file_operations tape_proc_ops = 112static const struct file_operations tape_proc_ops =
113{ 113{
114 .owner = THIS_MODULE,
114 .open = tape_proc_open, 115 .open = tape_proc_open,
115 .read = seq_read, 116 .read = seq_read,
116 .llseek = seq_lseek, 117 .llseek = seq_lseek,
@@ -124,14 +125,12 @@ void
124tape_proc_init(void) 125tape_proc_init(void)
125{ 126{
126 tape_proc_devices = 127 tape_proc_devices =
127 create_proc_entry ("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, 128 proc_create("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, NULL,
128 &proc_root); 129 &tape_proc_ops);
129 if (tape_proc_devices == NULL) { 130 if (tape_proc_devices == NULL) {
130 PRINT_WARN("tape: Cannot register procfs entry tapedevices\n"); 131 PRINT_WARN("tape: Cannot register procfs entry tapedevices\n");
131 return; 132 return;
132 } 133 }
133 tape_proc_devices->proc_fops = &tape_proc_ops;
134 tape_proc_devices->owner = THIS_MODULE;
135} 134}
136 135
137/* 136/*
@@ -141,5 +140,5 @@ void
141tape_proc_cleanup(void) 140tape_proc_cleanup(void)
142{ 141{
143 if (tape_proc_devices != NULL) 142 if (tape_proc_devices != NULL)
144 remove_proc_entry ("tapedevices", &proc_root); 143 remove_proc_entry ("tapedevices", NULL);
145} 144}
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 70b1980a08b6..c1f2adefad41 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -965,7 +965,7 @@ tty3270_write_room(struct tty_struct *tty)
965 * Insert character into the screen at the current position with the 965 * Insert character into the screen at the current position with the
966 * current color and highlight. This function does NOT do cursor movement. 966 * current color and highlight. This function does NOT do cursor movement.
967 */ 967 */
968static void 968static int
969tty3270_put_character(struct tty3270 *tp, char ch) 969tty3270_put_character(struct tty3270 *tp, char ch)
970{ 970{
971 struct tty3270_line *line; 971 struct tty3270_line *line;
@@ -986,6 +986,7 @@ tty3270_put_character(struct tty3270 *tp, char ch)
986 cell->character = tp->view.ascebc[(unsigned int) ch]; 986 cell->character = tp->view.ascebc[(unsigned int) ch];
987 cell->highlight = tp->highlight; 987 cell->highlight = tp->highlight;
988 cell->f_color = tp->f_color; 988 cell->f_color = tp->f_color;
989 return 1;
989} 990}
990 991
991/* 992/*
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index e8597ec92247..40ef948fcb3a 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -374,13 +374,10 @@ cio_ignore_proc_init (void)
374{ 374{
375 struct proc_dir_entry *entry; 375 struct proc_dir_entry *entry;
376 376
377 entry = create_proc_entry ("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR, 377 entry = proc_create("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR, NULL,
378 &proc_root); 378 &cio_ignore_proc_fops);
379 if (!entry) 379 if (!entry)
380 return -ENOENT; 380 return -ENOENT;
381
382 entry->proc_fops = &cio_ignore_proc_fops;
383
384 return 0; 381 return 0;
385} 382}
386 383
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)
152 return 0; 152 return 0;
153} 153}
154 154
155static int __get_next_bus_id(const char **buf, char *bus_id)
156{
157 int rc, len;
158 char *start, *end;
159
160 start = (char *)*buf;
161 end = strchr(start, ',');
162 if (!end) {
163 /* Last entry. Strip trailing newline, if applicable. */
164 end = strchr(start, '\n');
165 if (end)
166 *end = '\0';
167 len = strlen(start) + 1;
168 } else {
169 len = end - start + 1;
170 end++;
171 }
172 if (len < BUS_ID_SIZE) {
173 strlcpy(bus_id, start, len);
174 rc = 0;
175 } else
176 rc = -EINVAL;
177 *buf = end;
178 return rc;
179}
180
181static int __is_valid_bus_id(char bus_id[BUS_ID_SIZE])
182{
183 int cssid, ssid, devno;
184
185 /* Must be of form %x.%x.%04x */
186 if (sscanf(bus_id, "%x.%1x.%04x", &cssid, &ssid, &devno) != 3)
187 return 0;
188 return 1;
189}
190
155/** 191/**
156 * ccwgroup_create() - create and register a ccw group device 192 * ccwgroup_create_from_string() - create and register a ccw group device
157 * @root: parent device for the new device 193 * @root: parent device for the new device
158 * @creator_id: identifier of creating driver 194 * @creator_id: identifier of creating driver
159 * @cdrv: ccw driver of slave devices 195 * @cdrv: ccw driver of slave devices
160 * @argc: number of slave devices 196 * @num_devices: number of slave devices
161 * @argv: bus ids of slave devices 197 * @buf: buffer containing comma separated bus ids of slave devices
162 * 198 *
163 * Create and register a new ccw group device as a child of @root. Slave 199 * Create and register a new ccw group device as a child of @root. Slave
164 * devices are obtained from the list of bus ids given in @argv[] and must all 200 * devices are obtained from the list of bus ids given in @buf and must all
165 * belong to @cdrv. 201 * belong to @cdrv.
166 * Returns: 202 * Returns:
167 * %0 on success and an error code on failure. 203 * %0 on success and an error code on failure.
168 * Context: 204 * Context:
169 * non-atomic 205 * non-atomic
170 */ 206 */
171int ccwgroup_create(struct device *root, unsigned int creator_id, 207int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
172 struct ccw_driver *cdrv, int argc, char *argv[]) 208 struct ccw_driver *cdrv, int num_devices,
209 const char *buf)
173{ 210{
174 struct ccwgroup_device *gdev; 211 struct ccwgroup_device *gdev;
175 int i; 212 int rc, i;
176 int rc; 213 char tmp_bus_id[BUS_ID_SIZE];
214 const char *curr_buf;
177 215
178 if (argc > 256) /* disallow dumb users */ 216 gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]),
179 return -EINVAL; 217 GFP_KERNEL);
180
181 gdev = kzalloc(sizeof(*gdev) + argc*sizeof(gdev->cdev[0]), GFP_KERNEL);
182 if (!gdev) 218 if (!gdev)
183 return -ENOMEM; 219 return -ENOMEM;
184 220
185 atomic_set(&gdev->onoff, 0); 221 atomic_set(&gdev->onoff, 0);
186 mutex_init(&gdev->reg_mutex); 222 mutex_init(&gdev->reg_mutex);
187 mutex_lock(&gdev->reg_mutex); 223 mutex_lock(&gdev->reg_mutex);
188 for (i = 0; i < argc; i++) { 224 curr_buf = buf;
189 gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]); 225 for (i = 0; i < num_devices && curr_buf; i++) {
190 226 rc = __get_next_bus_id(&curr_buf, tmp_bus_id);
191 /* all devices have to be of the same type in 227 if (rc != 0)
192 * order to be grouped */ 228 goto error;
229 if (!__is_valid_bus_id(tmp_bus_id)) {
230 rc = -EINVAL;
231 goto error;
232 }
233 gdev->cdev[i] = get_ccwdev_by_busid(cdrv, tmp_bus_id);
234 /*
235 * All devices have to be of the same type in
236 * order to be grouped.
237 */
193 if (!gdev->cdev[i] 238 if (!gdev->cdev[i]
194 || gdev->cdev[i]->id.driver_info != 239 || gdev->cdev[i]->id.driver_info !=
195 gdev->cdev[0]->id.driver_info) { 240 gdev->cdev[0]->id.driver_info) {
@@ -203,9 +248,18 @@ int ccwgroup_create(struct device *root, unsigned int creator_id,
203 } 248 }
204 dev_set_drvdata(&gdev->cdev[i]->dev, gdev); 249 dev_set_drvdata(&gdev->cdev[i]->dev, gdev);
205 } 250 }
206 251 /* Check for sufficient number of bus ids. */
252 if (i < num_devices && !curr_buf) {
253 rc = -EINVAL;
254 goto error;
255 }
256 /* Check for trailing stuff. */
257 if (i == num_devices && strlen(curr_buf) > 0) {
258 rc = -EINVAL;
259 goto error;
260 }
207 gdev->creator_id = creator_id; 261 gdev->creator_id = creator_id;
208 gdev->count = argc; 262 gdev->count = num_devices;
209 gdev->dev.bus = &ccwgroup_bus_type; 263 gdev->dev.bus = &ccwgroup_bus_type;
210 gdev->dev.parent = root; 264 gdev->dev.parent = root;
211 gdev->dev.release = ccwgroup_release; 265 gdev->dev.release = ccwgroup_release;
@@ -233,7 +287,7 @@ int ccwgroup_create(struct device *root, unsigned int creator_id,
233 device_remove_file(&gdev->dev, &dev_attr_ungroup); 287 device_remove_file(&gdev->dev, &dev_attr_ungroup);
234 device_unregister(&gdev->dev); 288 device_unregister(&gdev->dev);
235error: 289error:
236 for (i = 0; i < argc; i++) 290 for (i = 0; i < num_devices; i++)
237 if (gdev->cdev[i]) { 291 if (gdev->cdev[i]) {
238 if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) 292 if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev)
239 dev_set_drvdata(&gdev->cdev[i]->dev, NULL); 293 dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
@@ -243,6 +297,7 @@ error:
243 put_device(&gdev->dev); 297 put_device(&gdev->dev);
244 return rc; 298 return rc;
245} 299}
300EXPORT_SYMBOL(ccwgroup_create_from_string);
246 301
247static int __init 302static int __init
248init_ccwgroup (void) 303init_ccwgroup (void)
@@ -318,7 +373,7 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
318{ 373{
319 struct ccwgroup_device *gdev; 374 struct ccwgroup_device *gdev;
320 struct ccwgroup_driver *gdrv; 375 struct ccwgroup_driver *gdrv;
321 unsigned int value; 376 unsigned long value;
322 int ret; 377 int ret;
323 378
324 gdev = to_ccwgroupdev(dev); 379 gdev = to_ccwgroupdev(dev);
@@ -329,7 +384,9 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
329 if (!try_module_get(gdrv->owner)) 384 if (!try_module_get(gdrv->owner))
330 return -EINVAL; 385 return -EINVAL;
331 386
332 value = simple_strtoul(buf, NULL, 0); 387 ret = strict_strtoul(buf, 0, &value);
388 if (ret)
389 goto out;
333 ret = count; 390 ret = count;
334 if (value == 1) 391 if (value == 1)
335 ccwgroup_set_online(gdev); 392 ccwgroup_set_online(gdev);
@@ -337,6 +394,7 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
337 ccwgroup_set_offline(gdev); 394 ccwgroup_set_offline(gdev);
338 else 395 else
339 ret = -EINVAL; 396 ret = -EINVAL;
397out:
340 module_put(gdrv->owner); 398 module_put(gdrv->owner);
341 return ret; 399 return ret;
342} 400}
@@ -518,6 +576,5 @@ void ccwgroup_remove_ccwdev(struct ccw_device *cdev)
518MODULE_LICENSE("GPL"); 576MODULE_LICENSE("GPL");
519EXPORT_SYMBOL(ccwgroup_driver_register); 577EXPORT_SYMBOL(ccwgroup_driver_register);
520EXPORT_SYMBOL(ccwgroup_driver_unregister); 578EXPORT_SYMBOL(ccwgroup_driver_unregister);
521EXPORT_SYMBOL(ccwgroup_create);
522EXPORT_SYMBOL(ccwgroup_probe_ccwdev); 579EXPORT_SYMBOL(ccwgroup_probe_ccwdev);
523EXPORT_SYMBOL(ccwgroup_remove_ccwdev); 580EXPORT_SYMBOL(ccwgroup_remove_ccwdev);
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 23ffcc4768a7..08a578161306 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -407,8 +407,7 @@ cio_modify (struct subchannel *sch)
407/* 407/*
408 * Enable subchannel. 408 * Enable subchannel.
409 */ 409 */
410int cio_enable_subchannel(struct subchannel *sch, unsigned int isc, 410int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
411 u32 intparm)
412{ 411{
413 char dbf_txt[15]; 412 char dbf_txt[15];
414 int ccode; 413 int ccode;
@@ -426,7 +425,7 @@ int cio_enable_subchannel(struct subchannel *sch, unsigned int isc,
426 425
427 for (retry = 5, ret = 0; retry > 0; retry--) { 426 for (retry = 5, ret = 0; retry > 0; retry--) {
428 sch->schib.pmcw.ena = 1; 427 sch->schib.pmcw.ena = 1;
429 sch->schib.pmcw.isc = isc; 428 sch->schib.pmcw.isc = sch->isc;
430 sch->schib.pmcw.intparm = intparm; 429 sch->schib.pmcw.intparm = intparm;
431 ret = cio_modify(sch); 430 ret = cio_modify(sch);
432 if (ret == -ENODEV) 431 if (ret == -ENODEV)
@@ -600,6 +599,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
600 else 599 else
601 sch->opm = chp_get_sch_opm(sch); 600 sch->opm = chp_get_sch_opm(sch);
602 sch->lpm = sch->schib.pmcw.pam & sch->opm; 601 sch->lpm = sch->schib.pmcw.pam & sch->opm;
602 sch->isc = 3;
603 603
604 CIO_DEBUG(KERN_INFO, 0, 604 CIO_DEBUG(KERN_INFO, 0,
605 "Detected device %04x on subchannel 0.%x.%04X" 605 "Detected device %04x on subchannel 0.%x.%04X"
@@ -610,13 +610,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
610 610
611 /* 611 /*
612 * We now have to initially ... 612 * We now have to initially ...
613 * ... set "interruption subclass"
614 * ... enable "concurrent sense" 613 * ... enable "concurrent sense"
615 * ... enable "multipath mode" if more than one 614 * ... enable "multipath mode" if more than one
616 * CHPID is available. This is done regardless 615 * CHPID is available. This is done regardless
617 * whether multiple paths are available for us. 616 * whether multiple paths are available for us.
618 */ 617 */
619 sch->schib.pmcw.isc = 3; /* could be smth. else */
620 sch->schib.pmcw.csense = 1; /* concurrent sense */ 618 sch->schib.pmcw.csense = 1; /* concurrent sense */
621 sch->schib.pmcw.ena = 0; 619 sch->schib.pmcw.ena = 0;
622 if ((sch->lpm & (sch->lpm - 1)) != 0) 620 if ((sch->lpm & (sch->lpm - 1)) != 0)
@@ -812,6 +810,7 @@ cio_probe_console(void)
812 * enable console I/O-interrupt subclass 7 810 * enable console I/O-interrupt subclass 7
813 */ 811 */
814 ctl_set_bit(6, 24); 812 ctl_set_bit(6, 24);
813 console_subchannel.isc = 7;
815 console_subchannel.schib.pmcw.isc = 7; 814 console_subchannel.schib.pmcw.isc = 7;
816 console_subchannel.schib.pmcw.intparm = 815 console_subchannel.schib.pmcw.intparm =
817 (u32)(addr_t)&console_subchannel; 816 (u32)(addr_t)&console_subchannel;
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 08f2235c5a6f..3c75412904dc 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -74,6 +74,7 @@ struct subchannel {
74 __u8 lpm; /* logical path mask */ 74 __u8 lpm; /* logical path mask */
75 __u8 opm; /* operational path mask */ 75 __u8 opm; /* operational path mask */
76 struct schib schib; /* subchannel information block */ 76 struct schib schib; /* subchannel information block */
77 int isc; /* desired interruption subclass */
77 struct chsc_ssd_info ssd_info; /* subchannel description */ 78 struct chsc_ssd_info ssd_info; /* subchannel description */
78 struct device dev; /* entry in device tree */ 79 struct device dev; /* entry in device tree */
79 struct css_driver *driver; 80 struct css_driver *driver;
@@ -85,7 +86,7 @@ struct subchannel {
85#define to_subchannel(n) container_of(n, struct subchannel, dev) 86#define to_subchannel(n) container_of(n, struct subchannel, dev)
86 87
87extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); 88extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
88extern int cio_enable_subchannel(struct subchannel *, unsigned int, u32); 89extern int cio_enable_subchannel(struct subchannel *, u32);
89extern int cio_disable_subchannel (struct subchannel *); 90extern int cio_disable_subchannel (struct subchannel *);
90extern int cio_cancel (struct subchannel *); 91extern int cio_cancel (struct subchannel *);
91extern int cio_clear (struct subchannel *); 92extern int cio_clear (struct subchannel *);
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,
1219{ 1219{
1220 struct ccw_device *cdev; 1220 struct ccw_device *cdev;
1221 int ret; 1221 int ret;
1222 unsigned long val;
1223
1224 ret = strict_strtoul(buf, 16, &val);
1225 if (ret)
1226 return ret;
1222 1227
1223 cdev = to_ccwdev(dev); 1228 cdev = to_ccwdev(dev);
1224 1229
1225 switch (buf[0]) { 1230 switch (val) {
1226 case '0': 1231 case 0:
1227 ret = disable_cmf(cdev); 1232 ret = disable_cmf(cdev);
1228 if (ret) 1233 if (ret)
1229 dev_info(&cdev->dev, "disable_cmf failed (%d)\n", ret); 1234 dev_info(&cdev->dev, "disable_cmf failed (%d)\n", ret);
1230 break; 1235 break;
1231 case '1': 1236 case 1:
1232 ret = enable_cmf(cdev); 1237 ret = enable_cmf(cdev);
1233 if (ret && ret != -EBUSY) 1238 if (ret && ret != -EBUSY)
1234 dev_info(&cdev->dev, "enable_cmf failed (%d)\n", ret); 1239 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..595e327d2f76 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -705,13 +705,17 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
705{ 705{
706 struct channel_subsystem *css = to_css(dev); 706 struct channel_subsystem *css = to_css(dev);
707 int ret; 707 int ret;
708 unsigned long val;
708 709
710 ret = strict_strtoul(buf, 16, &val);
711 if (ret)
712 return ret;
709 mutex_lock(&css->mutex); 713 mutex_lock(&css->mutex);
710 switch (buf[0]) { 714 switch (val) {
711 case '0': 715 case 0:
712 ret = css->cm_enabled ? chsc_secm(css, 0) : 0; 716 ret = css->cm_enabled ? chsc_secm(css, 0) : 0;
713 break; 717 break;
714 case '1': 718 case 1:
715 ret = css->cm_enabled ? 0 : chsc_secm(css, 1); 719 ret = css->cm_enabled ? 0 : chsc_secm(css, 1);
716 break; 720 break;
717 default: 721 default:
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index e0c7adb8958e..abfd601d237a 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -512,8 +512,8 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
512 const char *buf, size_t count) 512 const char *buf, size_t count)
513{ 513{
514 struct ccw_device *cdev = to_ccwdev(dev); 514 struct ccw_device *cdev = to_ccwdev(dev);
515 int i, force; 515 int force, ret;
516 char *tmp; 516 unsigned long i;
517 517
518 if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0) 518 if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0)
519 return -EAGAIN; 519 return -EAGAIN;
@@ -525,25 +525,30 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
525 if (!strncmp(buf, "force\n", count)) { 525 if (!strncmp(buf, "force\n", count)) {
526 force = 1; 526 force = 1;
527 i = 1; 527 i = 1;
528 ret = 0;
528 } else { 529 } else {
529 force = 0; 530 force = 0;
530 i = simple_strtoul(buf, &tmp, 16); 531 ret = strict_strtoul(buf, 16, &i);
531 } 532 }
532 533 if (ret)
534 goto out;
533 switch (i) { 535 switch (i) {
534 case 0: 536 case 0:
535 online_store_handle_offline(cdev); 537 online_store_handle_offline(cdev);
538 ret = count;
536 break; 539 break;
537 case 1: 540 case 1:
538 online_store_handle_online(cdev, force); 541 online_store_handle_online(cdev, force);
542 ret = count;
539 break; 543 break;
540 default: 544 default:
541 count = -EINVAL; 545 ret = -EINVAL;
542 } 546 }
547out:
543 if (cdev->drv) 548 if (cdev->drv)
544 module_put(cdev->drv->owner); 549 module_put(cdev->drv->owner);
545 atomic_set(&cdev->private->onoff, 0); 550 atomic_set(&cdev->private->onoff, 0);
546 return count; 551 return ret;
547} 552}
548 553
549static ssize_t 554static ssize_t
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 4b92c84fb438..99403b0a97a7 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -555,8 +555,7 @@ ccw_device_recognition(struct ccw_device *cdev)
555 (cdev->private->state != DEV_STATE_BOXED)) 555 (cdev->private->state != DEV_STATE_BOXED))
556 return -EINVAL; 556 return -EINVAL;
557 sch = to_subchannel(cdev->dev.parent); 557 sch = to_subchannel(cdev->dev.parent);
558 ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc, 558 ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
559 (u32)(addr_t)sch);
560 if (ret != 0) 559 if (ret != 0)
561 /* Couldn't enable the subchannel for i/o. Sick device. */ 560 /* Couldn't enable the subchannel for i/o. Sick device. */
562 return ret; 561 return ret;
@@ -667,8 +666,7 @@ ccw_device_online(struct ccw_device *cdev)
667 sch = to_subchannel(cdev->dev.parent); 666 sch = to_subchannel(cdev->dev.parent);
668 if (css_init_done && !get_device(&cdev->dev)) 667 if (css_init_done && !get_device(&cdev->dev))
669 return -ENODEV; 668 return -ENODEV;
670 ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc, 669 ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
671 (u32)(addr_t)sch);
672 if (ret != 0) { 670 if (ret != 0) {
673 /* Couldn't enable the subchannel for i/o. Sick device. */ 671 /* Couldn't enable the subchannel for i/o. Sick device. */
674 if (ret == -ENODEV) 672 if (ret == -ENODEV)
@@ -1048,8 +1046,7 @@ ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event)
1048 struct subchannel *sch; 1046 struct subchannel *sch;
1049 1047
1050 sch = to_subchannel(cdev->dev.parent); 1048 sch = to_subchannel(cdev->dev.parent);
1051 if (cio_enable_subchannel(sch, sch->schib.pmcw.isc, 1049 if (cio_enable_subchannel(sch, (u32)(addr_t)sch) != 0)
1052 (u32)(addr_t)sch) != 0)
1053 /* Couldn't enable the subchannel for i/o. Sick device. */ 1050 /* Couldn't enable the subchannel for i/o. Sick device. */
1054 return; 1051 return;
1055 1052
@@ -1082,7 +1079,6 @@ device_trigger_reprobe(struct subchannel *sch)
1082 */ 1079 */
1083 sch->lpm = sch->schib.pmcw.pam & sch->opm; 1080 sch->lpm = sch->schib.pmcw.pam & sch->opm;
1084 /* Re-set some bits in the pmcw that were lost. */ 1081 /* Re-set some bits in the pmcw that were lost. */
1085 sch->schib.pmcw.isc = 3;
1086 sch->schib.pmcw.csense = 1; 1082 sch->schib.pmcw.csense = 1;
1087 sch->schib.pmcw.ena = 0; 1083 sch->schib.pmcw.ena = 0;
1088 if ((sch->lpm & (sch->lpm - 1)) != 0) 1084 if ((sch->lpm & (sch->lpm - 1)) != 0)
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)
508 return -ENOMEM; 508 return -ENOMEM;
509 } 509 }
510 spin_lock_irqsave(sch->lock, flags); 510 spin_lock_irqsave(sch->lock, flags);
511 ret = cio_enable_subchannel(sch, 3, (u32)(addr_t)sch); 511 ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
512 if (ret) 512 if (ret)
513 goto out_unlock; 513 goto out_unlock;
514 /* 514 /*
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)
3632{ 3632{
3633 proc_perf_file_registration=0; 3633 proc_perf_file_registration=0;
3634 qdio_perf_proc_file=create_proc_entry(QDIO_PERF, 3634 qdio_perf_proc_file=create_proc_entry(QDIO_PERF,
3635 S_IFREG|0444,&proc_root); 3635 S_IFREG|0444,NULL);
3636 if (qdio_perf_proc_file) { 3636 if (qdio_perf_proc_file) {
3637 qdio_perf_proc_file->read_proc=&qdio_perf_procfile_read; 3637 qdio_perf_proc_file->read_proc=&qdio_perf_procfile_read;
3638 } else proc_perf_file_registration=-1; 3638 } else proc_perf_file_registration=-1;
@@ -3647,7 +3647,7 @@ static void
3647qdio_remove_procfs_entry(void) 3647qdio_remove_procfs_entry(void)
3648{ 3648{
3649 if (!proc_perf_file_registration) /* means if it went ok earlier */ 3649 if (!proc_perf_file_registration) /* means if it went ok earlier */
3650 remove_proc_entry(QDIO_PERF,&proc_root); 3650 remove_proc_entry(QDIO_PERF,NULL);
3651} 3651}
3652 3652
3653/** 3653/**
@@ -3663,11 +3663,11 @@ qdio_performance_stats_show(struct bus_type *bus, char *buf)
3663static ssize_t 3663static ssize_t
3664qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count) 3664qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count)
3665{ 3665{
3666 char *tmp; 3666 unsigned long i;
3667 int i; 3667 int ret;
3668 3668
3669 i = simple_strtoul(buf, &tmp, 16); 3669 ret = strict_strtoul(buf, 16, &i);
3670 if ((i == 0) || (i == 1)) { 3670 if (!ret && ((i == 0) || (i == 1))) {
3671 if (i == qdio_performance_stats) 3671 if (i == qdio_performance_stats)
3672 return count; 3672 return count;
3673 qdio_performance_stats = i; 3673 qdio_performance_stats = i;
diff --git a/drivers/s390/kvm/Makefile b/drivers/s390/kvm/Makefile
new file mode 100644
index 000000000000..4a5ec39f9ca6
--- /dev/null
+++ b/drivers/s390/kvm/Makefile
@@ -0,0 +1,9 @@
1# Makefile for kvm guest drivers on s390
2#
3# Copyright IBM Corp. 2008
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License (version 2 only)
7# as published by the Free Software Foundation.
8
9obj-$(CONFIG_VIRTIO) += kvm_virtio.o
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
new file mode 100644
index 000000000000..47a7e6200b26
--- /dev/null
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -0,0 +1,339 @@
1/*
2 * kvm_virtio.c - virtio for kvm on s390
3 *
4 * Copyright IBM Corp. 2008
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License (version 2 only)
8 * as published by the Free Software Foundation.
9 *
10 * Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
11 */
12
13#include <linux/init.h>
14#include <linux/bootmem.h>
15#include <linux/err.h>
16#include <linux/virtio.h>
17#include <linux/virtio_config.h>
18#include <linux/interrupt.h>
19#include <linux/virtio_ring.h>
20#include <linux/pfn.h>
21#include <asm/io.h>
22#include <asm/kvm_para.h>
23#include <asm/kvm_virtio.h>
24#include <asm/setup.h>
25#include <asm/s390_ext.h>
26
27#define VIRTIO_SUBCODE_64 0x0D00
28
29/*
30 * The pointer to our (page) of device descriptions.
31 */
32static void *kvm_devices;
33
34/*
35 * Unique numbering for kvm devices.
36 */
37static unsigned int dev_index;
38
39struct kvm_device {
40 struct virtio_device vdev;
41 struct kvm_device_desc *desc;
42};
43
44#define to_kvmdev(vd) container_of(vd, struct kvm_device, vdev)
45
46/*
47 * memory layout:
48 * - kvm_device_descriptor
49 * struct kvm_device_desc
50 * - configuration
51 * struct kvm_vqconfig
52 * - feature bits
53 * - config space
54 */
55static struct kvm_vqconfig *kvm_vq_config(const struct kvm_device_desc *desc)
56{
57 return (struct kvm_vqconfig *)(desc + 1);
58}
59
60static u8 *kvm_vq_features(const struct kvm_device_desc *desc)
61{
62 return (u8 *)(kvm_vq_config(desc) + desc->num_vq);
63}
64
65static u8 *kvm_vq_configspace(const struct kvm_device_desc *desc)
66{
67 return kvm_vq_features(desc) + desc->feature_len * 2;
68}
69
70/*
71 * The total size of the config page used by this device (incl. desc)
72 */
73static unsigned desc_size(const struct kvm_device_desc *desc)
74{
75 return sizeof(*desc)
76 + desc->num_vq * sizeof(struct kvm_vqconfig)
77 + desc->feature_len * 2
78 + desc->config_len;
79}
80
81/*
82 * This tests (and acknowleges) a feature bit.
83 */
84static bool kvm_feature(struct virtio_device *vdev, unsigned fbit)
85{
86 struct kvm_device_desc *desc = to_kvmdev(vdev)->desc;
87 u8 *features;
88
89 if (fbit / 8 > desc->feature_len)
90 return false;
91
92 features = kvm_vq_features(desc);
93 if (!(features[fbit / 8] & (1 << (fbit % 8))))
94 return false;
95
96 /*
97 * We set the matching bit in the other half of the bitmap to tell the
98 * Host we want to use this feature.
99 */
100 features[desc->feature_len + fbit / 8] |= (1 << (fbit % 8));
101 return true;
102}
103
104/*
105 * Reading and writing elements in config space
106 */
107static void kvm_get(struct virtio_device *vdev, unsigned int offset,
108 void *buf, unsigned len)
109{
110 struct kvm_device_desc *desc = to_kvmdev(vdev)->desc;
111
112 BUG_ON(offset + len > desc->config_len);
113 memcpy(buf, kvm_vq_configspace(desc) + offset, len);
114}
115
116static void kvm_set(struct virtio_device *vdev, unsigned int offset,
117 const void *buf, unsigned len)
118{
119 struct kvm_device_desc *desc = to_kvmdev(vdev)->desc;
120
121 BUG_ON(offset + len > desc->config_len);
122 memcpy(kvm_vq_configspace(desc) + offset, buf, len);
123}
124
125/*
126 * The operations to get and set the status word just access
127 * the status field of the device descriptor. set_status will also
128 * make a hypercall to the host, to tell about status changes
129 */
130static u8 kvm_get_status(struct virtio_device *vdev)
131{
132 return to_kvmdev(vdev)->desc->status;
133}
134
135static void kvm_set_status(struct virtio_device *vdev, u8 status)
136{
137 BUG_ON(!status);
138 to_kvmdev(vdev)->desc->status = status;
139 kvm_hypercall1(KVM_S390_VIRTIO_SET_STATUS,
140 (unsigned long) to_kvmdev(vdev)->desc);
141}
142
143/*
144 * To reset the device, we use the KVM_VIRTIO_RESET hypercall, using the
145 * descriptor address. The Host will zero the status and all the
146 * features.
147 */
148static void kvm_reset(struct virtio_device *vdev)
149{
150 kvm_hypercall1(KVM_S390_VIRTIO_RESET,
151 (unsigned long) to_kvmdev(vdev)->desc);
152}
153
154/*
155 * When the virtio_ring code wants to notify the Host, it calls us here and we
156 * make a hypercall. We hand the address of the virtqueue so the Host
157 * knows which virtqueue we're talking about.
158 */
159static void kvm_notify(struct virtqueue *vq)
160{
161 struct kvm_vqconfig *config = vq->priv;
162
163 kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, config->address);
164}
165
166/*
167 * This routine finds the first virtqueue described in the configuration of
168 * this device and sets it up.
169 */
170static struct virtqueue *kvm_find_vq(struct virtio_device *vdev,
171 unsigned index,
172 void (*callback)(struct virtqueue *vq))
173{
174 struct kvm_device *kdev = to_kvmdev(vdev);
175 struct kvm_vqconfig *config;
176 struct virtqueue *vq;
177 int err;
178
179 if (index >= kdev->desc->num_vq)
180 return ERR_PTR(-ENOENT);
181
182 config = kvm_vq_config(kdev->desc)+index;
183
184 err = vmem_add_mapping(config->address,
185 vring_size(config->num, PAGE_SIZE));
186 if (err)
187 goto out;
188
189 vq = vring_new_virtqueue(config->num, vdev, (void *) config->address,
190 kvm_notify, callback);
191 if (!vq) {
192 err = -ENOMEM;
193 goto unmap;
194 }
195
196 /*
197 * register a callback token
198 * The host will sent this via the external interrupt parameter
199 */
200 config->token = (u64) vq;
201
202 vq->priv = config;
203 return vq;
204unmap:
205 vmem_remove_mapping(config->address,
206 vring_size(config->num, PAGE_SIZE));
207out:
208 return ERR_PTR(err);
209}
210
211static void kvm_del_vq(struct virtqueue *vq)
212{
213 struct kvm_vqconfig *config = vq->priv;
214
215 vring_del_virtqueue(vq);
216 vmem_remove_mapping(config->address,
217 vring_size(config->num, PAGE_SIZE));
218}
219
220/*
221 * The config ops structure as defined by virtio config
222 */
223static struct virtio_config_ops kvm_vq_configspace_ops = {
224 .feature = kvm_feature,
225 .get = kvm_get,
226 .set = kvm_set,
227 .get_status = kvm_get_status,
228 .set_status = kvm_set_status,
229 .reset = kvm_reset,
230 .find_vq = kvm_find_vq,
231 .del_vq = kvm_del_vq,
232};
233
234/*
235 * The root device for the kvm virtio devices.
236 * This makes them appear as /sys/devices/kvm_s390/0,1,2 not /sys/devices/0,1,2.
237 */
238static struct device kvm_root = {
239 .parent = NULL,
240 .bus_id = "kvm_s390",
241};
242
243/*
244 * adds a new device and register it with virtio
245 * appropriate drivers are loaded by the device model
246 */
247static void add_kvm_device(struct kvm_device_desc *d)
248{
249 struct kvm_device *kdev;
250
251 kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
252 if (!kdev) {
253 printk(KERN_EMERG "Cannot allocate kvm dev %u\n",
254 dev_index++);
255 return;
256 }
257
258 kdev->vdev.dev.parent = &kvm_root;
259 kdev->vdev.index = dev_index++;
260 kdev->vdev.id.device = d->type;
261 kdev->vdev.config = &kvm_vq_configspace_ops;
262 kdev->desc = d;
263
264 if (register_virtio_device(&kdev->vdev) != 0) {
265 printk(KERN_ERR "Failed to register kvm device %u\n",
266 kdev->vdev.index);
267 kfree(kdev);
268 }
269}
270
271/*
272 * scan_devices() simply iterates through the device page.
273 * The type 0 is reserved to mean "end of devices".
274 */
275static void scan_devices(void)
276{
277 unsigned int i;
278 struct kvm_device_desc *d;
279
280 for (i = 0; i < PAGE_SIZE; i += desc_size(d)) {
281 d = kvm_devices + i;
282
283 if (d->type == 0)
284 break;
285
286 add_kvm_device(d);
287 }
288}
289
290/*
291 * we emulate the request_irq behaviour on top of s390 extints
292 */
293static void kvm_extint_handler(u16 code)
294{
295 void *data = (void *) *(long *) __LC_PFAULT_INTPARM;
296 u16 subcode = S390_lowcore.cpu_addr;
297
298 if ((subcode & 0xff00) != VIRTIO_SUBCODE_64)
299 return;
300
301 vring_interrupt(0, data);
302}
303
304/*
305 * Init function for virtio
306 * devices are in a single page above top of "normal" mem
307 */
308static int __init kvm_devices_init(void)
309{
310 int rc;
311
312 if (!MACHINE_IS_KVM)
313 return -ENODEV;
314
315 rc = device_register(&kvm_root);
316 if (rc) {
317 printk(KERN_ERR "Could not register kvm_s390 root device");
318 return rc;
319 }
320
321 rc = vmem_add_mapping(PFN_PHYS(max_pfn), PAGE_SIZE);
322 if (rc) {
323 device_unregister(&kvm_root);
324 return rc;
325 }
326
327 kvm_devices = (void *) PFN_PHYS(max_pfn);
328
329 ctl_set_bit(0, 9);
330 register_external_interrupt(0x2603, kvm_extint_handler);
331
332 scan_devices();
333 return 0;
334}
335
336/*
337 * We do this after core stuff, but before the drivers.
338 */
339postcore_initcall(kvm_devices_init);
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;
62static ssize_t 62static ssize_t
63group_write(struct device_driver *drv, const char *buf, size_t count) 63group_write(struct device_driver *drv, const char *buf, size_t count)
64{ 64{
65 const char *start, *end;
66 char bus_ids[2][BUS_ID_SIZE], *argv[2];
67 int i;
68 int ret; 65 int ret;
69 struct ccwgroup_driver *cdrv; 66 struct ccwgroup_driver *cdrv;
70 67
71 cdrv = to_ccwgroupdrv(drv); 68 cdrv = to_ccwgroupdrv(drv);
72 if (!cdrv) 69 if (!cdrv)
73 return -EINVAL; 70 return -EINVAL;
74 start = buf; 71 ret = ccwgroup_create_from_string(cu3088_root_dev, cdrv->driver_id,
75 for (i=0; i<2; i++) { 72 &cu3088_driver, 2, buf);
76 static const char delim[] = {',', '\n'};
77 int len;
78
79 if (!(end = strchr(start, delim[i])))
80 return -EINVAL;
81 len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start + 1);
82 strlcpy (bus_ids[i], start, len);
83 argv[i] = bus_ids[i];
84 start = end + 1;
85 }
86
87 ret = ccwgroup_create(cu3088_root_dev, cdrv->driver_id,
88 &cu3088_driver, 2, argv);
89 73
90 return (ret == 0) ? count : ret; 74 return (ret == 0) ? count : ret;
91} 75}
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)
1793 skb->protocol = card->lan_type_trans(skb, card->dev); 1793 skb->protocol = card->lan_type_trans(skb, card->dev);
1794 card->stats.rx_bytes += skb_len; 1794 card->stats.rx_bytes += skb_len;
1795 card->stats.rx_packets++; 1795 card->stats.rx_packets++;
1796 *((__u32 *)skb->cb) = ++card->pkt_seq; 1796 if (skb->protocol == htons(ETH_P_802_2))
1797 *((__u32 *)skb->cb) = ++card->pkt_seq;
1797 netif_rx(skb); 1798 netif_rx(skb);
1798} 1799}
1799 1800
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)
1313 * and throw away packet. 1313 * and throw away packet.
1314 */ 1314 */
1315 if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) { 1315 if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
1316 if (!in_atomic())
1317 fsm_event(privptr->fsm, DEV_EVENT_START, dev);
1318 dev_kfree_skb(skb); 1316 dev_kfree_skb(skb);
1319 privptr->stats.tx_dropped++; 1317 privptr->stats.tx_dropped++;
1320 privptr->stats.tx_errors++; 1318 privptr->stats.tx_errors++;
@@ -2147,6 +2145,7 @@ static int __init netiucv_init(void)
2147 if (rc) 2145 if (rc)
2148 goto out_dbf; 2146 goto out_dbf;
2149 IUCV_DBF_TEXT(trace, 3, __func__); 2147 IUCV_DBF_TEXT(trace, 3, __func__);
2148 netiucv_driver.groups = netiucv_drv_attr_groups;
2150 rc = driver_register(&netiucv_driver); 2149 rc = driver_register(&netiucv_driver);
2151 if (rc) { 2150 if (rc) {
2152 PRINT_ERR("NETIUCV: failed to register driver.\n"); 2151 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 {
72 debug_sprintf_event(qeth_dbf[QETH_DBF_MSG].id, level, text) 72 debug_sprintf_event(qeth_dbf[QETH_DBF_MSG].id, level, text)
73 73
74#define QETH_DBF_TEXT_(name, level, text...) \ 74#define QETH_DBF_TEXT_(name, level, text...) \
75 do { \ 75 qeth_dbf_longtext(QETH_DBF_##name, level, text)
76 if (qeth_dbf_passes(qeth_dbf[QETH_DBF_##name].id, level)) { \
77 char *dbf_txt_buf = \
78 get_cpu_var(QETH_DBF_TXT_BUF); \
79 sprintf(dbf_txt_buf, text); \
80 debug_text_event(qeth_dbf[QETH_DBF_##name].id, \
81 level, dbf_txt_buf); \
82 put_cpu_var(QETH_DBF_TXT_BUF); \
83 } \
84 } while (0)
85
86/* Allow to sort out low debug levels early to avoid wasted sprints */
87static inline int qeth_dbf_passes(debug_info_t *dbf_grp, int level)
88{
89 return (level <= dbf_grp->level);
90}
91 76
92/** 77/**
93 * some more debug stuff 78 * some more debug stuff
@@ -773,27 +758,6 @@ static inline int qeth_get_micros(void)
773 return (int) (get_clock() >> 12); 758 return (int) (get_clock() >> 12);
774} 759}
775 760
776static inline void *qeth_push_skb(struct qeth_card *card, struct sk_buff *skb,
777 int size)
778{
779 void *hdr;
780
781 hdr = (void *) skb_push(skb, size);
782 /*
783 * sanity check, the Linux memory allocation scheme should
784 * never present us cases like this one (the qdio header size plus
785 * the first 40 bytes of the paket cross a 4k boundary)
786 */
787 if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) !=
788 (((unsigned long) hdr + size +
789 QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
790 PRINT_ERR("Misaligned packet on interface %s. Discarded.",
791 QETH_CARD_IFNAME(card));
792 return NULL;
793 }
794 return hdr;
795}
796
797static inline int qeth_get_ip_version(struct sk_buff *skb) 761static inline int qeth_get_ip_version(struct sk_buff *skb)
798{ 762{
799 switch (skb->protocol) { 763 switch (skb->protocol) {
@@ -806,6 +770,12 @@ static inline int qeth_get_ip_version(struct sk_buff *skb)
806 } 770 }
807} 771}
808 772
773static inline void qeth_put_buffer_pool_entry(struct qeth_card *card,
774 struct qeth_buffer_pool_entry *entry)
775{
776 list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list);
777}
778
809struct qeth_eddp_context; 779struct qeth_eddp_context;
810extern struct ccwgroup_driver qeth_l2_ccwgroup_driver; 780extern struct ccwgroup_driver qeth_l2_ccwgroup_driver;
811extern struct ccwgroup_driver qeth_l3_ccwgroup_driver; 781extern struct ccwgroup_driver qeth_l3_ccwgroup_driver;
@@ -843,8 +813,6 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *,
843int qeth_query_setadapterparms(struct qeth_card *); 813int qeth_query_setadapterparms(struct qeth_card *);
844int qeth_check_qdio_errors(struct qdio_buffer *, unsigned int, 814int qeth_check_qdio_errors(struct qdio_buffer *, unsigned int,
845 unsigned int, const char *); 815 unsigned int, const char *);
846void qeth_put_buffer_pool_entry(struct qeth_card *,
847 struct qeth_buffer_pool_entry *);
848void qeth_queue_input_buffer(struct qeth_card *, int); 816void qeth_queue_input_buffer(struct qeth_card *, int);
849struct sk_buff *qeth_core_get_next_skb(struct qeth_card *, 817struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
850 struct qdio_buffer *, struct qdio_buffer_element **, int *, 818 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 *,
880 void *reply_param); 848 void *reply_param);
881int qeth_get_cast_type(struct qeth_card *, struct sk_buff *); 849int qeth_get_cast_type(struct qeth_card *, struct sk_buff *);
882int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int); 850int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int);
883struct sk_buff *qeth_prepare_skb(struct qeth_card *, struct sk_buff *,
884 struct qeth_hdr **);
885int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int); 851int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int);
886int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *, 852int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *,
887 struct sk_buff *, struct qeth_hdr *, int, 853 struct sk_buff *, struct qeth_hdr *, int,
@@ -894,6 +860,8 @@ void qeth_core_get_ethtool_stats(struct net_device *,
894 struct ethtool_stats *, u64 *); 860 struct ethtool_stats *, u64 *);
895void qeth_core_get_strings(struct net_device *, u32, u8 *); 861void qeth_core_get_strings(struct net_device *, u32, u8 *);
896void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *); 862void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
863void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *text, ...);
864int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *);
897 865
898/* exports for OSN */ 866/* exports for OSN */
899int qeth_osn_assist(struct net_device *, void *, int); 867int 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 @@
26#include "qeth_core.h" 26#include "qeth_core.h"
27#include "qeth_core_offl.h" 27#include "qeth_core_offl.h"
28 28
29static DEFINE_PER_CPU(char[256], qeth_core_dbf_txt_buf);
30#define QETH_DBF_TXT_BUF qeth_core_dbf_txt_buf
31
32struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS] = { 29struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS] = {
33 /* define dbf - Name, Pages, Areas, Maxlen, Level, View, Handle */ 30 /* define dbf - Name, Pages, Areas, Maxlen, Level, View, Handle */
34 /* N P A M L V H */ 31 /* N P A M L V H */
@@ -2255,14 +2252,6 @@ void qeth_print_status_message(struct qeth_card *card)
2255} 2252}
2256EXPORT_SYMBOL_GPL(qeth_print_status_message); 2253EXPORT_SYMBOL_GPL(qeth_print_status_message);
2257 2254
2258void qeth_put_buffer_pool_entry(struct qeth_card *card,
2259 struct qeth_buffer_pool_entry *entry)
2260{
2261 QETH_DBF_TEXT(TRACE, 6, "ptbfplen");
2262 list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list);
2263}
2264EXPORT_SYMBOL_GPL(qeth_put_buffer_pool_entry);
2265
2266static void qeth_initialize_working_pool_list(struct qeth_card *card) 2255static void qeth_initialize_working_pool_list(struct qeth_card *card)
2267{ 2256{
2268 struct qeth_buffer_pool_entry *entry; 2257 struct qeth_buffer_pool_entry *entry;
@@ -2603,7 +2592,6 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index)
2603 int rc; 2592 int rc;
2604 int newcount = 0; 2593 int newcount = 0;
2605 2594
2606 QETH_DBF_TEXT(TRACE, 6, "queinbuf");
2607 count = (index < queue->next_buf_to_init)? 2595 count = (index < queue->next_buf_to_init)?
2608 card->qdio.in_buf_pool.buf_count - 2596 card->qdio.in_buf_pool.buf_count -
2609 (queue->next_buf_to_init - index) : 2597 (queue->next_buf_to_init - index) :
@@ -2792,8 +2780,6 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
2792 int i; 2780 int i;
2793 unsigned int qdio_flags; 2781 unsigned int qdio_flags;
2794 2782
2795 QETH_DBF_TEXT(TRACE, 6, "flushbuf");
2796
2797 for (i = index; i < index + count; ++i) { 2783 for (i = index; i < index + count; ++i) {
2798 buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; 2784 buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
2799 buf->buffer->element[buf->next_element_to_fill - 1].flags |= 2785 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,
3037} 3023}
3038EXPORT_SYMBOL_GPL(qeth_get_priority_queue); 3024EXPORT_SYMBOL_GPL(qeth_get_priority_queue);
3039 3025
3040static void __qeth_free_new_skb(struct sk_buff *orig_skb,
3041 struct sk_buff *new_skb)
3042{
3043 if (orig_skb != new_skb)
3044 dev_kfree_skb_any(new_skb);
3045}
3046
3047static inline struct sk_buff *qeth_realloc_headroom(struct qeth_card *card,
3048 struct sk_buff *skb, int size)
3049{
3050 struct sk_buff *new_skb = skb;
3051
3052 if (skb_headroom(skb) >= size)
3053 return skb;
3054 new_skb = skb_realloc_headroom(skb, size);
3055 if (!new_skb)
3056 PRINT_ERR("Could not realloc headroom for qeth_hdr "
3057 "on interface %s", QETH_CARD_IFNAME(card));
3058 return new_skb;
3059}
3060
3061struct sk_buff *qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
3062 struct qeth_hdr **hdr)
3063{
3064 struct sk_buff *new_skb;
3065
3066 QETH_DBF_TEXT(TRACE, 6, "prepskb");
3067
3068 new_skb = qeth_realloc_headroom(card, skb,
3069 sizeof(struct qeth_hdr));
3070 if (!new_skb)
3071 return NULL;
3072
3073 *hdr = ((struct qeth_hdr *)qeth_push_skb(card, new_skb,
3074 sizeof(struct qeth_hdr)));
3075 if (*hdr == NULL) {
3076 __qeth_free_new_skb(skb, new_skb);
3077 return NULL;
3078 }
3079 return new_skb;
3080}
3081EXPORT_SYMBOL_GPL(qeth_prepare_skb);
3082
3083int qeth_get_elements_no(struct qeth_card *card, void *hdr, 3026int qeth_get_elements_no(struct qeth_card *card, void *hdr,
3084 struct sk_buff *skb, int elems) 3027 struct sk_buff *skb, int elems)
3085{ 3028{
@@ -3100,8 +3043,8 @@ int qeth_get_elements_no(struct qeth_card *card, void *hdr,
3100} 3043}
3101EXPORT_SYMBOL_GPL(qeth_get_elements_no); 3044EXPORT_SYMBOL_GPL(qeth_get_elements_no);
3102 3045
3103static void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, 3046static inline void __qeth_fill_buffer(struct sk_buff *skb,
3104 int is_tso, int *next_element_to_fill) 3047 struct qdio_buffer *buffer, int is_tso, int *next_element_to_fill)
3105{ 3048{
3106 int length = skb->len; 3049 int length = skb->len;
3107 int length_here; 3050 int length_here;
@@ -3143,15 +3086,13 @@ static void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
3143 *next_element_to_fill = element; 3086 *next_element_to_fill = element;
3144} 3087}
3145 3088
3146static int qeth_fill_buffer(struct qeth_qdio_out_q *queue, 3089static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
3147 struct qeth_qdio_out_buffer *buf, struct sk_buff *skb) 3090 struct qeth_qdio_out_buffer *buf, struct sk_buff *skb)
3148{ 3091{
3149 struct qdio_buffer *buffer; 3092 struct qdio_buffer *buffer;
3150 struct qeth_hdr_tso *hdr; 3093 struct qeth_hdr_tso *hdr;
3151 int flush_cnt = 0, hdr_len, large_send = 0; 3094 int flush_cnt = 0, hdr_len, large_send = 0;
3152 3095
3153 QETH_DBF_TEXT(TRACE, 6, "qdfillbf");
3154
3155 buffer = buf->buffer; 3096 buffer = buf->buffer;
3156 atomic_inc(&skb->users); 3097 atomic_inc(&skb->users);
3157 skb_queue_tail(&buf->skb_list, skb); 3098 skb_queue_tail(&buf->skb_list, skb);
@@ -3210,8 +3151,6 @@ int qeth_do_send_packet_fast(struct qeth_card *card,
3210 int flush_cnt = 0; 3151 int flush_cnt = 0;
3211 int index; 3152 int index;
3212 3153
3213 QETH_DBF_TEXT(TRACE, 6, "dosndpfa");
3214
3215 /* spin until we get the queue ... */ 3154 /* spin until we get the queue ... */
3216 while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, 3155 while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
3217 QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); 3156 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,
3263 int tmp; 3202 int tmp;
3264 int rc = 0; 3203 int rc = 0;
3265 3204
3266 QETH_DBF_TEXT(TRACE, 6, "dosndpkt");
3267
3268 /* spin until we get the queue ... */ 3205 /* spin until we get the queue ... */
3269 while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, 3206 while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
3270 QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); 3207 QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
@@ -3827,27 +3764,8 @@ static struct ccw_driver qeth_ccw_driver = {
3827static int qeth_core_driver_group(const char *buf, struct device *root_dev, 3764static int qeth_core_driver_group(const char *buf, struct device *root_dev,
3828 unsigned long driver_id) 3765 unsigned long driver_id)
3829{ 3766{
3830 const char *start, *end; 3767 return ccwgroup_create_from_string(root_dev, driver_id,
3831 char bus_ids[3][BUS_ID_SIZE], *argv[3]; 3768 &qeth_ccw_driver, 3, buf);
3832 int i;
3833
3834 start = buf;
3835 for (i = 0; i < 3; i++) {
3836 static const char delim[] = { ',', ',', '\n' };
3837 int len;
3838
3839 end = strchr(start, delim[i]);
3840 if (!end)
3841 return -EINVAL;
3842 len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start);
3843 strncpy(bus_ids[i], start, len);
3844 bus_ids[i][len] = '\0';
3845 start = end + 1;
3846 argv[i] = bus_ids[i];
3847 }
3848
3849 return (ccwgroup_create(root_dev, driver_id,
3850 &qeth_ccw_driver, 3, argv));
3851} 3769}
3852 3770
3853int qeth_core_hardsetup_card(struct qeth_card *card) 3771int qeth_core_hardsetup_card(struct qeth_card *card)
@@ -3885,8 +3803,9 @@ retry:
3885 QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); 3803 QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
3886 return rc; 3804 return rc;
3887 } 3805 }
3888 3806 mpno = qdio_get_ssqd_pct(CARD_DDEV(card));
3889 mpno = QETH_MAX_PORTNO; 3807 if (mpno)
3808 mpno = min(mpno - 1, QETH_MAX_PORTNO);
3890 if (card->info.portno > mpno) { 3809 if (card->info.portno > mpno) {
3891 PRINT_ERR("Device %s does not offer port number %d \n.", 3810 PRINT_ERR("Device %s does not offer port number %d \n.",
3892 CARD_BUS_ID(card), card->info.portno); 3811 CARD_BUS_ID(card), card->info.portno);
@@ -3980,7 +3899,6 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
3980 int use_rx_sg = 0; 3899 int use_rx_sg = 0;
3981 int frag = 0; 3900 int frag = 0;
3982 3901
3983 QETH_DBF_TEXT(TRACE, 6, "nextskb");
3984 /* qeth_hdr must not cross element boundaries */ 3902 /* qeth_hdr must not cross element boundaries */
3985 if (element->length < offset + sizeof(struct qeth_hdr)) { 3903 if (element->length < offset + sizeof(struct qeth_hdr)) {
3986 if (qeth_is_last_sbale(element)) 3904 if (qeth_is_last_sbale(element))
@@ -4086,6 +4004,18 @@ static void qeth_unregister_dbf_views(void)
4086 } 4004 }
4087} 4005}
4088 4006
4007void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *text, ...)
4008{
4009 char dbf_txt_buf[32];
4010
4011 if (level > (qeth_dbf[dbf_nix].id)->level)
4012 return;
4013 snprintf(dbf_txt_buf, sizeof(dbf_txt_buf), text);
4014 debug_text_event(qeth_dbf[dbf_nix].id, level, dbf_txt_buf);
4015
4016}
4017EXPORT_SYMBOL_GPL(qeth_dbf_longtext);
4018
4089static int qeth_register_dbf_views(void) 4019static int qeth_register_dbf_views(void)
4090{ 4020{
4091 int ret; 4021 int ret;
@@ -4433,6 +4363,96 @@ void qeth_core_get_drvinfo(struct net_device *dev,
4433} 4363}
4434EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo); 4364EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo);
4435 4365
4366int qeth_core_ethtool_get_settings(struct net_device *netdev,
4367 struct ethtool_cmd *ecmd)
4368{
4369 struct qeth_card *card = netdev_priv(netdev);
4370 enum qeth_link_types link_type;
4371
4372 if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan))
4373 link_type = QETH_LINK_TYPE_10GBIT_ETH;
4374 else
4375 link_type = card->info.link_type;
4376
4377 ecmd->transceiver = XCVR_INTERNAL;
4378 ecmd->supported = SUPPORTED_Autoneg;
4379 ecmd->advertising = ADVERTISED_Autoneg;
4380 ecmd->duplex = DUPLEX_FULL;
4381 ecmd->autoneg = AUTONEG_ENABLE;
4382
4383 switch (link_type) {
4384 case QETH_LINK_TYPE_FAST_ETH:
4385 case QETH_LINK_TYPE_LANE_ETH100:
4386 ecmd->supported |= SUPPORTED_10baseT_Half |
4387 SUPPORTED_10baseT_Full |
4388 SUPPORTED_100baseT_Half |
4389 SUPPORTED_100baseT_Full |
4390 SUPPORTED_TP;
4391 ecmd->advertising |= ADVERTISED_10baseT_Half |
4392 ADVERTISED_10baseT_Full |
4393 ADVERTISED_100baseT_Half |
4394 ADVERTISED_100baseT_Full |
4395 ADVERTISED_TP;
4396 ecmd->speed = SPEED_100;
4397 ecmd->port = PORT_TP;
4398 break;
4399
4400 case QETH_LINK_TYPE_GBIT_ETH:
4401 case QETH_LINK_TYPE_LANE_ETH1000:
4402 ecmd->supported |= SUPPORTED_10baseT_Half |
4403 SUPPORTED_10baseT_Full |
4404 SUPPORTED_100baseT_Half |
4405 SUPPORTED_100baseT_Full |
4406 SUPPORTED_1000baseT_Half |
4407 SUPPORTED_1000baseT_Full |
4408 SUPPORTED_FIBRE;
4409 ecmd->advertising |= ADVERTISED_10baseT_Half |
4410 ADVERTISED_10baseT_Full |
4411 ADVERTISED_100baseT_Half |
4412 ADVERTISED_100baseT_Full |
4413 ADVERTISED_1000baseT_Half |
4414 ADVERTISED_1000baseT_Full |
4415 ADVERTISED_FIBRE;
4416 ecmd->speed = SPEED_1000;
4417 ecmd->port = PORT_FIBRE;
4418 break;
4419
4420 case QETH_LINK_TYPE_10GBIT_ETH:
4421 ecmd->supported |= SUPPORTED_10baseT_Half |
4422 SUPPORTED_10baseT_Full |
4423 SUPPORTED_100baseT_Half |
4424 SUPPORTED_100baseT_Full |
4425 SUPPORTED_1000baseT_Half |
4426 SUPPORTED_1000baseT_Full |
4427 SUPPORTED_10000baseT_Full |
4428 SUPPORTED_FIBRE;
4429 ecmd->advertising |= ADVERTISED_10baseT_Half |
4430 ADVERTISED_10baseT_Full |
4431 ADVERTISED_100baseT_Half |
4432 ADVERTISED_100baseT_Full |
4433 ADVERTISED_1000baseT_Half |
4434 ADVERTISED_1000baseT_Full |
4435 ADVERTISED_10000baseT_Full |
4436 ADVERTISED_FIBRE;
4437 ecmd->speed = SPEED_10000;
4438 ecmd->port = PORT_FIBRE;
4439 break;
4440
4441 default:
4442 ecmd->supported |= SUPPORTED_10baseT_Half |
4443 SUPPORTED_10baseT_Full |
4444 SUPPORTED_TP;
4445 ecmd->advertising |= ADVERTISED_10baseT_Half |
4446 ADVERTISED_10baseT_Full |
4447 ADVERTISED_TP;
4448 ecmd->speed = SPEED_10;
4449 ecmd->port = PORT_TP;
4450 }
4451
4452 return 0;
4453}
4454EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_settings);
4455
4436static int __init qeth_core_init(void) 4456static int __init qeth_core_init(void)
4437{ 4457{
4438 int rc; 4458 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 @@
22#include "qeth_core.h" 22#include "qeth_core.h"
23#include "qeth_core_offl.h" 23#include "qeth_core_offl.h"
24 24
25#define QETH_DBF_TXT_BUF qeth_l2_dbf_txt_buf
26static DEFINE_PER_CPU(char[256], qeth_l2_dbf_txt_buf);
27
28static int qeth_l2_set_offline(struct ccwgroup_device *); 25static int qeth_l2_set_offline(struct ccwgroup_device *);
29static int qeth_l2_stop(struct net_device *); 26static int qeth_l2_stop(struct net_device *);
30static int qeth_l2_send_delmac(struct qeth_card *, __u8 *); 27static 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)
635 enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; 632 enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
636 struct qeth_eddp_context *ctx = NULL; 633 struct qeth_eddp_context *ctx = NULL;
637 634
638 QETH_DBF_TEXT(TRACE, 6, "l2xmit");
639
640 if ((card->state != CARD_STATE_UP) || !card->lan_online) { 635 if ((card->state != CARD_STATE_UP) || !card->lan_online) {
641 card->stats.tx_carrier_errors++; 636 card->stats.tx_carrier_errors++;
642 goto tx_drop; 637 goto tx_drop;
@@ -658,9 +653,12 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
658 if (card->info.type == QETH_CARD_TYPE_OSN) 653 if (card->info.type == QETH_CARD_TYPE_OSN)
659 hdr = (struct qeth_hdr *)skb->data; 654 hdr = (struct qeth_hdr *)skb->data;
660 else { 655 else {
661 new_skb = qeth_prepare_skb(card, skb, &hdr); 656 /* create a clone with writeable headroom */
657 new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr));
662 if (!new_skb) 658 if (!new_skb)
663 goto tx_drop; 659 goto tx_drop;
660 hdr = (struct qeth_hdr *)skb_push(new_skb,
661 sizeof(struct qeth_hdr));
664 qeth_l2_fill_header(card, hdr, new_skb, ipv, cast_type); 662 qeth_l2_fill_header(card, hdr, new_skb, ipv, cast_type);
665 } 663 }
666 664
@@ -747,7 +745,6 @@ static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
747 int index; 745 int index;
748 int i; 746 int i;
749 747
750 QETH_DBF_TEXT(TRACE, 6, "qdinput");
751 card = (struct qeth_card *) card_ptr; 748 card = (struct qeth_card *) card_ptr;
752 net_dev = card->dev; 749 net_dev = card->dev;
753 if (card->options.performance_stats) { 750 if (card->options.performance_stats) {
@@ -852,6 +849,22 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
852 return; 849 return;
853} 850}
854 851
852static int qeth_l2_ethtool_set_tso(struct net_device *dev, u32 data)
853{
854 struct qeth_card *card = netdev_priv(dev);
855
856 if (data) {
857 if (card->options.large_send == QETH_LARGE_SEND_NO) {
858 card->options.large_send = QETH_LARGE_SEND_EDDP;
859 dev->features |= NETIF_F_TSO;
860 }
861 } else {
862 dev->features &= ~NETIF_F_TSO;
863 card->options.large_send = QETH_LARGE_SEND_NO;
864 }
865 return 0;
866}
867
855static struct ethtool_ops qeth_l2_ethtool_ops = { 868static struct ethtool_ops qeth_l2_ethtool_ops = {
856 .get_link = ethtool_op_get_link, 869 .get_link = ethtool_op_get_link,
857 .get_tx_csum = ethtool_op_get_tx_csum, 870 .get_tx_csum = ethtool_op_get_tx_csum,
@@ -859,11 +872,12 @@ static struct ethtool_ops qeth_l2_ethtool_ops = {
859 .get_sg = ethtool_op_get_sg, 872 .get_sg = ethtool_op_get_sg,
860 .set_sg = ethtool_op_set_sg, 873 .set_sg = ethtool_op_set_sg,
861 .get_tso = ethtool_op_get_tso, 874 .get_tso = ethtool_op_get_tso,
862 .set_tso = ethtool_op_set_tso, 875 .set_tso = qeth_l2_ethtool_set_tso,
863 .get_strings = qeth_core_get_strings, 876 .get_strings = qeth_core_get_strings,
864 .get_ethtool_stats = qeth_core_get_ethtool_stats, 877 .get_ethtool_stats = qeth_core_get_ethtool_stats,
865 .get_stats_count = qeth_core_get_stats_count, 878 .get_stats_count = qeth_core_get_stats_count,
866 .get_drvinfo = qeth_core_get_drvinfo, 879 .get_drvinfo = qeth_core_get_drvinfo,
880 .get_settings = qeth_core_ethtool_get_settings,
867}; 881};
868 882
869static struct ethtool_ops qeth_l2_osn_ops = { 883static 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 @@
13 13
14#include "qeth_core.h" 14#include "qeth_core.h"
15 15
16#define QETH_DBF_TXT_BUF qeth_l3_dbf_txt_buf
17DECLARE_PER_CPU(char[256], qeth_l3_dbf_txt_buf);
18
19struct qeth_ipaddr { 16struct qeth_ipaddr {
20 struct list_head entry; 17 struct list_head entry;
21 enum qeth_ip_types type; 18 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 @@
28#include "qeth_l3.h" 28#include "qeth_l3.h"
29#include "qeth_core_offl.h" 29#include "qeth_core_offl.h"
30 30
31DEFINE_PER_CPU(char[256], qeth_l3_dbf_txt_buf);
32
33static int qeth_l3_set_offline(struct ccwgroup_device *); 31static int qeth_l3_set_offline(struct ccwgroup_device *);
34static int qeth_l3_recover(void *); 32static int qeth_l3_recover(void *);
35static int qeth_l3_stop(struct net_device *); 33static int qeth_l3_stop(struct net_device *);
@@ -2093,6 +2091,11 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
2093 (card->state == CARD_STATE_UP)) { 2091 (card->state == CARD_STATE_UP)) {
2094 if (recovery_mode) 2092 if (recovery_mode)
2095 qeth_l3_stop(card->dev); 2093 qeth_l3_stop(card->dev);
2094 else {
2095 rtnl_lock();
2096 dev_close(card->dev);
2097 rtnl_unlock();
2098 }
2096 if (!card->use_hard_stop) { 2099 if (!card->use_hard_stop) {
2097 rc = qeth_send_stoplan(card); 2100 rc = qeth_send_stoplan(card);
2098 if (rc) 2101 if (rc)
@@ -2559,8 +2562,6 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2559static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, 2562static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
2560 struct sk_buff *skb, int ipv, int cast_type) 2563 struct sk_buff *skb, int ipv, int cast_type)
2561{ 2564{
2562 QETH_DBF_TEXT(TRACE, 6, "fillhdr");
2563
2564 memset(hdr, 0, sizeof(struct qeth_hdr)); 2565 memset(hdr, 0, sizeof(struct qeth_hdr));
2565 hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3; 2566 hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
2566 hdr->hdr.l3.ext_flags = 0; 2567 hdr->hdr.l3.ext_flags = 0;
@@ -2570,9 +2571,10 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
2570 * v6 uses passthrough, v4 sets the tag in the QDIO header. 2571 * v6 uses passthrough, v4 sets the tag in the QDIO header.
2571 */ 2572 */
2572 if (card->vlangrp && vlan_tx_tag_present(skb)) { 2573 if (card->vlangrp && vlan_tx_tag_present(skb)) {
2573 hdr->hdr.l3.ext_flags = (ipv == 4) ? 2574 if ((ipv == 4) || (card->info.type == QETH_CARD_TYPE_IQD))
2574 QETH_HDR_EXT_VLAN_FRAME : 2575 hdr->hdr.l3.ext_flags = QETH_HDR_EXT_VLAN_FRAME;
2575 QETH_HDR_EXT_INCLUDE_VLAN_TAG; 2576 else
2577 hdr->hdr.l3.ext_flags = QETH_HDR_EXT_INCLUDE_VLAN_TAG;
2576 hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb); 2578 hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb);
2577 } 2579 }
2578 2580
@@ -2638,8 +2640,6 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2638 enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; 2640 enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
2639 struct qeth_eddp_context *ctx = NULL; 2641 struct qeth_eddp_context *ctx = NULL;
2640 2642
2641 QETH_DBF_TEXT(TRACE, 6, "l3xmit");
2642
2643 if ((card->info.type == QETH_CARD_TYPE_IQD) && 2643 if ((card->info.type == QETH_CARD_TYPE_IQD) &&
2644 (skb->protocol != htons(ETH_P_IPV6)) && 2644 (skb->protocol != htons(ETH_P_IPV6)) &&
2645 (skb->protocol != htons(ETH_P_IP))) 2645 (skb->protocol != htons(ETH_P_IP)))
@@ -2890,6 +2890,7 @@ static struct ethtool_ops qeth_l3_ethtool_ops = {
2890 .get_ethtool_stats = qeth_core_get_ethtool_stats, 2890 .get_ethtool_stats = qeth_core_get_ethtool_stats,
2891 .get_stats_count = qeth_core_get_stats_count, 2891 .get_stats_count = qeth_core_get_stats_count,
2892 .get_drvinfo = qeth_core_get_drvinfo, 2892 .get_drvinfo = qeth_core_get_drvinfo,
2893 .get_settings = qeth_core_ethtool_get_settings,
2893}; 2894};
2894 2895
2895/* 2896/*
@@ -2982,7 +2983,6 @@ static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev,
2982 int index; 2983 int index;
2983 int i; 2984 int i;
2984 2985
2985 QETH_DBF_TEXT(TRACE, 6, "qdinput");
2986 card = (struct qeth_card *) card_ptr; 2986 card = (struct qeth_card *) card_ptr;
2987 net_dev = card->dev; 2987 net_dev = card->dev;
2988 if (card->options.performance_stats) { 2988 if (card->options.performance_stats) {
@@ -3140,9 +3140,15 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
3140 netif_carrier_on(card->dev); 3140 netif_carrier_on(card->dev);
3141 3141
3142 qeth_set_allowed_threads(card, 0xffffffff, 0); 3142 qeth_set_allowed_threads(card, 0xffffffff, 0);
3143 if ((recover_flag == CARD_STATE_RECOVER) && recovery_mode) { 3143 if (recover_flag == CARD_STATE_RECOVER) {
3144 if (recovery_mode)
3144 qeth_l3_open(card->dev); 3145 qeth_l3_open(card->dev);
3145 qeth_l3_set_multicast_list(card->dev); 3146 else {
3147 rtnl_lock();
3148 dev_open(card->dev);
3149 rtnl_unlock();
3150 }
3151 qeth_l3_set_multicast_list(card->dev);
3146 } 3152 }
3147 /* let user_space know that device is online */ 3153 /* let user_space know that device is online */
3148 kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); 3154 kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
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,
1055 rec->scsi_result = scsi_cmnd->result; 1055 rec->scsi_result = scsi_cmnd->result;
1056 rec->scsi_cmnd = (unsigned long)scsi_cmnd; 1056 rec->scsi_cmnd = (unsigned long)scsi_cmnd;
1057 rec->scsi_serial = scsi_cmnd->serial_number; 1057 rec->scsi_serial = scsi_cmnd->serial_number;
1058 memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd, 1058 memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
1059 min((int)scsi_cmnd->cmd_len, 1059 min((int)scsi_cmnd->cmd_len,
1060 ZFCP_DBF_SCSI_OPCODE)); 1060 ZFCP_DBF_SCSI_OPCODE));
1061 rec->scsi_retries = scsi_cmnd->retries; 1061 rec->scsi_retries = scsi_cmnd->retries;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 7c3f02816e95..b2ea4ea051f5 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -1927,7 +1927,8 @@ zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
1927 1927
1928 /* setup new FSF request */ 1928 /* setup new FSF request */
1929 retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, 1929 retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA,
1930 0, NULL, &lock_flags, &fsf_req); 1930 ZFCP_WAIT_FOR_SBAL, NULL, &lock_flags,
1931 &fsf_req);
1931 if (retval) { 1932 if (retval) {
1932 ZFCP_LOG_INFO("error: Could not create exchange configuration " 1933 ZFCP_LOG_INFO("error: Could not create exchange configuration "
1933 "data request for adapter %s.\n", 1934 "data request for adapter %s.\n",
@@ -2035,21 +2036,21 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
2035 min(FC_SERIAL_NUMBER_SIZE, 17)); 2036 min(FC_SERIAL_NUMBER_SIZE, 17));
2036 } 2037 }
2037 2038
2038 ZFCP_LOG_NORMAL("The adapter %s reported the following " 2039 if (fsf_req->erp_action)
2039 "characteristics:\n" 2040 ZFCP_LOG_NORMAL("The adapter %s reported the following "
2040 "WWNN 0x%016Lx, " 2041 "characteristics:\n"
2041 "WWPN 0x%016Lx, " 2042 "WWNN 0x%016Lx, WWPN 0x%016Lx, "
2042 "S_ID 0x%06x,\n" 2043 "S_ID 0x%06x,\n"
2043 "adapter version 0x%x, " 2044 "adapter version 0x%x, "
2044 "LIC version 0x%x, " 2045 "LIC version 0x%x, "
2045 "FC link speed %d Gb/s\n", 2046 "FC link speed %d Gb/s\n",
2046 zfcp_get_busid_by_adapter(adapter), 2047 zfcp_get_busid_by_adapter(adapter),
2047 (wwn_t) fc_host_node_name(shost), 2048 (wwn_t) fc_host_node_name(shost),
2048 (wwn_t) fc_host_port_name(shost), 2049 (wwn_t) fc_host_port_name(shost),
2049 fc_host_port_id(shost), 2050 fc_host_port_id(shost),
2050 adapter->hydra_version, 2051 adapter->hydra_version,
2051 adapter->fsf_lic_version, 2052 adapter->fsf_lic_version,
2052 fc_host_speed(shost)); 2053 fc_host_speed(shost));
2053 if (ZFCP_QTCB_VERSION < bottom->low_qtcb_version) { 2054 if (ZFCP_QTCB_VERSION < bottom->low_qtcb_version) {
2054 ZFCP_LOG_NORMAL("error: the adapter %s " 2055 ZFCP_LOG_NORMAL("error: the adapter %s "
2055 "only supports newer control block " 2056 "only supports newer control block "
@@ -2114,8 +2115,10 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
2114 zfcp_erp_adapter_shutdown(adapter, 0, 127, fsf_req); 2115 zfcp_erp_adapter_shutdown(adapter, 0, 127, fsf_req);
2115 return -EIO; 2116 return -EIO;
2116 case FC_PORTTYPE_NPORT: 2117 case FC_PORTTYPE_NPORT:
2117 ZFCP_LOG_NORMAL("Switched fabric fibrechannel " 2118 if (fsf_req->erp_action)
2118 "network detected at adapter %s.\n", 2119 ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
2120 "network detected at adapter "
2121 "%s.\n",
2119 zfcp_get_busid_by_adapter(adapter)); 2122 zfcp_get_busid_by_adapter(adapter));
2120 break; 2123 break;
2121 default: 2124 default:
@@ -4011,7 +4014,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
4011 ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n", 4014 ZFCP_LOG_TRACE("scpnt->result =0x%x, command was:\n",
4012 scpnt->result); 4015 scpnt->result);
4013 ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, 4016 ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
4014 (void *) &scpnt->cmnd, scpnt->cmd_len); 4017 scpnt->cmnd, scpnt->cmd_len);
4015 4018
4016 ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n", 4019 ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n",
4017 fcp_rsp_iu->fcp_sns_len); 4020 fcp_rsp_iu->fcp_sns_len);
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 8cce5cc11d50..099970b27001 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -213,6 +213,7 @@
213#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 213#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
214#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 214#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
215#define FSF_FEATURE_UPDATE_ALERT 0x00000100 215#define FSF_FEATURE_UPDATE_ALERT 0x00000100
216#define FSF_FEATURE_MEASUREMENT_DATA 0x00000200
216 217
217/* host connection features */ 218/* host connection features */
218#define FSF_FEATURE_NPIV_MODE 0x00000001 219#define FSF_FEATURE_NPIV_MODE 0x00000001
@@ -340,6 +341,15 @@ struct fsf_qtcb_prefix {
340 u8 res1[20]; 341 u8 res1[20];
341} __attribute__ ((packed)); 342} __attribute__ ((packed));
342 343
344struct fsf_statistics_info {
345 u64 input_req;
346 u64 output_req;
347 u64 control_req;
348 u64 input_mb;
349 u64 output_mb;
350 u64 seconds_act;
351} __attribute__ ((packed));
352
343union fsf_status_qual { 353union fsf_status_qual {
344 u8 byte[FSF_STATUS_QUALIFIER_SIZE]; 354 u8 byte[FSF_STATUS_QUALIFIER_SIZE];
345 u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)]; 355 u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)];
@@ -436,7 +446,8 @@ struct fsf_qtcb_bottom_config {
436 u32 hardware_version; 446 u32 hardware_version;
437 u8 serial_number[32]; 447 u8 serial_number[32];
438 struct fsf_nport_serv_param plogi_payload; 448 struct fsf_nport_serv_param plogi_payload;
439 u8 res4[160]; 449 struct fsf_statistics_info stat_info;
450 u8 res4[112];
440} __attribute__ ((packed)); 451} __attribute__ ((packed));
441 452
442struct fsf_qtcb_bottom_port { 453struct fsf_qtcb_bottom_port {
@@ -469,7 +480,10 @@ struct fsf_qtcb_bottom_port {
469 u64 control_requests; 480 u64 control_requests;
470 u64 input_mb; /* where 1 MByte == 1.000.000 Bytes */ 481 u64 input_mb; /* where 1 MByte == 1.000.000 Bytes */
471 u64 output_mb; /* where 1 MByte == 1.000.000 Bytes */ 482 u64 output_mb; /* where 1 MByte == 1.000.000 Bytes */
472 u8 res2[256]; 483 u8 cp_util;
484 u8 cb_util;
485 u8 a_util;
486 u8 res2[253];
473} __attribute__ ((packed)); 487} __attribute__ ((packed));
474 488
475union fsf_qtcb_bottom { 489union fsf_qtcb_bottom {
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index f81850624eed..01687559dc06 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -40,6 +40,7 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int,
40 unsigned int, unsigned int); 40 unsigned int, unsigned int);
41 41
42static struct device_attribute *zfcp_sysfs_sdev_attrs[]; 42static struct device_attribute *zfcp_sysfs_sdev_attrs[];
43static struct device_attribute *zfcp_a_stats_attrs[];
43 44
44struct zfcp_data zfcp_data = { 45struct zfcp_data zfcp_data = {
45 .scsi_host_template = { 46 .scsi_host_template = {
@@ -61,6 +62,7 @@ struct zfcp_data zfcp_data = {
61 .use_clustering = 1, 62 .use_clustering = 1,
62 .sdev_attrs = zfcp_sysfs_sdev_attrs, 63 .sdev_attrs = zfcp_sysfs_sdev_attrs,
63 .max_sectors = ZFCP_MAX_SECTORS, 64 .max_sectors = ZFCP_MAX_SECTORS,
65 .shost_attrs = zfcp_a_stats_attrs,
64 }, 66 },
65 .driver_version = ZFCP_VERSION, 67 .driver_version = ZFCP_VERSION,
66}; 68};
@@ -809,4 +811,116 @@ static struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
809 NULL 811 NULL
810}; 812};
811 813
814static ssize_t zfcp_sysfs_adapter_util_show(struct device *dev,
815 struct device_attribute *attr,
816 char *buf)
817{
818 struct Scsi_Host *scsi_host = dev_to_shost(dev);
819 struct fsf_qtcb_bottom_port *qtcb_port;
820 int retval;
821 struct zfcp_adapter *adapter;
822
823 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
824 if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
825 return -EOPNOTSUPP;
826
827 qtcb_port = kzalloc(sizeof(struct fsf_qtcb_bottom_port), GFP_KERNEL);
828 if (!qtcb_port)
829 return -ENOMEM;
830
831 retval = zfcp_fsf_exchange_port_data_sync(adapter, qtcb_port);
832 if (!retval)
833 retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
834 qtcb_port->cb_util, qtcb_port->a_util);
835 kfree(qtcb_port);
836 return retval;
837}
838
839static int zfcp_sysfs_adapter_ex_config(struct device *dev,
840 struct fsf_statistics_info *stat_inf)
841{
842 int retval;
843 struct fsf_qtcb_bottom_config *qtcb_config;
844 struct Scsi_Host *scsi_host = dev_to_shost(dev);
845 struct zfcp_adapter *adapter;
846
847 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
848 if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
849 return -EOPNOTSUPP;
850
851 qtcb_config = kzalloc(sizeof(struct fsf_qtcb_bottom_config),
852 GFP_KERNEL);
853 if (!qtcb_config)
854 return -ENOMEM;
855
856 retval = zfcp_fsf_exchange_config_data_sync(adapter, qtcb_config);
857 if (!retval)
858 *stat_inf = qtcb_config->stat_info;
859
860 kfree(qtcb_config);
861 return retval;
862}
863
864static ssize_t zfcp_sysfs_adapter_request_show(struct device *dev,
865 struct device_attribute *attr,
866 char *buf)
867{
868 struct fsf_statistics_info stat_info;
869 int retval;
870
871 retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
872 if (retval)
873 return retval;
874
875 return sprintf(buf, "%llu %llu %llu\n",
876 (unsigned long long) stat_info.input_req,
877 (unsigned long long) stat_info.output_req,
878 (unsigned long long) stat_info.control_req);
879}
880
881static ssize_t zfcp_sysfs_adapter_mb_show(struct device *dev,
882 struct device_attribute *attr,
883 char *buf)
884{
885 struct fsf_statistics_info stat_info;
886 int retval;
887
888 retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
889 if (retval)
890 return retval;
891
892 return sprintf(buf, "%llu %llu\n",
893 (unsigned long long) stat_info.input_mb,
894 (unsigned long long) stat_info.output_mb);
895}
896
897static ssize_t zfcp_sysfs_adapter_sec_active_show(struct device *dev,
898 struct device_attribute *attr,
899 char *buf)
900{
901 struct fsf_statistics_info stat_info;
902 int retval;
903
904 retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
905 if (retval)
906 return retval;
907
908 return sprintf(buf, "%llu\n",
909 (unsigned long long) stat_info.seconds_act);
910}
911
912static DEVICE_ATTR(utilization, S_IRUGO, zfcp_sysfs_adapter_util_show, NULL);
913static DEVICE_ATTR(requests, S_IRUGO, zfcp_sysfs_adapter_request_show, NULL);
914static DEVICE_ATTR(megabytes, S_IRUGO, zfcp_sysfs_adapter_mb_show, NULL);
915static DEVICE_ATTR(seconds_active, S_IRUGO,
916 zfcp_sysfs_adapter_sec_active_show, NULL);
917
918static struct device_attribute *zfcp_a_stats_attrs[] = {
919 &dev_attr_utilization,
920 &dev_attr_requests,
921 &dev_attr_megabytes,
922 &dev_attr_seconds_active,
923 NULL
924};
925
812#undef ZFCP_LOG_AREA 926#undef ZFCP_LOG_AREA