summaryrefslogtreecommitdiff
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/char/con3270.c7
-rw-r--r--drivers/s390/char/fs3270.c234
-rw-r--r--drivers/s390/char/raw3270.c100
-rw-r--r--drivers/s390/char/raw3270.h7
-rw-r--r--drivers/s390/char/tape_class.c1
-rw-r--r--drivers/s390/char/tty3270.c27
-rw-r--r--drivers/s390/char/vmlogrdr.c1
-rw-r--r--drivers/s390/cio/cmf.c3
-rw-r--r--drivers/s390/cio/device.c20
-rw-r--r--drivers/s390/cio/device_fsm.c2
-rw-r--r--drivers/s390/net/fsm.c2
-rw-r--r--drivers/s390/net/fsm.h2
-rw-r--r--drivers/s390/net/qeth.h45
-rw-r--r--drivers/s390/net/qeth_fs.h12
-rw-r--r--drivers/s390/net/qeth_main.c419
-rw-r--r--drivers/s390/net/qeth_mpc.c6
-rw-r--r--drivers/s390/net/qeth_mpc.h15
-rw-r--r--drivers/s390/net/qeth_sys.c28
18 files changed, 748 insertions, 183 deletions
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index fc7a213e591f..c570a9f6ce9c 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -213,6 +213,9 @@ con3270_update(struct con3270 *cp)
struct string *s, *n;
int rc;
+ if (cp->view.dev)
+ raw3270_activate_view(&cp->view);
+
wrq = xchg(&cp->write, 0);
if (!wrq) {
con3270_set_timer(cp, 1);
@@ -489,8 +492,6 @@ con3270_write(struct console *co, const char *str, unsigned int count)
unsigned char c;
cp = condev;
- if (cp->view.dev)
- raw3270_activate_view(&cp->view);
spin_lock_irqsave(&cp->view.lock, flags);
while (count-- > 0) {
c = *str++;
@@ -620,7 +621,7 @@ con3270_init(void)
(void (*)(unsigned long)) con3270_read_tasklet,
(unsigned long) condev->read);
- raw3270_add_view(&condev->view, &con3270_fn, 0);
+ raw3270_add_view(&condev->view, &con3270_fn, 1);
INIT_LIST_HEAD(&condev->freemem);
for (i = 0; i < CON3270_STRING_PAGES; i++) {
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 60afcdcf91c2..735a7fcdeff5 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -33,8 +33,11 @@ struct fs3270 {
int read_command; /* ccw command to use for reads. */
int write_command; /* ccw command to use for writes. */
int attention; /* Got attention. */
- struct raw3270_request *clear; /* single clear request. */
- wait_queue_head_t attn_wait; /* Attention wait queue. */
+ int active; /* Fullscreen view is active. */
+ struct raw3270_request *init; /* single init request. */
+ wait_queue_head_t wait; /* Init & attention wait queue. */
+ struct idal_buffer *rdbuf; /* full-screen-deactivate buffer */
+ size_t rdbuf_size; /* size of data returned by RDBUF */
};
static void
@@ -43,58 +46,172 @@ fs3270_wake_up(struct raw3270_request *rq, void *data)
wake_up((wait_queue_head_t *) data);
}
+static inline int
+fs3270_working(struct fs3270 *fp)
+{
+ /*
+ * The fullscreen view is in working order if the view
+ * has been activated AND the initial request is finished.
+ */
+ return fp->active && raw3270_request_final(fp->init);
+}
+
static int
fs3270_do_io(struct raw3270_view *view, struct raw3270_request *rq)
{
- wait_queue_head_t wq;
+ struct fs3270 *fp;
int rc;
- init_waitqueue_head(&wq);
+ fp = (struct fs3270 *) view;
rq->callback = fs3270_wake_up;
- rq->callback_data = &wq;
- rc = raw3270_start(view, rq);
- if (rc)
- return rc;
- /* Started sucessfully. Now wait for completion. */
- wait_event(wq, raw3270_request_final(rq));
- return rq->rc;
+ rq->callback_data = &fp->wait;
+
+ do {
+ if (!fs3270_working(fp)) {
+ /* Fullscreen view isn't ready yet. */
+ rc = wait_event_interruptible(fp->wait,
+ fs3270_working(fp));
+ if (rc != 0)
+ break;
+ }
+ rc = raw3270_start(view, rq);
+ if (rc == 0) {
+ /* Started sucessfully. Now wait for completion. */
+ wait_event(fp->wait, raw3270_request_final(rq));
+ }
+ } while (rc == -EACCES);
+ return rc;
}
+/*
+ * Switch to the fullscreen view.
+ */
static void
fs3270_reset_callback(struct raw3270_request *rq, void *data)
{
+ struct fs3270 *fp;
+
+ fp = (struct fs3270 *) rq->view;
raw3270_request_reset(rq);
+ wake_up(&fp->wait);
+}
+
+static void
+fs3270_restore_callback(struct raw3270_request *rq, void *data)
+{
+ struct fs3270 *fp;
+
+ fp = (struct fs3270 *) rq->view;
+ if (rq->rc != 0 || rq->rescnt != 0) {
+ if (fp->fs_pid)
+ kill_proc(fp->fs_pid, SIGHUP, 1);
+ }
+ fp->rdbuf_size = 0;
+ raw3270_request_reset(rq);
+ wake_up(&fp->wait);
}
-/*
- * Switch to the fullscreen view.
- */
static int
fs3270_activate(struct raw3270_view *view)
{
struct fs3270 *fp;
+ char *cp;
+ int rc;
fp = (struct fs3270 *) view;
- raw3270_request_set_cmd(fp->clear, TC_EWRITEA);
- fp->clear->callback = fs3270_reset_callback;
- return raw3270_start(view, fp->clear);
+
+ /* If an old init command is still running just return. */
+ if (!raw3270_request_final(fp->init))
+ return 0;
+
+ if (fp->rdbuf_size == 0) {
+ /* No saved buffer. Just clear the screen. */
+ raw3270_request_set_cmd(fp->init, TC_EWRITEA);
+ fp->init->callback = fs3270_reset_callback;
+ } else {
+ /* Restore fullscreen buffer saved by fs3270_deactivate. */
+ raw3270_request_set_cmd(fp->init, TC_EWRITEA);
+ raw3270_request_set_idal(fp->init, fp->rdbuf);
+ fp->init->ccw.count = fp->rdbuf_size;
+ cp = fp->rdbuf->data[0];
+ cp[0] = TW_KR;
+ cp[1] = TO_SBA;
+ cp[2] = cp[6];
+ cp[3] = cp[7];
+ cp[4] = TO_IC;
+ cp[5] = TO_SBA;
+ cp[6] = 0x40;
+ cp[7] = 0x40;
+ fp->init->rescnt = 0;
+ fp->init->callback = fs3270_restore_callback;
+ }
+ rc = fp->init->rc = raw3270_start_locked(view, fp->init);
+ if (rc)
+ fp->init->callback(fp->init, NULL);
+ else
+ fp->active = 1;
+ return rc;
}
/*
* Shutdown fullscreen view.
*/
static void
+fs3270_save_callback(struct raw3270_request *rq, void *data)
+{
+ struct fs3270 *fp;
+
+ fp = (struct fs3270 *) rq->view;
+
+ /* Correct idal buffer element 0 address. */
+ fp->rdbuf->data[0] -= 5;
+ fp->rdbuf->size += 5;
+
+ /*
+ * If the rdbuf command failed or the idal buffer is
+ * to small for the amount of data returned by the
+ * rdbuf command, then we have no choice but to send
+ * a SIGHUP to the application.
+ */
+ if (rq->rc != 0 || rq->rescnt == 0) {
+ if (fp->fs_pid)
+ kill_proc(fp->fs_pid, SIGHUP, 1);
+ fp->rdbuf_size = 0;
+ } else
+ fp->rdbuf_size = fp->rdbuf->size - rq->rescnt;
+ raw3270_request_reset(rq);
+ wake_up(&fp->wait);
+}
+
+static void
fs3270_deactivate(struct raw3270_view *view)
{
- // FIXME: is this a good idea? The user program using fullscreen 3270
- // will die just because a console message appeared. On the other
- // hand the fullscreen device is unoperational now.
struct fs3270 *fp;
fp = (struct fs3270 *) view;
- if (fp->fs_pid != 0)
- kill_proc(fp->fs_pid, SIGHUP, 1);
- fp->fs_pid = 0;
+ fp->active = 0;
+
+ /* If an old init command is still running just return. */
+ if (!raw3270_request_final(fp->init))
+ return;
+
+ /* Prepare read-buffer request. */
+ raw3270_request_set_cmd(fp->init, TC_RDBUF);
+ /*
+ * Hackish: skip first 5 bytes of the idal buffer to make
+ * room for the TW_KR/TO_SBA/<address>/<address>/TO_IC sequence
+ * in the activation command.
+ */
+ fp->rdbuf->data[0] += 5;
+ fp->rdbuf->size -= 5;
+ raw3270_request_set_idal(fp->init, fp->rdbuf);
+ fp->init->rescnt = 0;
+ fp->init->callback = fs3270_save_callback;
+
+ /* Start I/O to read in the 3270 buffer. */
+ fp->init->rc = raw3270_start_locked(view, fp->init);
+ if (fp->init->rc)
+ fp->init->callback(fp->init, NULL);
}
static int
@@ -103,7 +220,7 @@ fs3270_irq(struct fs3270 *fp, struct raw3270_request *rq, struct irb *irb)
/* Handle ATTN. Set indication and wake waiters for attention. */
if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
fp->attention = 1;
- wake_up(&fp->attn_wait);
+ wake_up(&fp->wait);
}
if (rq) {
@@ -125,7 +242,7 @@ fs3270_read(struct file *filp, char *data, size_t count, loff_t *off)
struct fs3270 *fp;
struct raw3270_request *rq;
struct idal_buffer *ib;
- int rc;
+ ssize_t rc;
if (count == 0 || count > 65535)
return -EINVAL;
@@ -133,7 +250,7 @@ fs3270_read(struct file *filp, char *data, size_t count, loff_t *off)
if (!fp)
return -ENODEV;
ib = idal_buffer_alloc(count, 0);
- if (!ib)
+ if (IS_ERR(ib))
return -ENOMEM;
rq = raw3270_request_alloc(0);
if (!IS_ERR(rq)) {
@@ -141,10 +258,19 @@ fs3270_read(struct file *filp, char *data, size_t count, loff_t *off)
fp->read_command = 6;
raw3270_request_set_cmd(rq, fp->read_command ? : 2);
raw3270_request_set_idal(rq, ib);
- wait_event(fp->attn_wait, fp->attention);
- rc = fs3270_do_io(&fp->view, rq);
- if (rc == 0 && idal_buffer_to_user(ib, data, count))
- rc = -EFAULT;
+ rc = wait_event_interruptible(fp->wait, fp->attention);
+ fp->attention = 0;
+ if (rc == 0) {
+ rc = fs3270_do_io(&fp->view, rq);
+ if (rc == 0) {
+ count -= rq->rescnt;
+ if (idal_buffer_to_user(ib, data, count) != 0)
+ rc = -EFAULT;
+ else
+ rc = count;
+
+ }
+ }
raw3270_request_free(rq);
} else
rc = PTR_ERR(rq);
@@ -162,13 +288,13 @@ fs3270_write(struct file *filp, const char *data, size_t count, loff_t *off)
struct raw3270_request *rq;
struct idal_buffer *ib;
int write_command;
- int rc;
+ ssize_t rc;
fp = filp->private_data;
if (!fp)
return -ENODEV;
ib = idal_buffer_alloc(count, 0);
- if (!ib)
+ if (IS_ERR(ib))
return -ENOMEM;
rq = raw3270_request_alloc(0);
if (!IS_ERR(rq)) {
@@ -179,6 +305,8 @@ fs3270_write(struct file *filp, const char *data, size_t count, loff_t *off)
raw3270_request_set_cmd(rq, write_command);
raw3270_request_set_idal(rq, ib);
rc = fs3270_do_io(&fp->view, rq);
+ if (rc == 0)
+ rc = count - rq->rescnt;
} else
rc = -EFAULT;
raw3270_request_free(rq);
@@ -232,7 +360,7 @@ fs3270_ioctl(struct inode *inode, struct file *filp,
}
/*
- * Allocate tty3270 structure.
+ * Allocate fs3270 structure.
*/
static struct fs3270 *
fs3270_alloc_view(void)
@@ -243,8 +371,8 @@ fs3270_alloc_view(void)
if (!fp)
return ERR_PTR(-ENOMEM);
memset(fp, 0, sizeof(struct fs3270));
- fp->clear = raw3270_request_alloc(0);
- if (!IS_ERR(fp->clear)) {
+ fp->init = raw3270_request_alloc(0);
+ if (IS_ERR(fp->init)) {
kfree(fp);
return ERR_PTR(-ENOMEM);
}
@@ -252,12 +380,17 @@ fs3270_alloc_view(void)
}
/*
- * Free tty3270 structure.
+ * Free fs3270 structure.
*/
static void
fs3270_free_view(struct raw3270_view *view)
{
- raw3270_request_free(((struct fs3270 *) view)->clear);
+ struct fs3270 *fp;
+
+ fp = (struct fs3270 *) view;
+ if (fp->rdbuf)
+ idal_buffer_free(fp->rdbuf);
+ raw3270_request_free(((struct fs3270 *) view)->init);
kfree(view);
}
@@ -285,11 +418,20 @@ static int
fs3270_open(struct inode *inode, struct file *filp)
{
struct fs3270 *fp;
+ struct idal_buffer *ib;
int minor, rc;
if (imajor(filp->f_dentry->d_inode) != IBM_FS3270_MAJOR)
return -ENODEV;
minor = iminor(filp->f_dentry->d_inode);
+ /* Check for minor 0 multiplexer. */
+ if (minor == 0) {
+ if (!current->signal->tty)
+ return -ENODEV;
+ if (current->signal->tty->driver->major != IBM_TTY3270_MAJOR)
+ return -ENODEV;
+ minor = current->signal->tty->index + RAW3270_FIRSTMINOR;
+ }
/* Check if some other program is already using fullscreen mode. */
fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor);
if (!IS_ERR(fp)) {
@@ -301,7 +443,7 @@ fs3270_open(struct inode *inode, struct file *filp)
if (IS_ERR(fp))
return PTR_ERR(fp);
- init_waitqueue_head(&fp->attn_wait);
+ init_waitqueue_head(&fp->wait);
fp->fs_pid = current->pid;
rc = raw3270_add_view(&fp->view, &fs3270_fn, minor);
if (rc) {
@@ -309,8 +451,18 @@ fs3270_open(struct inode *inode, struct file *filp)
return rc;
}
+ /* Allocate idal-buffer. */
+ ib = idal_buffer_alloc(2*fp->view.rows*fp->view.cols + 5, 0);
+ if (IS_ERR(ib)) {
+ raw3270_put_view(&fp->view);
+ raw3270_del_view(&fp->view);
+ return PTR_ERR(fp);
+ }
+ fp->rdbuf = ib;
+
rc = raw3270_activate_view(&fp->view);
if (rc) {
+ raw3270_put_view(&fp->view);
raw3270_del_view(&fp->view);
return rc;
}
@@ -329,8 +481,12 @@ fs3270_close(struct inode *inode, struct file *filp)
fp = filp->private_data;
filp->private_data = 0;
- if (fp)
+ if (fp) {
+ fp->fs_pid = 0;
+ raw3270_reset(&fp->view);
+ raw3270_put_view(&fp->view);
raw3270_del_view(&fp->view);
+ }
return 0;
}
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 328d9cbc56a3..d66946443dfc 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -25,6 +25,12 @@
#include "raw3270.h"
+#include <linux/major.h>
+#include <linux/kdev_t.h>
+#include <linux/device.h>
+
+struct class *class3270;
+
/* The main 3270 data structure. */
struct raw3270 {
struct list_head list;
@@ -41,6 +47,8 @@ struct raw3270 {
struct timer_list timer; /* Device timer. */
unsigned char *ascebc; /* ascii -> ebcdic table */
+ struct class_device *clttydev; /* 3270-class tty device ptr */
+ struct class_device *cltubdev; /* 3270-class tub device ptr */
};
/* raw3270->flags */
@@ -317,6 +325,22 @@ raw3270_start(struct raw3270_view *view, struct raw3270_request *rq)
}
int
+raw3270_start_locked(struct raw3270_view *view, struct raw3270_request *rq)
+{
+ struct raw3270 *rp;
+ int rc;
+
+ rp = view->dev;
+ if (!rp || rp->view != view)
+ rc = -EACCES;
+ else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
+ rc = -ENODEV;
+ else
+ rc = __raw3270_start(rp, view, rq);
+ return rc;
+}
+
+int
raw3270_start_irq(struct raw3270_view *view, struct raw3270_request *rq)
{
struct raw3270 *rp;
@@ -744,6 +768,22 @@ raw3270_reset_device(struct raw3270 *rp)
return rc;
}
+int
+raw3270_reset(struct raw3270_view *view)
+{
+ struct raw3270 *rp;
+ int rc;
+
+ rp = view->dev;
+ if (!rp || rp->view != view)
+ rc = -EACCES;
+ else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
+ rc = -ENODEV;
+ else
+ rc = raw3270_reset_device(view->dev);
+ return rc;
+}
+
/*
* Setup new 3270 device.
*/
@@ -774,11 +814,12 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
/*
* Add device to list and find the smallest unused minor
- * number for it.
+ * number for it. Note: there is no device with minor 0,
+ * see special case for fs3270.c:fs3270_open().
*/
down(&raw3270_sem);
/* Keep the list sorted. */
- minor = 0;
+ minor = RAW3270_FIRSTMINOR;
rp->minor = -1;
list_for_each(l, &raw3270_devices) {
tmp = list_entry(l, struct raw3270, list);
@@ -789,7 +830,7 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
}
minor++;
}
- if (rp->minor == -1 && minor < RAW3270_MAXDEVS) {
+ if (rp->minor == -1 && minor < RAW3270_MAXDEVS + RAW3270_FIRSTMINOR) {
rp->minor = minor;
list_add_tail(&rp->list, &raw3270_devices);
}
@@ -941,11 +982,12 @@ raw3270_deactivate_view(struct raw3270_view *view)
list_add_tail(&view->list, &rp->view_list);
/* Try to activate another view. */
if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
- list_for_each_entry(view, &rp->view_list, list)
- if (view->fn->activate(view) == 0) {
- rp->view = view;
+ list_for_each_entry(view, &rp->view_list, list) {
+ rp->view = view;
+ if (view->fn->activate(view) == 0)
break;
- }
+ rp->view = 0;
+ }
}
}
spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
@@ -961,6 +1003,8 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor)
struct raw3270 *rp;
int rc;
+ if (minor <= 0)
+ return -ENODEV;
down(&raw3270_sem);
rc = -ENODEV;
list_for_each_entry(rp, &raw3270_devices, list) {
@@ -976,7 +1020,7 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor)
view->cols = rp->cols;
view->ascebc = rp->ascebc;
spin_lock_init(&view->lock);
- list_add_tail(&view->list, &rp->view_list);
+ list_add(&view->list, &rp->view_list);
rc = 0;
}
spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
@@ -1039,7 +1083,7 @@ raw3270_del_view(struct raw3270_view *view)
if (!rp->view && test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
/* Try to activate another view. */
list_for_each_entry(nv, &rp->view_list, list) {
- if (nv->fn->activate(view) == 0) {
+ if (nv->fn->activate(nv) == 0) {
rp->view = nv;
break;
}
@@ -1063,6 +1107,12 @@ raw3270_delete_device(struct raw3270 *rp)
/* Remove from device chain. */
down(&raw3270_sem);
+ if (rp->clttydev)
+ class_device_destroy(class3270,
+ MKDEV(IBM_TTY3270_MAJOR, rp->minor));
+ if (rp->cltubdev)
+ class_device_destroy(class3270,
+ MKDEV(IBM_FS3270_MAJOR, rp->minor));
list_del_init(&rp->list);
up(&raw3270_sem);
@@ -1129,6 +1179,16 @@ raw3270_create_attributes(struct raw3270 *rp)
{
//FIXME: check return code
sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
+ rp->clttydev =
+ class_device_create(class3270,
+ MKDEV(IBM_TTY3270_MAJOR, rp->minor),
+ &rp->cdev->dev, "tty%s",
+ rp->cdev->dev.bus_id);
+ rp->cltubdev =
+ class_device_create(class3270,
+ MKDEV(IBM_FS3270_MAJOR, rp->minor),
+ &rp->cdev->dev, "tub%s",
+ rp->cdev->dev.bus_id);
}
/*
@@ -1189,13 +1249,13 @@ raw3270_set_online (struct ccw_device *cdev)
return PTR_ERR(rp);
rc = raw3270_reset_device(rp);
if (rc)
- return rc;
+ goto failure;
rc = raw3270_size_device(rp);
if (rc)
- return rc;
+ goto failure;
rc = raw3270_reset_device(rp);
if (rc)
- return rc;
+ goto failure;
raw3270_create_attributes(rp);
set_bit(RAW3270_FLAGS_READY, &rp->flags);
down(&raw3270_sem);
@@ -1203,6 +1263,10 @@ raw3270_set_online (struct ccw_device *cdev)
np->notifier(rp->minor, 1);
up(&raw3270_sem);
return 0;
+
+failure:
+ raw3270_delete_device(rp);
+ return rc;
}
/*
@@ -1217,6 +1281,14 @@ raw3270_remove (struct ccw_device *cdev)
struct raw3270_notifier *np;
rp = cdev->dev.driver_data;
+ /*
+ * _remove is the opposite of _probe; it's probe that
+ * should set up rp. raw3270_remove gets entered for
+ * devices even if they haven't been varied online.
+ * Thus, rp may validly be NULL here.
+ */
+ if (rp == NULL)
+ return;
clear_bit(RAW3270_FLAGS_READY, &rp->flags);
sysfs_remove_group(&cdev->dev.kobj, &raw3270_attr_group);
@@ -1301,6 +1373,7 @@ raw3270_init(void)
if (rc == 0) {
/* Create attributes for early (= console) device. */
down(&raw3270_sem);
+ class3270 = class_create(THIS_MODULE, "3270");
list_for_each_entry(rp, &raw3270_devices, list) {
get_device(&rp->cdev->dev);
raw3270_create_attributes(rp);
@@ -1314,6 +1387,7 @@ static void
raw3270_exit(void)
{
ccw_driver_unregister(&raw3270_ccw_driver);
+ class_destroy(class3270);
}
MODULE_LICENSE("GPL");
@@ -1335,7 +1409,9 @@ EXPORT_SYMBOL(raw3270_find_view);
EXPORT_SYMBOL(raw3270_activate_view);
EXPORT_SYMBOL(raw3270_deactivate_view);
EXPORT_SYMBOL(raw3270_start);
+EXPORT_SYMBOL(raw3270_start_locked);
EXPORT_SYMBOL(raw3270_start_irq);
+EXPORT_SYMBOL(raw3270_reset);
EXPORT_SYMBOL(raw3270_register_notifier);
EXPORT_SYMBOL(raw3270_unregister_notifier);
EXPORT_SYMBOL(raw3270_wait_queue);
diff --git a/drivers/s390/char/raw3270.h b/drivers/s390/char/raw3270.h
index ed5d4eb9f623..b635bf8e7775 100644
--- a/drivers/s390/char/raw3270.h
+++ b/drivers/s390/char/raw3270.h
@@ -21,6 +21,7 @@
/* Local Channel Commands */
#define TC_WRITE 0x01 /* Write */
+#define TC_RDBUF 0x02 /* Read Buffer */
#define TC_EWRITE 0x05 /* Erase write */
#define TC_READMOD 0x06 /* Read modified */
#define TC_EWRITEA 0x0d /* Erase write alternate */
@@ -76,7 +77,8 @@
#define TW_KR 0xc2 /* Keyboard restore */
#define TW_PLUSALARM 0x04 /* Add this bit for alarm */
-#define RAW3270_MAXDEVS 256
+#define RAW3270_FIRSTMINOR 1 /* First minor number */
+#define RAW3270_MAXDEVS 255 /* Max number of 3270 devices */
/* For TUBGETMOD and TUBSETMOD. Should include. */
struct raw3270_iocb {
@@ -166,7 +168,10 @@ void raw3270_del_view(struct raw3270_view *);
void raw3270_deactivate_view(struct raw3270_view *);
struct raw3270_view *raw3270_find_view(struct raw3270_fn *, int);
int raw3270_start(struct raw3270_view *, struct raw3270_request *);
+int raw3270_start_locked(struct raw3270_view *, struct raw3270_request *);
int raw3270_start_irq(struct raw3270_view *, struct raw3270_request *);
+int raw3270_reset(struct raw3270_view *);
+struct raw3270_view *raw3270_view(struct raw3270_view *);
/* Reference count inliner for view structures. */
static inline void
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index ed0cb1f15b4c..fcaee447d6fe 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -72,6 +72,7 @@ struct tape_class_device *register_tape_dev(
tcd->class_device = class_device_create(
tape_class,
+ NULL,
tcd->char_device->dev,
device,
"%s", tcd->device_name
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 7db5ebce7f0f..4b9069370388 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -653,18 +653,12 @@ tty3270_activate(struct raw3270_view *view)
tp->update_flags = TTY_UPDATE_ALL;
tty3270_set_timer(tp, 1);
spin_unlock_irqrestore(&tp->view.lock, flags);
- start_tty(tp->tty);
return 0;
}
static void
tty3270_deactivate(struct raw3270_view *view)
{
- struct tty3270 *tp;
-
- tp = (struct tty3270 *) view;
- if (tp && tp->tty)
- stop_tty(tp->tty);
}
static int
@@ -716,13 +710,13 @@ tty3270_alloc_view(void)
tp->freemem_pages[pages], PAGE_SIZE);
}
tp->write = raw3270_request_alloc(TTY3270_OUTPUT_BUFFER_SIZE);
- if (!tp->write)
+ if (IS_ERR(tp->write))
goto out_pages;
tp->read = raw3270_request_alloc(0);
- if (!tp->read)
+ if (IS_ERR(tp->read))
goto out_write;
tp->kreset = raw3270_request_alloc(1);
- if (!tp->kreset)
+ if (IS_ERR(tp->kreset))
goto out_read;
tp->kbd = kbd_alloc();
if (!tp->kbd)
@@ -845,7 +839,8 @@ tty3270_del_views(void)
int i;
for (i = 0; i < tty3270_max_index; i++) {
- tp = (struct tty3270 *) raw3270_find_view(&tty3270_fn, i);
+ tp = (struct tty3270 *)
+ raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR);
if (!IS_ERR(tp))
raw3270_del_view(&tp->view);
}
@@ -871,7 +866,9 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
if (tty->count > 1)
return 0;
/* Check if the tty3270 is already there. */
- tp = (struct tty3270 *) raw3270_find_view(&tty3270_fn, tty->index);
+ tp = (struct tty3270 *)
+ raw3270_find_view(&tty3270_fn,
+ tty->index + RAW3270_FIRSTMINOR);
if (!IS_ERR(tp)) {
tty->driver_data = tp;
tty->winsize.ws_row = tp->view.rows - 2;
@@ -903,7 +900,8 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
(void (*)(unsigned long)) tty3270_read_tasklet,
(unsigned long) tp->read);
- rc = raw3270_add_view(&tp->view, &tty3270_fn, tty->index);
+ rc = raw3270_add_view(&tp->view, &tty3270_fn,
+ tty->index + RAW3270_FIRSTMINOR);
if (rc) {
tty3270_free_view(tp);
return rc;
@@ -911,8 +909,8 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
rc = tty3270_alloc_screen(tp);
if (rc) {
- raw3270_del_view(&tp->view);
raw3270_put_view(&tp->view);
+ raw3270_del_view(&tp->view);
return rc;
}
@@ -1780,7 +1778,7 @@ tty3270_init(void)
struct tty_driver *driver;
int ret;
- driver = alloc_tty_driver(256);
+ driver = alloc_tty_driver(RAW3270_MAXDEVS);
if (!driver)
return -ENOMEM;
@@ -1794,6 +1792,7 @@ tty3270_init(void)
driver->driver_name = "ttyTUB";
driver->name = "ttyTUB";
driver->major = IBM_TTY3270_MAJOR;
+ driver->minor_start = RAW3270_FIRSTMINOR;
driver->type = TTY_DRIVER_TYPE_SYSTEM;
driver->subtype = SYSTEM_TYPE_TTY;
driver->init_termios = tty_std_termios;
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 491f00c032e8..b2d75de144c6 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -788,6 +788,7 @@ vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
}
priv->class_device = class_device_create(
vmlogrdr_class,
+ NULL,
MKDEV(vmlogrdr_major, priv->minor_num),
dev,
"%s", dev->bus_id );
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 8cc4f1a940dc..c05b069c2996 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -30,10 +30,13 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/timex.h> /* get_clock() */
#include <asm/ccwdev.h>
#include <asm/cio.h>
#include <asm/cmb.h>
+#include <asm/div64.h>
#include "cio.h"
#include "css.h"
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 9adc11e8b8bc..811c9d150637 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -22,6 +22,7 @@
#include <asm/ccwdev.h>
#include <asm/cio.h>
+#include <asm/param.h> /* HZ */
#include "cio.h"
#include "css.h"
@@ -252,6 +253,23 @@ cutype_show (struct device *dev, struct device_attribute *attr, char *buf)
}
static ssize_t
+modalias_show (struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct ccw_device *cdev = to_ccwdev(dev);
+ struct ccw_device_id *id = &(cdev->id);
+ int ret;
+
+ ret = sprintf(buf, "ccw:t%04Xm%02x",
+ id->cu_type, id->cu_model);
+ if (id->dev_type != 0)
+ ret += sprintf(buf + ret, "dt%04Xdm%02X\n",
+ id->dev_type, id->dev_model);
+ else
+ ret += sprintf(buf + ret, "dtdm\n");
+ return ret;
+}
+
+static ssize_t
online_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct ccw_device *cdev = to_ccwdev(dev);
@@ -448,6 +466,7 @@ static DEVICE_ATTR(chpids, 0444, chpids_show, NULL);
static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL);
static DEVICE_ATTR(devtype, 0444, devtype_show, NULL);
static DEVICE_ATTR(cutype, 0444, cutype_show, NULL);
+static DEVICE_ATTR(modalias, 0444, modalias_show, NULL);
static DEVICE_ATTR(online, 0644, online_show, online_store);
extern struct device_attribute dev_attr_cmb_enable;
static DEVICE_ATTR(availability, 0444, available_show, NULL);
@@ -471,6 +490,7 @@ subchannel_add_files (struct device *dev)
static struct attribute * ccwdev_attrs[] = {
&dev_attr_devtype.attr,
&dev_attr_cutype.attr,
+ &dev_attr_modalias.attr,
&dev_attr_online.attr,
&dev_attr_cmb_enable.attr,
&dev_attr_availability.attr,
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index fbe4202a3f6f..c1c89f4fd4e3 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -11,6 +11,8 @@
#include <linux/module.h>
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
#include <asm/ccwdev.h>
#include <asm/cio.h>
diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c
index fa09440d82e5..38f50b7129a2 100644
--- a/drivers/s390/net/fsm.c
+++ b/drivers/s390/net/fsm.c
@@ -16,7 +16,7 @@ MODULE_LICENSE("GPL");
fsm_instance *
init_fsm(char *name, const char **state_names, const char **event_names, int nr_states,
- int nr_events, const fsm_node *tmpl, int tmpl_len, int order)
+ int nr_events, const fsm_node *tmpl, int tmpl_len, gfp_t order)
{
int i;
fsm_instance *this;
diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h
index f9a011001eb6..1b8a7e7c34f3 100644
--- a/drivers/s390/net/fsm.h
+++ b/drivers/s390/net/fsm.h
@@ -110,7 +110,7 @@ extern fsm_instance *
init_fsm(char *name, const char **state_names,
const char **event_names,
int nr_states, int nr_events, const fsm_node *tmpl,
- int tmpl_len, int order);
+ int tmpl_len, gfp_t order);
/**
* Releases an FSM
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 9963479ba89f..38a2441564d7 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -275,6 +275,10 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \
QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \
QETH_MAX_QUEUES,0x103}, \
+ {0x1731,0x06,0x1732,0x06,QETH_CARD_TYPE_OSN,0, \
+ QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
+ QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
+ QETH_MAX_QUEUES,0}, \
{0,0,0,0,0,0,0,0,0}}
#define QETH_REAL_CARD 1
@@ -363,10 +367,22 @@ struct qeth_hdr_layer2 {
__u8 reserved2[16];
} __attribute__ ((packed));
+struct qeth_hdr_osn {
+ __u8 id;
+ __u8 reserved;
+ __u16 seq_no;
+ __u16 reserved2;
+ __u16 control_flags;
+ __u16 pdu_length;
+ __u8 reserved3[18];
+ __u32 ccid;
+} __attribute__ ((packed));
+
struct qeth_hdr {
union {
struct qeth_hdr_layer2 l2;
struct qeth_hdr_layer3 l3;
+ struct qeth_hdr_osn osn;
} hdr;
} __attribute__ ((packed));
@@ -413,6 +429,7 @@ enum qeth_header_ids {
QETH_HEADER_TYPE_LAYER3 = 0x01,
QETH_HEADER_TYPE_LAYER2 = 0x02,
QETH_HEADER_TYPE_TSO = 0x03,
+ QETH_HEADER_TYPE_OSN = 0x04,
};
/* flags for qeth_hdr.ext_flags */
#define QETH_HDR_EXT_VLAN_FRAME 0x01
@@ -582,7 +599,6 @@ enum qeth_card_states {
* Protocol versions
*/
enum qeth_prot_versions {
- QETH_PROT_SNA = 0x0001,
QETH_PROT_IPV4 = 0x0004,
QETH_PROT_IPV6 = 0x0006,
};
@@ -761,6 +777,11 @@ enum qeth_threads {
QETH_RECOVER_THREAD = 2,
};
+struct qeth_osn_info {
+ int (*assist_cb)(struct net_device *dev, void *data);
+ int (*data_cb)(struct sk_buff *skb);
+};
+
struct qeth_card {
struct list_head list;
enum qeth_card_states state;
@@ -803,6 +824,7 @@ struct qeth_card {
int use_hard_stop;
int (*orig_hard_header)(struct sk_buff *,struct net_device *,
unsigned short,void *,void *,unsigned);
+ struct qeth_osn_info osn_info;
};
struct qeth_card_list_struct {
@@ -916,10 +938,12 @@ qeth_get_hlen(__u8 link_type)
static inline unsigned short
qeth_get_netdev_flags(struct qeth_card *card)
{
- if (card->options.layer2)
+ if (card->options.layer2 &&
+ (card->info.type == QETH_CARD_TYPE_OSAE))
return 0;
switch (card->info.type) {
case QETH_CARD_TYPE_IQD:
+ case QETH_CARD_TYPE_OSN:
return IFF_NOARP;
#ifdef CONFIG_QETH_IPV6
default:
@@ -956,9 +980,10 @@ static inline int
qeth_get_max_mtu_for_card(int cardtype)
{
switch (cardtype) {
+
case QETH_CARD_TYPE_UNKNOWN:
- return 61440;
case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSN:
return 61440;
case QETH_CARD_TYPE_IQD:
return 57344;
@@ -1004,6 +1029,7 @@ qeth_mtu_is_valid(struct qeth_card * card, int mtu)
case QETH_CARD_TYPE_IQD:
return ((mtu >= 576) &&
(mtu <= card->info.max_mtu + 4096 - 32));
+ case QETH_CARD_TYPE_OSN:
case QETH_CARD_TYPE_UNKNOWN:
default:
return 1;
@@ -1015,6 +1041,7 @@ qeth_get_arphdr_type(int cardtype, int linktype)
{
switch (cardtype) {
case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSN:
switch (linktype) {
case QETH_LINK_TYPE_LANE_TR:
case QETH_LINK_TYPE_HSTR:
@@ -1182,4 +1209,16 @@ qeth_fill_header(struct qeth_card *, struct qeth_hdr *,
extern void
qeth_flush_buffers(struct qeth_qdio_out_q *, int, int, int);
+extern int
+qeth_osn_assist(struct net_device *, void *, int);
+
+extern int
+qeth_osn_register(unsigned char *read_dev_no,
+ struct net_device **,
+ int (*assist_cb)(struct net_device *, void *),
+ int (*data_cb)(struct sk_buff *));
+
+extern void
+qeth_osn_deregister(struct net_device *);
+
#endif /* __QETH_H__ */
diff --git a/drivers/s390/net/qeth_fs.h b/drivers/s390/net/qeth_fs.h
index 5c9a51ce91b6..c0b4c8d82c45 100644
--- a/drivers/s390/net/qeth_fs.h
+++ b/drivers/s390/net/qeth_fs.h
@@ -12,7 +12,7 @@
#ifndef __QETH_FS_H__
#define __QETH_FS_H__
-#define VERSION_QETH_FS_H "$Revision: 1.9 $"
+#define VERSION_QETH_FS_H "$Revision: 1.10 $"
extern const char *VERSION_QETH_PROC_C;
extern const char *VERSION_QETH_SYS_C;
@@ -43,6 +43,12 @@ extern void
qeth_remove_device_attributes(struct device *dev);
extern int
+qeth_create_device_attributes_osn(struct device *dev);
+
+extern void
+qeth_remove_device_attributes_osn(struct device *dev);
+
+extern int
qeth_create_driver_attributes(void);
extern void
@@ -108,6 +114,8 @@ qeth_get_cardname(struct qeth_card *card)
return " OSD Express";
case QETH_CARD_TYPE_IQD:
return " HiperSockets";
+ case QETH_CARD_TYPE_OSN:
+ return " OSN QDIO";
default:
return " unknown";
}
@@ -153,6 +161,8 @@ qeth_get_cardname_short(struct qeth_card *card)
}
case QETH_CARD_TYPE_IQD:
return "HiperSockets";
+ case QETH_CARD_TYPE_OSN:
+ return "OSN";
default:
return "unknown";
}
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index bd28e2438d7f..692003c9f896 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -196,7 +196,6 @@ qeth_notifier_register(struct task_struct *p, int signum)
{
struct qeth_notify_list_struct *n_entry;
-
/*check first if entry already exists*/
spin_lock(&qeth_notify_lock);
list_for_each_entry(n_entry, &qeth_notify_list, list) {
@@ -1024,7 +1023,10 @@ qeth_set_intial_options(struct qeth_card *card)
card->options.fake_broadcast = 0;
card->options.add_hhlen = DEFAULT_ADD_HHLEN;
card->options.fake_ll = 0;
- card->options.layer2 = 0;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ card->options.layer2 = 1;
+ else
+ card->options.layer2 = 0;
}
/**
@@ -1113,19 +1115,20 @@ qeth_determine_card_type(struct qeth_card *card)
QETH_DBF_TEXT(setup, 2, "detcdtyp");
+ card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+ card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
while (known_devices[i][4]) {
if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
(CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
card->info.type = known_devices[i][4];
+ card->qdio.no_out_queues = known_devices[i][8];
+ card->info.is_multicast_different = known_devices[i][9];
if (is_1920_device(card)) {
PRINT_INFO("Priority Queueing not able "
"due to hardware limitations!\n");
card->qdio.no_out_queues = 1;
card->qdio.default_out_queue = 0;
- } else {
- card->qdio.no_out_queues = known_devices[i][8];
- }
- card->info.is_multicast_different = known_devices[i][9];
+ }
return 0;
}
i++;
@@ -1149,6 +1152,8 @@ qeth_probe_device(struct ccwgroup_device *gdev)
if (!get_device(dev))
return -ENODEV;
+ QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);
+
card = qeth_alloc_card();
if (!card) {
put_device(dev);
@@ -1158,28 +1163,27 @@ qeth_probe_device(struct ccwgroup_device *gdev)
card->read.ccwdev = gdev->cdev[0];
card->write.ccwdev = gdev->cdev[1];
card->data.ccwdev = gdev->cdev[2];
-
- if ((rc = qeth_setup_card(card))){
- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
- put_device(dev);
- qeth_free_card(card);
- return rc;
- }
gdev->dev.driver_data = card;
card->gdev = gdev;
gdev->cdev[0]->handler = qeth_irq;
gdev->cdev[1]->handler = qeth_irq;
gdev->cdev[2]->handler = qeth_irq;
- rc = qeth_create_device_attributes(dev);
- if (rc) {
+ if ((rc = qeth_determine_card_type(card))){
+ PRINT_WARN("%s: not a valid card type\n", __func__);
+ QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+ put_device(dev);
+ qeth_free_card(card);
+ return rc;
+ }
+ if ((rc = qeth_setup_card(card))){
+ QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
put_device(dev);
qeth_free_card(card);
return rc;
}
- if ((rc = qeth_determine_card_type(card))){
- PRINT_WARN("%s: not a valid card type\n", __func__);
- QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+ rc = qeth_create_device_attributes(dev);
+ if (rc) {
put_device(dev);
qeth_free_card(card);
return rc;
@@ -1660,6 +1664,8 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
netif_carrier_on(card->dev);
qeth_schedule_recovery(card);
return NULL;
+ case IPA_CMD_MODCCID:
+ return cmd;
case IPA_CMD_REGISTER_LOCAL_ADDR:
QETH_DBF_TEXT(trace,3, "irla");
break;
@@ -1721,6 +1727,14 @@ qeth_send_control_data_cb(struct qeth_channel *channel,
cmd = qeth_check_ipa_data(card, iob);
if ((cmd == NULL) && (card->state != CARD_STATE_DOWN))
goto out;
+ /*in case of OSN : check if cmd is set */
+ if (card->info.type == QETH_CARD_TYPE_OSN &&
+ cmd &&
+ cmd->hdr.command != IPA_CMD_STARTLAN &&
+ card->osn_info.assist_cb != NULL) {
+ card->osn_info.assist_cb(card->dev, cmd);
+ goto out;
+ }
spin_lock_irqsave(&card->lock, flags);
list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
@@ -1737,8 +1751,7 @@ qeth_send_control_data_cb(struct qeth_channel *channel,
keep_reply = reply->callback(card,
reply,
(unsigned long)cmd);
- }
- else
+ } else
keep_reply = reply->callback(card,
reply,
(unsigned long)iob);
@@ -1768,6 +1781,24 @@ out:
qeth_release_buffer(channel,iob);
}
+static inline void
+qeth_prepare_control_data(struct qeth_card *card, int len,
+struct qeth_cmd_buffer *iob)
+{
+ qeth_setup_ccw(&card->write,iob->data,len);
+ iob->callback = qeth_release_buffer;
+
+ memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+ &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+ card->seqno.trans_hdr++;
+ memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
+ &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
+ card->seqno.pdu_hdr++;
+ memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
+ &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
+ QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
+}
+
static int
qeth_send_control_data(struct qeth_card *card, int len,
struct qeth_cmd_buffer *iob,
@@ -1778,24 +1809,11 @@ qeth_send_control_data(struct qeth_card *card, int len,
{
int rc;
unsigned long flags;
- struct qeth_reply *reply;
+ struct qeth_reply *reply = NULL;
struct timer_list timer;
QETH_DBF_TEXT(trace, 2, "sendctl");
- qeth_setup_ccw(&card->write,iob->data,len);
-
- memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
- &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
- card->seqno.trans_hdr++;
-
- memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
- &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
- card->seqno.pdu_hdr++;
- memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
- &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
- iob->callback = qeth_release_buffer;
-
reply = qeth_alloc_reply(card);
if (!reply) {
PRINT_WARN("Could no alloc qeth_reply!\n");
@@ -1810,10 +1828,6 @@ qeth_send_control_data(struct qeth_card *card, int len,
init_timer(&timer);
timer.function = qeth_cmd_timeout;
timer.data = (unsigned long) reply;
- if (IS_IPA(iob->data))
- timer.expires = jiffies + QETH_IPA_TIMEOUT;
- else
- timer.expires = jiffies + QETH_TIMEOUT;
init_waitqueue_head(&reply->wait_q);
spin_lock_irqsave(&card->lock, flags);
list_add_tail(&reply->list, &card->cmd_waiter_list);
@@ -1821,6 +1835,11 @@ qeth_send_control_data(struct qeth_card *card, int len,
QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
wait_event(card->wait_q,
atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+ qeth_prepare_control_data(card, len, iob);
+ if (IS_IPA(iob->data))
+ timer.expires = jiffies + QETH_IPA_TIMEOUT;
+ else
+ timer.expires = jiffies + QETH_TIMEOUT;
QETH_DBF_TEXT(trace, 6, "noirqpnd");
spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
@@ -1848,6 +1867,62 @@ qeth_send_control_data(struct qeth_card *card, int len,
}
static int
+qeth_osn_send_control_data(struct qeth_card *card, int len,
+ struct qeth_cmd_buffer *iob)
+{
+ unsigned long flags;
+ int rc = 0;
+
+ QETH_DBF_TEXT(trace, 5, "osndctrd");
+
+ wait_event(card->wait_q,
+ atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+ qeth_prepare_control_data(card, len, iob);
+ QETH_DBF_TEXT(trace, 6, "osnoirqp");
+ spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
+ rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
+ (addr_t) iob, 0, 0);
+ spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
+ if (rc){
+ PRINT_WARN("qeth_osn_send_control_data: "
+ "ccw_device_start rc = %i\n", rc);
+ QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+ qeth_release_buffer(iob->channel, iob);
+ atomic_set(&card->write.irq_pending, 0);
+ wake_up(&card->wait_q);
+ }
+ return rc;
+}
+
+static inline void
+qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+ char prot_type)
+{
+ memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+ memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
+ memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+ &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+}
+
+static int
+qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+ int data_len)
+{
+ u16 s1, s2;
+
+QETH_DBF_TEXT(trace,4,"osndipa");
+
+ qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
+ s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
+ s2 = (u16)data_len;
+ memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+ memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+ memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+ memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+ return qeth_osn_send_control_data(card, s1, iob);
+}
+
+static int
qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
int (*reply_cb)
(struct qeth_card *,struct qeth_reply*, unsigned long),
@@ -1858,17 +1933,14 @@ qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
QETH_DBF_TEXT(trace,4,"sendipa");
- memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
-
if (card->options.layer2)
- prot_type = QETH_PROT_LAYER2;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ prot_type = QETH_PROT_OSN2;
+ else
+ prot_type = QETH_PROT_LAYER2;
else
prot_type = QETH_PROT_TCPIP;
-
- memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
- memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
- &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
-
+ qeth_prepare_ipa_cmd(card,iob,prot_type);
rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob,
reply_cb, reply_param);
return rc;
@@ -2010,7 +2082,10 @@ qeth_ulp_enable(struct qeth_card *card)
*(QETH_ULP_ENABLE_LINKNUM(iob->data)) =
(__u8) card->info.portno;
if (card->options.layer2)
- prot_type = QETH_PROT_LAYER2;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ prot_type = QETH_PROT_OSN2;
+ else
+ prot_type = QETH_PROT_LAYER2;
else
prot_type = QETH_PROT_TCPIP;
@@ -2100,15 +2175,21 @@ qeth_check_for_inbound_error(struct qeth_qdio_buffer *buf,
}
static inline struct sk_buff *
-qeth_get_skb(unsigned int length)
+qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
{
struct sk_buff* skb;
+ int add_len;
+
+ add_len = 0;
+ if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN)
+ add_len = sizeof(struct qeth_hdr);
#ifdef CONFIG_QETH_VLAN
- if ((skb = dev_alloc_skb(length + VLAN_HLEN)))
- skb_reserve(skb, VLAN_HLEN);
-#else
- skb = dev_alloc_skb(length);
+ else
+ add_len = VLAN_HLEN;
#endif
+ skb = dev_alloc_skb(length + add_len);
+ if (skb && add_len)
+ skb_reserve(skb, add_len);
return skb;
}
@@ -2138,7 +2219,10 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
offset += sizeof(struct qeth_hdr);
if (card->options.layer2)
- skb_len = (*hdr)->hdr.l2.pkt_length;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ skb_len = (*hdr)->hdr.osn.pdu_length;
+ else
+ skb_len = (*hdr)->hdr.l2.pkt_length;
else
skb_len = (*hdr)->hdr.l3.length;
@@ -2146,15 +2230,15 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
return NULL;
if (card->options.fake_ll){
if(card->dev->type == ARPHRD_IEEE802_TR){
- if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR)))
+ if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR, *hdr)))
goto no_mem;
skb_reserve(skb,QETH_FAKE_LL_LEN_TR);
} else {
- if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH)))
+ if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH, *hdr)))
goto no_mem;
skb_reserve(skb,QETH_FAKE_LL_LEN_ETH);
}
- } else if (!(skb = qeth_get_skb(skb_len)))
+ } else if (!(skb = qeth_get_skb(skb_len, *hdr)))
goto no_mem;
data_ptr = element->addr + offset;
while (skb_len) {
@@ -2453,8 +2537,12 @@ qeth_process_inbound_buffer(struct qeth_card *card,
skb->dev = card->dev;
if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr);
- else
+ else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)
qeth_rebuild_skb(card, skb, hdr);
+ else { /*in case of OSN*/
+ skb_push(skb, sizeof(struct qeth_hdr));
+ memcpy(skb->data, hdr, sizeof(struct qeth_hdr));
+ }
/* is device UP ? */
if (!(card->dev->flags & IFF_UP)){
dev_kfree_skb_any(skb);
@@ -2465,7 +2553,10 @@ qeth_process_inbound_buffer(struct qeth_card *card,
vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag);
else
#endif
- rxrc = netif_rx(skb);
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ rxrc = card->osn_info.data_cb(skb);
+ else
+ rxrc = netif_rx(skb);
card->dev->last_rx = jiffies;
card->stats.rx_packets++;
card->stats.rx_bytes += skb->len;
@@ -3150,8 +3241,6 @@ qeth_init_qdio_info(struct qeth_card *card)
INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
/* outbound */
- card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
- card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
}
static int
@@ -3466,7 +3555,7 @@ qeth_mpc_initialize(struct qeth_card *card)
return 0;
out_qdio:
- qeth_qdio_clear_card(card, card->info.type==QETH_CARD_TYPE_OSAE);
+ qeth_qdio_clear_card(card, card->info.type!=QETH_CARD_TYPE_IQD);
return rc;
}
@@ -3491,6 +3580,9 @@ qeth_get_netdevice(enum qeth_card_types type, enum qeth_link_types linktype)
case QETH_CARD_TYPE_IQD:
dev = alloc_netdev(0, "hsi%d", ether_setup);
break;
+ case QETH_CARD_TYPE_OSN:
+ dev = alloc_netdev(0, "osn%d", ether_setup);
+ break;
default:
dev = alloc_etherdev(0);
}
@@ -3655,7 +3747,8 @@ qeth_open(struct net_device *dev)
if (card->state != CARD_STATE_SOFTSETUP)
return -ENODEV;
- if ( (card->options.layer2) &&
+ if ( (card->info.type != QETH_CARD_TYPE_OSN) &&
+ (card->options.layer2) &&
(!card->info.layer2_mac_registered)) {
QETH_DBF_TEXT(trace,4,"nomacadr");
return -EPERM;
@@ -3693,6 +3786,9 @@ qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
{
int cast_type = RTN_UNSPEC;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return cast_type;
+
if (skb->dst && skb->dst->neighbour){
cast_type = skb->dst->neighbour->type;
if ((cast_type == RTN_BROADCAST) ||
@@ -3782,13 +3878,16 @@ static inline int
qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
struct qeth_hdr **hdr, int ipv)
{
- int rc;
+ int rc = 0;
#ifdef CONFIG_QETH_VLAN
u16 *tag;
#endif
QETH_DBF_TEXT(trace, 6, "prepskb");
-
+ if (card->info.type == QETH_CARD_TYPE_OSN) {
+ *hdr = (struct qeth_hdr *)(*skb)->data;
+ return rc;
+ }
rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
if (rc)
return rc;
@@ -4291,8 +4390,14 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
}
}
}
+ if ((card->info.type == QETH_CARD_TYPE_OSN) &&
+ (skb->protocol == htons(ETH_P_IPV6))) {
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
cast_type = qeth_get_cast_type(card, skb);
- if ((cast_type == RTN_BROADCAST) && (card->info.broadcast_capable == 0)){
+ if ((cast_type == RTN_BROADCAST) &&
+ (card->info.broadcast_capable == 0)){
card->stats.tx_dropped++;
card->stats.tx_errors++;
dev_kfree_skb_any(skb);
@@ -4320,7 +4425,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc);
return rc;
}
- qeth_fill_header(card, hdr, skb, ipv, cast_type);
+ if (card->info.type != QETH_CARD_TYPE_OSN)
+ qeth_fill_header(card, hdr, skb, ipv, cast_type);
}
if (large_send == QETH_LARGE_SEND_EDDP) {
@@ -4381,6 +4487,7 @@ qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
case MII_BMCR: /* Basic mode control register */
rc = BMCR_FULLDPLX;
if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH)&&
+ (card->info.link_type != QETH_LINK_TYPE_OSN) &&
(card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH))
rc |= BMCR_SPEED100;
break;
@@ -5004,6 +5111,9 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
(card->state != CARD_STATE_SOFTSETUP))
return -ENODEV;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return -EPERM;
+
switch (cmd){
case SIOC_QETH_ARP_SET_NO_ENTRIES:
if ( !capable(CAP_NET_ADMIN) ||
@@ -5329,6 +5439,9 @@ qeth_set_multicast_list(struct net_device *dev)
{
struct qeth_card *card = (struct qeth_card *) dev->priv;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return ;
+
QETH_DBF_TEXT(trace,3,"setmulti");
qeth_delete_mc_addresses(card);
qeth_add_multicast_ipv4(card);
@@ -5370,6 +5483,94 @@ qeth_get_addr_buffer(enum qeth_prot_versions prot)
return addr;
}
+int
+qeth_osn_assist(struct net_device *dev,
+ void *data,
+ int data_len)
+{
+ struct qeth_cmd_buffer *iob;
+ struct qeth_card *card;
+ int rc;
+
+ QETH_DBF_TEXT(trace, 2, "osnsdmc");
+ if (!dev)
+ return -ENODEV;
+ card = (struct qeth_card *)dev->priv;
+ if (!card)
+ return -ENODEV;
+ if ((card->state != CARD_STATE_UP) &&
+ (card->state != CARD_STATE_SOFTSETUP))
+ return -ENODEV;
+ iob = qeth_wait_for_buffer(&card->write);
+ memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len);
+ rc = qeth_osn_send_ipa_cmd(card, iob, data_len);
+ return rc;
+}
+
+static struct net_device *
+qeth_netdev_by_devno(unsigned char *read_dev_no)
+{
+ struct qeth_card *card;
+ struct net_device *ndev;
+ unsigned char *readno;
+ __u16 temp_dev_no, card_dev_no;
+ char *endp;
+ unsigned long flags;
+
+ ndev = NULL;
+ memcpy(&temp_dev_no, read_dev_no, 2);
+ read_lock_irqsave(&qeth_card_list.rwlock, flags);
+ list_for_each_entry(card, &qeth_card_list.list, list) {
+ readno = CARD_RDEV_ID(card);
+ readno += (strlen(readno) - 4);
+ card_dev_no = simple_strtoul(readno, &endp, 16);
+ if (card_dev_no == temp_dev_no) {
+ ndev = card->dev;
+ break;
+ }
+ }
+ read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+ return ndev;
+}
+
+int
+qeth_osn_register(unsigned char *read_dev_no,
+ struct net_device **dev,
+ int (*assist_cb)(struct net_device *, void *),
+ int (*data_cb)(struct sk_buff *))
+{
+ struct qeth_card * card;
+
+ QETH_DBF_TEXT(trace, 2, "osnreg");
+ *dev = qeth_netdev_by_devno(read_dev_no);
+ if (*dev == NULL)
+ return -ENODEV;
+ card = (struct qeth_card *)(*dev)->priv;
+ if (!card)
+ return -ENODEV;
+ if ((assist_cb == NULL) || (data_cb == NULL))
+ return -EINVAL;
+ card->osn_info.assist_cb = assist_cb;
+ card->osn_info.data_cb = data_cb;
+ return 0;
+}
+
+void
+qeth_osn_deregister(struct net_device * dev)
+{
+ struct qeth_card *card;
+
+ QETH_DBF_TEXT(trace, 2, "osndereg");
+ if (!dev)
+ return;
+ card = (struct qeth_card *)dev->priv;
+ if (!card)
+ return;
+ card->osn_info.assist_cb = NULL;
+ card->osn_info.data_cb = NULL;
+ return;
+}
+
static void
qeth_delete_mc_addresses(struct qeth_card *card)
{
@@ -5700,6 +5901,12 @@ qeth_layer2_set_mac_address(struct net_device *dev, void *p)
QETH_DBF_TEXT(trace, 3, "setmcLY3");
return -EOPNOTSUPP;
}
+ if (card->info.type == QETH_CARD_TYPE_OSN) {
+ PRINT_WARN("Setting MAC address on %s is not supported.\n",
+ dev->name);
+ QETH_DBF_TEXT(trace, 3, "setmcOSN");
+ return -EOPNOTSUPP;
+ }
QETH_DBF_TEXT_(trace, 3, "%s", CARD_BUS_ID(card));
QETH_DBF_HEX(trace, 3, addr->sa_data, OSA_ADDR_LEN);
rc = qeth_layer2_send_delmac(card, &card->dev->dev_addr[0]);
@@ -6076,9 +6283,8 @@ qeth_netdev_init(struct net_device *dev)
qeth_get_hlen(card->info.link_type) + card->options.add_hhlen;
dev->addr_len = OSA_ADDR_LEN;
dev->mtu = card->info.initial_mtu;
-
- SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
-
+ if (card->info.type != QETH_CARD_TYPE_OSN)
+ SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
SET_MODULE_OWNER(dev);
return 0;
}
@@ -6095,6 +6301,7 @@ qeth_init_func_level(struct qeth_card *card)
QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT;
} else {
if (card->info.type == QETH_CARD_TYPE_IQD)
+ /*FIXME:why do we have same values for dis and ena for osae??? */
card->info.func_level =
QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
else
@@ -6124,7 +6331,7 @@ retry:
ccw_device_set_online(CARD_WDEV(card));
ccw_device_set_online(CARD_DDEV(card));
}
- rc = qeth_qdio_clear_card(card,card->info.type==QETH_CARD_TYPE_OSAE);
+ rc = qeth_qdio_clear_card(card,card->info.type!=QETH_CARD_TYPE_IQD);
if (rc == -ERESTARTSYS) {
QETH_DBF_TEXT(setup, 2, "break1");
return rc;
@@ -6176,8 +6383,8 @@ retry:
card->dev = qeth_get_netdevice(card->info.type,
card->info.link_type);
if (!card->dev){
- qeth_qdio_clear_card(card, card->info.type ==
- QETH_CARD_TYPE_OSAE);
+ qeth_qdio_clear_card(card, card->info.type !=
+ QETH_CARD_TYPE_IQD);
rc = -ENODEV;
QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
goto out;
@@ -7084,6 +7291,8 @@ qeth_softsetup_card(struct qeth_card *card)
return rc;
} else
card->lan_online = 1;
+ if (card->info.type==QETH_CARD_TYPE_OSN)
+ goto out;
if (card->options.layer2) {
card->dev->features |=
NETIF_F_HW_VLAN_FILTER |
@@ -7255,7 +7464,8 @@ qeth_stop_card(struct qeth_card *card, int recovery_mode)
if (card->read.state == CH_STATE_UP &&
card->write.state == CH_STATE_UP &&
(card->state == CARD_STATE_UP)) {
- if(recovery_mode) {
+ if (recovery_mode &&
+ card->info.type != QETH_CARD_TYPE_OSN) {
qeth_stop(card->dev);
} else {
rtnl_lock();
@@ -7437,7 +7647,8 @@ qeth_start_again(struct qeth_card *card, int recovery_mode)
{
QETH_DBF_TEXT(setup ,2, "startag");
- if(recovery_mode) {
+ if (recovery_mode &&
+ card->info.type != QETH_CARD_TYPE_OSN) {
qeth_open(card->dev);
} else {
rtnl_lock();
@@ -7469,33 +7680,36 @@ qeth_start_again(struct qeth_card *card, int recovery_mode)
static void qeth_make_parameters_consistent(struct qeth_card *card)
{
- if (card->options.layer2) {
- if (card->info.type == QETH_CARD_TYPE_IQD) {
- PRINT_ERR("Device %s does not support " \
- "layer 2 functionality. " \
- "Ignoring layer2 option.\n",CARD_BUS_ID(card));
- }
- IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER,
- "Routing options are");
+ if (card->options.layer2 == 0)
+ return;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return;
+ if (card->info.type == QETH_CARD_TYPE_IQD) {
+ PRINT_ERR("Device %s does not support layer 2 functionality." \
+ " Ignoring layer2 option.\n",CARD_BUS_ID(card));
+ card->options.layer2 = 0;
+ return;
+ }
+ IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER,
+ "Routing options are");
#ifdef CONFIG_QETH_IPV6
- IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER,
- "Routing options are");
+ IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER,
+ "Routing options are");
#endif
- IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING,
- QETH_CHECKSUM_DEFAULT,
- "Checksumming options are");
- IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS,
- QETH_TR_BROADCAST_ALLRINGS,
- "Broadcast mode options are");
- IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL,
- QETH_TR_MACADDR_NONCANONICAL,
- "Canonical MAC addr options are");
- IGNORE_PARAM_NEQ(fake_broadcast, 0, 0,
- "Broadcast faking options are");
- IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN,
- DEFAULT_ADD_HHLEN,"Option add_hhlen is");
- IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is");
- }
+ IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING,
+ QETH_CHECKSUM_DEFAULT,
+ "Checksumming options are");
+ IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS,
+ QETH_TR_BROADCAST_ALLRINGS,
+ "Broadcast mode options are");
+ IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL,
+ QETH_TR_MACADDR_NONCANONICAL,
+ "Canonical MAC addr options are");
+ IGNORE_PARAM_NEQ(fake_broadcast, 0, 0,
+ "Broadcast faking options are");
+ IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN,
+ DEFAULT_ADD_HHLEN,"Option add_hhlen is");
+ IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is");
}
@@ -7525,8 +7739,7 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
return -EIO;
}
- if (card->options.layer2)
- qeth_make_parameters_consistent(card);
+ qeth_make_parameters_consistent(card);
if ((rc = qeth_hardsetup_card(card))){
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
@@ -7585,6 +7798,7 @@ qeth_set_online(struct ccwgroup_device *gdev)
static struct ccw_device_id qeth_ids[] = {
{CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE},
{CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD},
+ {CCW_DEVICE(0x1731, 0x06), driver_info:QETH_CARD_TYPE_OSN},
{},
};
MODULE_DEVICE_TABLE(ccw, qeth_ids);
@@ -8329,6 +8543,9 @@ again:
printk("qeth: removed\n");
}
+EXPORT_SYMBOL(qeth_osn_register);
+EXPORT_SYMBOL(qeth_osn_deregister);
+EXPORT_SYMBOL(qeth_osn_assist);
module_init(qeth_init);
module_exit(qeth_exit);
MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>");
diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
index f685ecc7da99..30e053d3cac2 100644
--- a/drivers/s390/net/qeth_mpc.c
+++ b/drivers/s390/net/qeth_mpc.c
@@ -11,7 +11,7 @@
#include <asm/cio.h>
#include "qeth_mpc.h"
-const char *VERSION_QETH_MPC_C = "$Revision: 1.11 $";
+const char *VERSION_QETH_MPC_C = "$Revision: 1.12 $";
unsigned char IDX_ACTIVATE_READ[]={
0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
@@ -138,7 +138,9 @@ unsigned char IPA_PDU_HEADER[]={
sizeof(struct qeth_ipa_cmd)%256,
0x00,
sizeof(struct qeth_ipa_cmd)/256,
- sizeof(struct qeth_ipa_cmd),0x05, 0x77,0x77,0x77,0x77,
+ sizeof(struct qeth_ipa_cmd)%256,
+ 0x05,
+ 0x77,0x77,0x77,0x77,
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
0x01,0x00,
sizeof(struct qeth_ipa_cmd)/256,
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
index 3d916b5c5d09..7edc5f1fc0d2 100644
--- a/drivers/s390/net/qeth_mpc.h
+++ b/drivers/s390/net/qeth_mpc.h
@@ -46,13 +46,16 @@ extern unsigned char IPA_PDU_HEADER[];
/* IP Assist related definitions */
/*****************************************************************************/
#define IPA_CMD_INITIATOR_HOST 0x00
-#define IPA_CMD_INITIATOR_HYDRA 0x01
+#define IPA_CMD_INITIATOR_OSA 0x01
+#define IPA_CMD_INITIATOR_HOST_REPLY 0x80
+#define IPA_CMD_INITIATOR_OSA_REPLY 0x81
#define IPA_CMD_PRIM_VERSION_NO 0x01
enum qeth_card_types {
QETH_CARD_TYPE_UNKNOWN = 0,
QETH_CARD_TYPE_OSAE = 10,
QETH_CARD_TYPE_IQD = 1234,
+ QETH_CARD_TYPE_OSN = 11,
};
#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
@@ -61,6 +64,7 @@ enum qeth_link_types {
QETH_LINK_TYPE_FAST_ETH = 0x01,
QETH_LINK_TYPE_HSTR = 0x02,
QETH_LINK_TYPE_GBIT_ETH = 0x03,
+ QETH_LINK_TYPE_OSN = 0x04,
QETH_LINK_TYPE_10GBIT_ETH = 0x10,
QETH_LINK_TYPE_LANE_ETH100 = 0x81,
QETH_LINK_TYPE_LANE_TR = 0x82,
@@ -111,6 +115,9 @@ enum qeth_ipa_cmds {
IPA_CMD_DELGMAC = 0x24,
IPA_CMD_SETVLAN = 0x25,
IPA_CMD_DELVLAN = 0x26,
+ IPA_CMD_SETCCID = 0x41,
+ IPA_CMD_DELCCID = 0x42,
+ IPA_CMD_MODCCID = 0x43,
IPA_CMD_SETIP = 0xb1,
IPA_CMD_DELIP = 0xb7,
IPA_CMD_QIPASSIST = 0xb2,
@@ -437,8 +444,9 @@ enum qeth_ipa_arp_return_codes {
#define QETH_ARP_DATA_SIZE 3968
#define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8)
/* Helper functions */
-#define IS_IPA_REPLY(cmd) (cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST)
-
+#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
+ (cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
+
/*****************************************************************************/
/* END OF IP Assist related definitions */
/*****************************************************************************/
@@ -483,6 +491,7 @@ extern unsigned char ULP_ENABLE[];
/* Layer 2 defintions */
#define QETH_PROT_LAYER2 0x08
#define QETH_PROT_TCPIP 0x03
+#define QETH_PROT_OSN2 0x0a
#define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer+0x50)
#define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer+0x19)
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index dda105b73063..f91a02db5743 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.54 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.55 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs.
@@ -20,7 +20,7 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
-const char *VERSION_QETH_SYS_C = "$Revision: 1.54 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.55 $";
/*****************************************************************************/
/* */
@@ -937,6 +937,19 @@ static struct attribute_group qeth_device_attr_group = {
.attrs = (struct attribute **)qeth_device_attrs,
};
+static struct device_attribute * qeth_osn_device_attrs[] = {
+ &dev_attr_state,
+ &dev_attr_chpid,
+ &dev_attr_if_name,
+ &dev_attr_card_type,
+ &dev_attr_buffer_count,
+ &dev_attr_recover,
+ NULL,
+};
+
+static struct attribute_group qeth_osn_device_attr_group = {
+ .attrs = (struct attribute **)qeth_osn_device_attrs,
+};
#define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \
struct device_attribute dev_attr_##_id = { \
@@ -1667,7 +1680,12 @@ int
qeth_create_device_attributes(struct device *dev)
{
int ret;
+ struct qeth_card *card = dev->driver_data;
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return sysfs_create_group(&dev->kobj,
+ &qeth_osn_device_attr_group);
+
if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group)))
return ret;
if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){
@@ -1693,6 +1711,12 @@ qeth_create_device_attributes(struct device *dev)
void
qeth_remove_device_attributes(struct device *dev)
{
+ struct qeth_card *card = dev->driver_data;
+
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ return sysfs_remove_group(&dev->kobj,
+ &qeth_osn_device_attr_group);
+
sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);