Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / s390 / net / qeth_main.c
index 208127a..9e671a4 100644 (file)
@@ -1,6 +1,5 @@
 /*
- *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $)
+ * linux/drivers/s390/net/qeth_main.c
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -9,11 +8,9 @@
  *    Author(s): Original Code written by
  *                       Utz Bacher (utz.bacher@de.ibm.com)
  *              Rewritten by
- *                       Frank Pavlic (pavlic@de.ibm.com) and
+ *                       Frank Pavlic (fpavlic@de.ibm.com) and
  *                       Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.214 $        $Date: 2005/05/04 20:19:18 $
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/***
- * eye catcher; just for debugging purposes
- */
-void volatile
-qeth_eyecatcher(void)
-{
-       return;
-}
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -73,6 +62,7 @@ qeth_eyecatcher(void)
 #include <asm/timex.h>
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
+#include <asm/s390_rdev.h>
 
 #include "qeth.h"
 #include "qeth_mpc.h"
@@ -80,7 +70,6 @@ qeth_eyecatcher(void)
 #include "qeth_eddp.h"
 #include "qeth_tso.h"
 
-#define VERSION_QETH_C "$Revision: 1.214 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -167,6 +156,9 @@ qeth_get_addr_buffer(enum qeth_prot_versions);
 static void
 qeth_set_multicast_list(struct net_device *);
 
+static void
+qeth_setadp_promisc_mode(struct qeth_card *);
+
 static void
 qeth_notify_processes(void)
 {
@@ -204,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) {
@@ -306,12 +297,10 @@ qeth_alloc_card(void)
        struct qeth_card *card;
 
        QETH_DBF_TEXT(setup, 2, "alloccrd");
-       card = (struct qeth_card *) kmalloc(sizeof(struct qeth_card),
-                                           GFP_DMA|GFP_KERNEL);
+       card = kzalloc(sizeof(struct qeth_card), GFP_DMA|GFP_KERNEL);
        if (!card)
                return NULL;
        QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
-       memset(card, 0, sizeof(struct qeth_card));
        if (qeth_setup_channel(&card->read)) {
                kfree(card);
                return NULL;
@@ -519,23 +508,27 @@ static int
 __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
 {
        struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
-       int rc = 0;
+       int rc = 0, rc2 = 0, rc3 = 0;
        enum qeth_card_states recover_flag;
 
        QETH_DBF_TEXT(setup, 3, "setoffl");
        QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
 
+       if (card->dev && netif_carrier_ok(card->dev))
+               netif_carrier_off(card->dev);
        recover_flag = card->state;
        if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){
                PRINT_WARN("Stopping card %s interrupted by user!\n",
                           CARD_BUS_ID(card));
                return -ERESTARTSYS;
        }
-       if ((rc = ccw_device_set_offline(CARD_DDEV(card))) ||
-           (rc = ccw_device_set_offline(CARD_WDEV(card))) ||
-           (rc = ccw_device_set_offline(CARD_RDEV(card)))) {
+       rc  = ccw_device_set_offline(CARD_DDEV(card));
+       rc2 = ccw_device_set_offline(CARD_WDEV(card));
+       rc3 = ccw_device_set_offline(CARD_RDEV(card));
+       if (!rc)
+               rc = (rc2) ? rc2 : rc3;
+       if (rc)
                QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
-       }
        if (recover_flag == CARD_STATE_UP)
                card->state = CARD_STATE_RECOVER;
        qeth_notify_processes();
@@ -609,11 +602,20 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
        int found = 0;
 
        list_for_each_entry(addr, &card->ip_list, entry) {
+               if (card->options.layer2) {
+                       if ((addr->type == todo->type) &&
+                           (memcmp(&addr->mac, &todo->mac,
+                                   OSA_ADDR_LEN) == 0)) {
+                               found = 1;
+                               break;
+                       }
+                       continue;
+               }
                if ((addr->proto     == QETH_PROT_IPV4)  &&
                    (todo->proto     == QETH_PROT_IPV4)  &&
                    (addr->type      == todo->type)      &&
                    (addr->u.a4.addr == todo->u.a4.addr) &&
-                   (addr->u.a4.mask == todo->u.a4.mask)   ){
+                   (addr->u.a4.mask == todo->u.a4.mask){
                        found = 1;
                        break;
                }
@@ -622,12 +624,12 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
                    (addr->type        == todo->type)         &&
                    (addr->u.a6.pfxlen == todo->u.a6.pfxlen)  &&
                    (memcmp(&addr->u.a6.addr, &todo->u.a6.addr,
-                           sizeof(struct in6_addr)) == 0))     {
+                           sizeof(struct in6_addr)) == 0)) {
                        found = 1;
                        break;
                }
        }
-       if (found){
+       if (found) {
                addr->users += todo->users;
                if (addr->users <= 0){
                        *__addr = addr;
@@ -639,7 +641,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
                        return 0;
                }
        }
-       if (todo->users > 0){
+       if (todo->users > 0) {
                /* for VIPA and RXIP limit refcount to 1 */
                if (todo->type != QETH_IP_TYPE_NORMAL)
                        todo->users = 1;
@@ -689,12 +691,22 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
                if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
                    (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
                        return 0;
+               if (card->options.layer2) {
+                       if ((tmp->type  == addr->type)  &&
+                           (tmp->is_multicast == addr->is_multicast) &&
+                           (memcmp(&tmp->mac, &addr->mac,
+                                   OSA_ADDR_LEN) == 0)) {
+                               found = 1;
+                               break;
+                       }
+                       continue;
+               }
                if ((tmp->proto        == QETH_PROT_IPV4)     &&
                    (addr->proto       == QETH_PROT_IPV4)     &&
                    (tmp->type         == addr->type)         &&
                    (tmp->is_multicast == addr->is_multicast) &&
                    (tmp->u.a4.addr    == addr->u.a4.addr)    &&
-                   (tmp->u.a4.mask    == addr->u.a4.mask)      ){
+                   (tmp->u.a4.mask    == addr->u.a4.mask){
                        found = 1;
                        break;
                }
@@ -704,7 +716,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
                    (tmp->is_multicast == addr->is_multicast)  &&
                    (tmp->u.a6.pfxlen  == addr->u.a6.pfxlen)   &&
                    (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
-                           sizeof(struct in6_addr)) == 0)        ){
+                           sizeof(struct in6_addr)) == 0){
                        found = 1;
                        break;
                }
@@ -714,7 +726,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
                        tmp->users += addr->users;
                else
                        tmp->users += add? 1:-1;
-               if (tmp->users == 0){
+               if (tmp->users == 0) {
                        list_del(&tmp->entry);
                        kfree(tmp);
                }
@@ -745,12 +757,15 @@ qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
        unsigned long flags;
        int rc = 0;
 
-       QETH_DBF_TEXT(trace,4,"delip");
-       if (addr->proto == QETH_PROT_IPV4)
-               QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4);
+       QETH_DBF_TEXT(trace, 4, "delip");
+
+       if (card->options.layer2)
+               QETH_DBF_HEX(trace, 4, &addr->mac, 6);
+       else if (addr->proto == QETH_PROT_IPV4)
+               QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
        else {
-               QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8);
-               QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8);
+               QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+               QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
        }
        spin_lock_irqsave(&card->ip_lock, flags);
        rc = __qeth_insert_ip_todo(card, addr, 0);
@@ -764,12 +779,14 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
        unsigned long flags;
        int rc = 0;
 
-       QETH_DBF_TEXT(trace,4,"addip");
-       if (addr->proto == QETH_PROT_IPV4)
-               QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4);
+       QETH_DBF_TEXT(trace, 4, "addip");
+       if (card->options.layer2)
+               QETH_DBF_HEX(trace, 4, &addr->mac, 6);
+       else if (addr->proto == QETH_PROT_IPV4)
+               QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
        else {
-               QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8);
-               QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8);
+               QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+               QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
        }
        spin_lock_irqsave(&card->ip_lock, flags);
        rc = __qeth_insert_ip_todo(card, addr, 1);
@@ -782,7 +799,7 @@ __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags)
 {
        struct qeth_ipaddr *addr, *tmp;
        int rc;
-
+again:
        list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {
                if (addr->is_multicast) {
                        spin_unlock_irqrestore(&card->ip_lock, *flags);
@@ -791,6 +808,7 @@ __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags)
                        if (!rc) {
                                list_del(&addr->entry);
                                kfree(addr);
+                               goto again;
                        }
                }
        }
@@ -858,6 +876,7 @@ qeth_set_ip_addr_list(struct qeth_card *card)
 
 static void qeth_delete_mc_addresses(struct qeth_card *);
 static void qeth_add_multicast_ipv4(struct qeth_card *);
+static void qeth_layer2_add_multicast(struct qeth_card *);
 #ifdef CONFIG_QETH_IPV6
 static void qeth_add_multicast_ipv6(struct qeth_card *);
 #endif
@@ -946,6 +965,24 @@ qeth_register_ip_addresses(void *ptr)
        return 0;
 }
 
+/*
+ * Drive the SET_PROMISC_MODE thread
+ */
+static int
+qeth_set_promisc_mode(void *ptr)
+{
+       struct qeth_card *card = (struct qeth_card *) ptr;
+
+       daemonize("qeth_setprm");
+       QETH_DBF_TEXT(trace,4,"setprm1");
+       if (!qeth_do_run_thread(card, QETH_SET_PROMISC_MODE_THREAD))
+               return 0;
+       QETH_DBF_TEXT(trace,4,"setprm2");
+       qeth_setadp_promisc_mode(card);
+       qeth_clear_thread_running_bit(card, QETH_SET_PROMISC_MODE_THREAD);
+       return 0;
+}
+
 static int
 qeth_recover(void *ptr)
 {
@@ -980,7 +1017,6 @@ void
 qeth_schedule_recovery(struct qeth_card *card)
 {
        QETH_DBF_TEXT(trace,2,"startrec");
-
        if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0)
                schedule_work(&card->kernel_thread_starter);
 }
@@ -1012,6 +1048,8 @@ qeth_start_kernel_thread(struct qeth_card *card)
 
        if (qeth_do_start_thread(card, QETH_SET_IP_THREAD))
                kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD);
+       if (qeth_do_start_thread(card, QETH_SET_PROMISC_MODE_THREAD))
+               kernel_thread(qeth_set_promisc_mode, (void *)card, SIGCHLD);
        if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
                kernel_thread(qeth_recover, (void *) card, SIGCHLD);
 }
@@ -1030,7 +1068,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;
 }
 
 /**
@@ -1054,6 +1095,7 @@ qeth_setup_card(struct qeth_card *card)
        spin_lock_init(&card->vlanlock);
        card->vlangrp = NULL;
 #endif
+       spin_lock_init(&card->lock);
        spin_lock_init(&card->ip_lock);
        spin_lock_init(&card->thread_mask_lock);
        card->thread_start_mask = 0;
@@ -1118,19 +1160,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++;
@@ -1154,6 +1197,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);
@@ -1163,28 +1208,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_determine_card_type(card))){
-               PRINT_WARN("%s: not a valid card type\n", __func__);
-               QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+       if ((rc = qeth_setup_card(card))){
+               QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+               put_device(dev);
+               qeth_free_card(card);
+               return rc;
+       }
+       rc = qeth_create_device_attributes(dev);
+       if (rc) {
                put_device(dev);
                qeth_free_card(card);
                return rc;
@@ -1318,7 +1362,7 @@ qeth_wait_for_buffer(struct qeth_channel *channel)
 static void
 qeth_clear_cmd_buffers(struct qeth_channel *channel)
 {
-       int cnt = 0;
+       int cnt;
 
        for (cnt=0; cnt < QETH_CMD_BUFFER_NO; cnt++)
                qeth_release_buffer(channel,&channel->iob[cnt]);
@@ -1348,7 +1392,7 @@ qeth_idx_activate_get_answer(struct qeth_channel *channel,
        channel->ccw.cda = (__u32) __pa(iob->data);
 
        wait_event(card->wait_q,
-                  atomic_compare_and_swap(0,1,&channel->irq_pending) == 0);
+                  atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
        QETH_DBF_TEXT(setup, 6, "noirqpnd");
        spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
        rc = ccw_device_start(channel->ccwdev,
@@ -1415,7 +1459,7 @@ qeth_idx_activate_channel(struct qeth_channel *channel,
        memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2);
 
        wait_event(card->wait_q,
-                  atomic_compare_and_swap(0,1,&channel->irq_pending) == 0);
+                  atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
        QETH_DBF_TEXT(setup, 6, "noirqpnd");
        spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
        rc = ccw_device_start(channel->ccwdev,
@@ -1568,7 +1612,7 @@ qeth_issue_next_read(struct qeth_card *card)
        }
        qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
        wait_event(card->wait_q,
-                  atomic_compare_and_swap(0,1,&card->read.irq_pending) == 0);
+                  atomic_cmpxchg(&card->read.irq_pending, 0, 1) == 0);
        QETH_DBF_TEXT(trace, 6, "noirqpnd");
        rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
                              (addr_t) iob, 0, 0);
@@ -1586,9 +1630,8 @@ qeth_alloc_reply(struct qeth_card *card)
 {
        struct qeth_reply *reply;
 
-       reply = kmalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
+       reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
        if (reply){
-               memset(reply, 0, sizeof(struct qeth_reply));
                atomic_set(&reply->refcnt, 1);
                reply->card = card;
        };
@@ -1634,15 +1677,6 @@ qeth_cmd_timeout(unsigned long data)
        spin_unlock_irqrestore(&reply->card->lock, flags);
 }
 
-static void
-qeth_reset_ip_addresses(struct qeth_card *card)
-{
-       QETH_DBF_TEXT(trace, 2, "rstipadd");
-
-       qeth_clear_ip_list(card, 0, 1);
-       /* this function will also schedule the SET_IP_THREAD */
-       qeth_set_multicast_list(card->dev);
-}
 
 static struct qeth_ipa_cmd *
 qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
@@ -1664,7 +1698,8 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
                                           QETH_CARD_IFNAME(card),
                                           card->info.chpid);
                                card->lan_online = 0;
-                               netif_carrier_off(card->dev);
+                               if (card->dev && netif_carrier_ok(card->dev))
+                                       netif_carrier_off(card->dev);
                                return NULL;
                        case IPA_CMD_STARTLAN:
                                PRINT_INFO("Link reestablished on %s "
@@ -1672,10 +1707,10 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
                                           "IP address reset.\n",
                                           QETH_CARD_IFNAME(card),
                                           card->info.chpid);
-                               card->lan_online = 1;
-                               netif_carrier_on(card->dev);
-                               qeth_reset_ip_addresses(card);
+                               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;
@@ -1737,6 +1772,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) {
@@ -1753,8 +1796,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);
@@ -1784,6 +1826,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,
@@ -1794,24 +1854,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");
@@ -1826,17 +1873,18 @@ 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);
        spin_unlock_irqrestore(&card->lock, flags);
        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);
+                  atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 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,
@@ -1863,6 +1911,62 @@ qeth_send_control_data(struct qeth_card *card, int len,
        return rc;
 }
 
+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_cmpxchg(&card->write.irq_pending, 0, 1) == 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)
@@ -1874,17 +1978,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;
@@ -2026,7 +2127,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;
 
@@ -2095,36 +2199,39 @@ qeth_ulp_setup(struct qeth_card *card)
 }
 
 static inline int
-qeth_check_for_inbound_error(struct qeth_qdio_buffer *buf,
-                            unsigned int qdio_error,
-                            unsigned int siga_error)
+qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error,
+                      unsigned int siga_error, const char *dbftext)
 {
-       int rc = 0;
-
        if (qdio_error || siga_error) {
-               QETH_DBF_TEXT(trace, 2, "qdinerr");
-               QETH_DBF_TEXT(qerr, 2, "qdinerr");
+               QETH_DBF_TEXT(trace, 2, dbftext);
+               QETH_DBF_TEXT(qerr, 2, dbftext);
                QETH_DBF_TEXT_(qerr, 2, " F15=%02X",
-                              buf->buffer->element[15].flags & 0xff);
+                              buf->element[15].flags & 0xff);
                QETH_DBF_TEXT_(qerr, 2, " F14=%02X",
-                              buf->buffer->element[14].flags & 0xff);
+                              buf->element[14].flags & 0xff);
                QETH_DBF_TEXT_(qerr, 2, " qerr=%X", qdio_error);
                QETH_DBF_TEXT_(qerr, 2, " serr=%X", siga_error);
-               rc = 1;
+               return 1;
        }
-       return rc;
+       return 0;
 }
 
 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;
 }
 
@@ -2154,7 +2261,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;
 
@@ -2162,15 +2272,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) {
@@ -2210,7 +2320,7 @@ no_mem:
        return NULL;
 }
 
-static inline unsigned short
+static inline __be16
 qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
        struct qeth_card *card;
@@ -2395,6 +2505,7 @@ qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
                skb_pull(skb, VLAN_HLEN);
        }
 #endif
+       *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
        return vlan_id;
 }
 
@@ -2468,8 +2579,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);
@@ -2480,7 +2595,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;
@@ -2644,8 +2762,9 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status,
        for (i = first_element; i < (first_element + count); ++i) {
                index = i % QDIO_MAX_BUFFERS_PER_Q;
                buffer = &card->qdio.in_q->bufs[index];
-               if (!((status == QDIO_STATUS_LOOK_FOR_ERROR) &&
-                     qeth_check_for_inbound_error(buffer, qdio_err, siga_err)))
+               if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
+                     qeth_check_qdio_errors(buffer->buffer,
+                                            qdio_err, siga_err,"qinerr")))
                        qeth_process_inbound_buffer(card, buffer, index);
                /* clear buffer and give back to hardware */
                qeth_put_buffer_pool_entry(card, buffer->pool_entry);
@@ -2660,12 +2779,13 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status,
 static inline int
 qeth_handle_send_error(struct qeth_card *card,
                       struct qeth_qdio_out_buffer *buffer,
-                      int qdio_err, int siga_err)
+                      unsigned int qdio_err, unsigned int siga_err)
 {
        int sbalf15 = buffer->buffer->element[15].flags & 0xff;
        int cc = siga_err & 3;
 
        QETH_DBF_TEXT(trace, 6, "hdsnderr");
+       qeth_check_qdio_errors(buffer->buffer, qdio_err, siga_err, "qouterr");
        switch (cc) {
        case 0:
                if (qdio_err){
@@ -2691,11 +2811,11 @@ qeth_handle_send_error(struct qeth_card *card,
                QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
                return QETH_SEND_ERROR_LINK_FAILURE;
        case 3:
+       default:
                QETH_DBF_TEXT(trace, 1, "SIGAcc3");
                QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
                return QETH_SEND_ERROR_KICK_IT;
        }
-       return QETH_SEND_ERROR_LINK_FAILURE;
 }
 
 void
@@ -2759,11 +2879,9 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
                queue->card->perf_stats.outbound_do_qdio_start_time;
 #endif
        if (rc){
-               QETH_DBF_SPRINTF(trace, 0, "qeth_flush_buffers: do_QDIO "
-                                "returned error (%i) on device %s.",
-                                rc, CARD_DDEV_ID(queue->card));
                QETH_DBF_TEXT(trace, 2, "flushbuf");
                QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+               QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card));
                queue->card->stats.tx_errors += count;
                /* this must not happen under normal circumstances. if it
                 * happens something is really wrong -> recover */
@@ -2909,11 +3027,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
        QETH_DBF_TEXT(trace, 6, "qdouhdl");
        if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
                if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
-                       QETH_DBF_SPRINTF(trace, 2, "On device %s: "
-                                        "received active check "
-                                        "condition (0x%08x).",
-                                        CARD_BUS_ID(card), status);
-                       QETH_DBF_TEXT(trace, 2, "chkcond");
+                       QETH_DBF_TEXT(trace, 2, "achkcond");
+                       QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card));
                        QETH_DBF_TEXT_(trace, 2, "%08x", status);
                        netif_stop_queue(card->dev);
                        qeth_schedule_recovery(card);
@@ -2927,7 +3042,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
        for(i = first_element; i < (first_element + count); ++i){
                buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
                /*we only handle the KICK_IT error by doing a recovery */
-               if (qeth_handle_send_error(card, buffer, qdio_error, siga_error)
+               if (qeth_handle_send_error(card, buffer,
+                                          qdio_error, siga_error)
                                == QETH_SEND_ERROR_KICK_IT){
                        netif_stop_queue(card->dev);
                        qeth_schedule_recovery(card);
@@ -3027,7 +3143,7 @@ qeth_alloc_buffer_pool(struct qeth_card *card)
                        return -ENOMEM;
                }
                for(j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j){
-                       ptr = (void *) __get_free_page(GFP_KERNEL);
+                       ptr = (void *) __get_free_page(GFP_KERNEL|GFP_DMA);
                        if (!ptr) {
                                while (j > 0)
                                        free_page((unsigned long)
@@ -3071,7 +3187,8 @@ qeth_alloc_qdio_buffers(struct qeth_card *card)
        if (card->qdio.state == QETH_QDIO_ALLOCATED)
                return 0;
 
-       card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), GFP_KERNEL);
+       card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
+                                 GFP_KERNEL|GFP_DMA);
        if (!card->qdio.in_q)
                return - ENOMEM;
        QETH_DBF_TEXT(setup, 2, "inq");
@@ -3096,7 +3213,7 @@ qeth_alloc_qdio_buffers(struct qeth_card *card)
        }
        for (i = 0; i < card->qdio.no_out_queues; ++i){
                card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q),
-                                              GFP_KERNEL);
+                                              GFP_KERNEL|GFP_DMA);
                if (!card->qdio.out_qs[i]){
                        while (i > 0)
                                kfree(card->qdio.out_qs[--i]);
@@ -3168,9 +3285,6 @@ qeth_init_qdio_info(struct qeth_card *card)
        card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count;
        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
@@ -3231,13 +3345,11 @@ qeth_qdio_establish(struct qeth_card *card)
 
        QETH_DBF_TEXT(setup, 2, "qdioest");
 
-       qib_param_field = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
+       qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
                              GFP_KERNEL);
        if (!qib_param_field)
                return -ENOMEM;
 
-       memset(qib_param_field, 0, QDIO_MAX_BUFFERS_PER_Q * sizeof(char));
-
        qeth_create_qib_param_field(card, qib_param_field);
        qeth_create_qib_param_field_blkt(card, qib_param_field);
 
@@ -3356,26 +3468,32 @@ qeth_halt_channel(struct qeth_channel *channel)
 static int
 qeth_halt_channels(struct qeth_card *card)
 {
-       int rc = 0;
+       int rc1 = 0, rc2=0, rc3 = 0;
 
        QETH_DBF_TEXT(trace,3,"haltchs");
-       if ((rc = qeth_halt_channel(&card->read)))
-               return rc;
-       if ((rc = qeth_halt_channel(&card->write)))
-               return rc;
-       return  qeth_halt_channel(&card->data);
+       rc1 = qeth_halt_channel(&card->read);
+       rc2 = qeth_halt_channel(&card->write);
+       rc3 = qeth_halt_channel(&card->data);
+       if (rc1)
+               return rc1;
+       if (rc2)
+               return rc2;
+       return rc3;
 }
 static int
 qeth_clear_channels(struct qeth_card *card)
 {
-       int rc = 0;
+       int rc1 = 0, rc2=0, rc3 = 0;
 
        QETH_DBF_TEXT(trace,3,"clearchs");
-       if ((rc = qeth_clear_channel(&card->read)))
-               return rc;
-       if ((rc = qeth_clear_channel(&card->write)))
-               return rc;
-       return  qeth_clear_channel(&card->data);
+       rc1 = qeth_clear_channel(&card->read);
+       rc2 = qeth_clear_channel(&card->write);
+       rc3 = qeth_clear_channel(&card->data);
+       if (rc1)
+               return rc1;
+       if (rc2)
+               return rc2;
+       return rc3;
 }
 
 static int
@@ -3445,23 +3563,23 @@ qeth_mpc_initialize(struct qeth_card *card)
        }
        if ((rc = qeth_cm_enable(card))){
                QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
-               return rc;
+               goto out_qdio;
        }
        if ((rc = qeth_cm_setup(card))){
                QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
-               return rc;
+               goto out_qdio;
        }
        if ((rc = qeth_ulp_enable(card))){
                QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
-               return rc;
+               goto out_qdio;
        }
        if ((rc = qeth_ulp_setup(card))){
                QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
-               return rc;
+               goto out_qdio;
        }
        if ((rc = qeth_alloc_qdio_buffers(card))){
                QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
-               return rc;
+               goto out_qdio;
        }
        if ((rc = qeth_qdio_establish(card))){
                QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
@@ -3479,7 +3597,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;
 }
 
@@ -3504,6 +3622,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);
        }
@@ -3603,6 +3724,9 @@ qeth_verify_vlan_dev(struct net_device *dev, struct qeth_card *card)
                        break;
                }
        }
+       if (rc && !(VLAN_DEV_INFO(dev)->real_dev->priv == (void *)card))
+               return 0;
+
 #endif
        return rc;
 }
@@ -3668,20 +3792,19 @@ qeth_open(struct net_device *dev)
        if (card->state != CARD_STATE_SOFTSETUP)
                return -ENODEV;
 
-       if ( (card->options.layer2) &&
-            (!card->info.layer2_mac_registered)) {
+       if ( (card->info.type != QETH_CARD_TYPE_OSN) &&
+            (card->options.layer2) &&
+            (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
                QETH_DBF_TEXT(trace,4,"nomacadr");
                return -EPERM;
        }
-       card->dev->flags |= IFF_UP;
-       netif_start_queue(dev);
        card->data.state = CH_STATE_UP;
        card->state = CARD_STATE_UP;
+       card->dev->flags |= IFF_UP;
+       netif_start_queue(dev);
 
-       if (!card->lan_online){
-               if (netif_carrier_ok(dev))
-                       netif_carrier_off(dev);
-       }
+       if (!card->lan_online && netif_carrier_ok(dev))
+               netif_carrier_off(dev);
        return 0;
 }
 
@@ -3694,7 +3817,7 @@ qeth_stop(struct net_device *dev)
 
        card = (struct qeth_card *) dev->priv;
 
-       netif_stop_queue(dev);
+       netif_tx_disable(dev);
        card->dev->flags &= ~IFF_UP;
        if (card->state == CARD_STATE_UP)
                card->state = CARD_STATE_SOFTSETUP;
@@ -3706,6 +3829,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) ||
@@ -3734,6 +3860,7 @@ qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
                        if ((hdr_mac == QETH_TR_MAC_NC) ||
                            (hdr_mac == QETH_TR_MAC_C))
                                return RTN_MULTICAST;
+                       break;
                /* eth or so multicast? */
                 default:
                        if ((hdr_mac == QETH_ETH_MAC_V4) ||
@@ -3795,12 +3922,19 @@ static inline int
 qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
                 struct qeth_hdr **hdr, int ipv)
 {
+       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;
 #ifdef CONFIG_QETH_VLAN
        if (card->vlangrp && vlan_tx_tag_present(*skb) &&
            ((ipv == 6) || card->options.layer2) ) {
@@ -3824,7 +3958,7 @@ qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
 #endif
        *hdr = (struct qeth_hdr *)
                qeth_push_skb(card, skb, sizeof(struct qeth_hdr));
-       if (hdr == NULL)
+       if (*hdr == NULL)
                return -EINVAL;
        return 0;
 }
@@ -3964,7 +4098,7 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
                }
        } else { /* passthrough */
                 if((skb->dev->type == ARPHRD_IEEE802_TR) &&
-                   !memcmp(skb->data + sizeof(struct qeth_hdr) + 
+                   !memcmp(skb->data + sizeof(struct qeth_hdr) +
                    sizeof(__u16), skb->dev->broadcast, 6)) {
                        hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
                                                QETH_HDR_PASSTHRU;
@@ -4098,9 +4232,8 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue,
        QETH_DBF_TEXT(trace, 6, "dosndpfa");
 
        /* spin until we get the queue ... */
-       while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED,
-                                      QETH_OUT_Q_LOCKED,
-                                      &queue->state));
+       while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+                             QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
        /* ... now we've got the queue */
        index = queue->next_buf_to_fill;
        buffer = &queue->bufs[queue->next_buf_to_fill];
@@ -4154,9 +4287,8 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
        QETH_DBF_TEXT(trace, 6, "dosndpkt");
 
        /* spin until we get the queue ... */
-       while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED,
-                                      QETH_OUT_Q_LOCKED,
-                                      &queue->state));
+       while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+                             QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
        start_index = queue->next_buf_to_fill;
        buffer = &queue->bufs[queue->next_buf_to_fill];
        /*
@@ -4221,6 +4353,8 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
 out:
        if (flush_count)
                qeth_flush_buffers(queue, 0, start_index, flush_count);
+       else if (!atomic_read(&queue->set_pci_flags_count))
+               atomic_swap(&queue->state, QETH_OUT_Q_LOCKED_FLUSH);
        /*
         * queue->state will go from LOCKED -> UNLOCKED or from
         * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us
@@ -4251,7 +4385,8 @@ out:
 }
 
 static inline int
-qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
+qeth_get_elements_no(struct qeth_card *card, void *hdr,
+                    struct sk_buff *skb, int elems)
 {
        int elements_needed = 0;
 
@@ -4261,9 +4396,10 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
         if (elements_needed == 0 )
                 elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
                                         + skb->len) >> PAGE_SHIFT);
-        if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
+       if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){
                 PRINT_ERR("qeth_do_send_packet: invalid size of "
-                          "IP packet. Discarded.");
+                          "IP packet (Number=%d / Length=%d). Discarded.\n",
+                          (elements_needed+elems), skb->len);
                 return 0;
         }
         return elements_needed;
@@ -4275,10 +4411,13 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
        int ipv = 0;
        int cast_type;
        struct qeth_qdio_out_q *queue;
-       struct qeth_hdr *hdr;
+       struct qeth_hdr *hdr = NULL;
        int elements_needed = 0;
        enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
        struct qeth_eddp_context *ctx = NULL;
+       int tx_bytes = skb->len;
+       unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
+       unsigned short tso_size = skb_shinfo(skb)->tso_size;
        int rc;
 
        QETH_DBF_TEXT(trace, 6, "sendpkt");
@@ -4298,8 +4437,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,14 +4465,15 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
                        card->stats.tx_errors++;
                        dev_kfree_skb_any(skb);
                        return NETDEV_TX_OK;
-               } 
+               }
                elements_needed++;
        } else {
                if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))) {
                        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) {
@@ -4337,9 +4483,11 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
                        return -EINVAL;
                }
        } else {
-               elements_needed += qeth_get_elements_no(card,(void*) hdr, skb);
-               if (!elements_needed)
+               int elems = qeth_get_elements_no(card,(void*) hdr, skb,
+                                                elements_needed);
+               if (!elems)
                        return -EINVAL;
+               elements_needed += elems;
        }
 
        if (card->info.type != QETH_CARD_TYPE_IQD)
@@ -4350,18 +4498,18 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
                                              elements_needed, ctx);
        if (!rc){
                card->stats.tx_packets++;
-               card->stats.tx_bytes += skb->len;
+               card->stats.tx_bytes += tx_bytes;
 #ifdef CONFIG_QETH_PERF_STATS
-               if (skb_shinfo(skb)->tso_size &&
+               if (tso_size &&
                   !(large_send == QETH_LARGE_SEND_NO)) {
-                       card->perf_stats.large_send_bytes += skb->len;
+                       card->perf_stats.large_send_bytes += tx_bytes;
                        card->perf_stats.large_send_cnt++;
                }
-               if (skb_shinfo(skb)->nr_frags > 0){
+               if (nr_frags > 0){
                        card->perf_stats.sg_skbs_sent++;
                        /* nr_frags + skb->data */
                        card->perf_stats.sg_frags_sent +=
-                               skb_shinfo(skb)->nr_frags + 1;
+                               nr_frags + 1;
                }
 #endif /* CONFIG_QETH_PERF_STATS */
        }
@@ -4386,6 +4534,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;
@@ -4435,38 +4584,11 @@ qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
        case MII_NCONFIG: /* network interface config */
                break;
        default:
-               rc = 0;
                break;
        }
        return rc;
 }
 
-static void
-qeth_mdio_write(struct net_device *dev, int phy_id, int regnum, int value)
-{
-       switch(regnum){
-       case MII_BMCR: /* Basic mode control register */
-       case MII_BMSR: /* Basic mode status register */
-       case MII_PHYSID1: /* PHYS ID 1 */
-       case MII_PHYSID2: /* PHYS ID 2 */
-       case MII_ADVERTISE: /* Advertisement control reg */
-       case MII_LPA: /* Link partner ability reg */
-       case MII_EXPANSION: /* Expansion register */
-       case MII_DCOUNTER: /* disconnect counter */
-       case MII_FCSCOUNTER: /* false carrier counter */
-       case MII_NWAYTEST: /* N-way auto-neg test register */
-       case MII_RERRCOUNTER: /* rx error counter */
-       case MII_SREVISION: /* silicon revision */
-       case MII_RESV1: /* reserved 1 */
-       case MII_LBRERROR: /* loopback, rx, bypass error */
-       case MII_PHYADDR: /* physical address */
-       case MII_RESV2: /* reserved 2 */
-       case MII_TPISTATUS: /* TPI status for 10mbps */
-       case MII_NCONFIG: /* network interface config */
-       default:
-               break;
-       }
-}
 
 static inline const char *
 qeth_arp_get_error_cause(int *rc)
@@ -4504,7 +4626,11 @@ qeth_arp_set_no_entries(struct qeth_card *card, int no_entries)
 
        QETH_DBF_TEXT(trace,3,"arpstnoe");
 
-       /* TODO: really not supported by GuestLAN? */
+       /*
+        * currently GuestLAN only supports the ARP assist function
+        * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
+        * thus we say EOPNOTSUPP for this ARP function
+        */
        if (card->info.guestlan)
                return -EOPNOTSUPP;
        if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
@@ -4681,14 +4807,6 @@ qeth_arp_query(struct qeth_card *card, char *udata)
 
        QETH_DBF_TEXT(trace,3,"arpquery");
 
-       /*
-        * currently GuestLAN  does only deliver all zeros on query arp,
-        * even though arp processing is supported (according to IPA supp.
-        * funcs flags); since all zeros is no valueable information,
-        * we say EOPNOTSUPP for all ARP functions
-        */
-       /*if (card->info.guestlan)
-               return -EOPNOTSUPP; */
        if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
                               IPA_ARP_PROCESSING)) {
                PRINT_WARN("ARP processing not supported "
@@ -4698,9 +4816,8 @@ qeth_arp_query(struct qeth_card *card, char *udata)
        /* get size of userspace buffer and mask_bits -> 6 bytes */
        if (copy_from_user(&qinfo, udata, 6))
                return -EFAULT;
-       if (!(qinfo.udata = kmalloc(qinfo.udata_len, GFP_KERNEL)))
+       if (!(qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL)))
                return -ENOMEM;
-       memset(qinfo.udata, 0, qinfo.udata_len);
        qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET;
        iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
                                       IPA_CMD_ASS_ARP_QUERY_INFO,
@@ -4848,11 +4965,10 @@ qeth_snmp_command(struct qeth_card *card, char *udata)
                return -EFAULT;
        }
        qinfo.udata_len = ureq->hdr.data_len;
-       if (!(qinfo.udata = kmalloc(qinfo.udata_len, GFP_KERNEL))){
+       if (!(qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL))){
                kfree(ureq);
                return -ENOMEM;
        }
-       memset(qinfo.udata, 0, qinfo.udata_len);
        qinfo.udata_offset = sizeof(struct qeth_snmp_ureq_hdr);
 
        iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL,
@@ -4877,6 +4993,10 @@ qeth_default_setassparms_cb(struct qeth_card *, struct qeth_reply *,
                            unsigned long);
 
 static int
+qeth_default_setadapterparms_cb(struct qeth_card *card,
+                                struct qeth_reply *reply,
+                                unsigned long data);
+static int
 qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *,
                      __u16, long,
                      int (*reply_cb)
@@ -4894,10 +5014,9 @@ qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
        QETH_DBF_TEXT(trace,3,"arpadent");
 
        /*
-        * currently GuestLAN  does only deliver all zeros on query arp,
-        * even though arp processing is supported (according to IPA supp.
-        * funcs flags); since all zeros is no valueable information,
-        * we say EOPNOTSUPP for all ARP functions
+        * currently GuestLAN only supports the ARP assist function
+        * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
+        * thus we say EOPNOTSUPP for this ARP function
         */
        if (card->info.guestlan)
                return -EOPNOTSUPP;
@@ -4937,10 +5056,9 @@ qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry
        QETH_DBF_TEXT(trace,3,"arprment");
 
        /*
-        * currently GuestLAN  does only deliver all zeros on query arp,
-        * even though arp processing is supported (according to IPA supp.
-        * funcs flags); since all zeros is no valueable information,
-        * we say EOPNOTSUPP for all ARP functions
+        * currently GuestLAN only supports the ARP assist function
+        * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
+        * thus we say EOPNOTSUPP for this ARP function
         */
        if (card->info.guestlan)
                return -EOPNOTSUPP;
@@ -4978,11 +5096,10 @@ qeth_arp_flush_cache(struct qeth_card *card)
        QETH_DBF_TEXT(trace,3,"arpflush");
 
        /*
-        * currently GuestLAN  does only deliver all zeros on query arp,
-        * even though arp processing is supported (according to IPA supp.
-        * funcs flags); since all zeros is no valueable information,
-        * we say EOPNOTSUPP for all ARP functions
-        */
+        * currently GuestLAN only supports the ARP assist function
+        * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
+        * thus we say EOPNOTSUPP for this ARP function
+       */
        if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
                return -EOPNOTSUPP;
        if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
@@ -5016,6 +5133,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) ||
@@ -5086,21 +5206,6 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                        mii_data->val_out = qeth_mdio_read(dev,mii_data->phy_id,
                                                           mii_data->reg_num);
                break;
-       case SIOCSMIIREG:
-               rc = -EOPNOTSUPP;
-               break;
-               /* TODO: remove return if qeth_mdio_write does something */
-               if (!capable(CAP_NET_ADMIN)){
-                       rc = -EPERM;
-                       break;
-               }
-               mii_data = if_mii(rq);
-               if (mii_data->phy_id != 0)
-                       rc = -EINVAL;
-               else
-                       qeth_mdio_write(dev, mii_data->phy_id, mii_data->reg_num,
-                                       mii_data->val_in);
-               break;
        default:
                rc = -EOPNOTSUPP;
        }
@@ -5203,10 +5308,9 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
        struct qeth_ipaddr *addr;
 
        QETH_DBF_TEXT(trace, 4, "frvaddr4");
-       if (!card->vlangrp)
-               return;
+
        rcu_read_lock();
-       in_dev = __in_dev_get(card->vlangrp->vlan_devices[vid]);
+       in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]);
        if (!in_dev)
                goto out;
        for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
@@ -5232,8 +5336,7 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
        struct qeth_ipaddr *addr;
 
        QETH_DBF_TEXT(trace, 4, "frvaddr6");
-       if (!card->vlangrp)
-               return;
+
        in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]);
        if (!in6_dev)
                return;
@@ -5253,10 +5356,38 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
 }
 
 static void
+qeth_free_vlan_addresses(struct qeth_card *card, unsigned short vid)
+{
+       if (card->options.layer2 || !card->vlangrp)
+               return;
+       qeth_free_vlan_addresses4(card, vid);
+       qeth_free_vlan_addresses6(card, vid);
+}
+
+static int
+qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
+                               struct qeth_reply *reply,
+                               unsigned long data)
+{
+        struct qeth_ipa_cmd *cmd;
+
+        QETH_DBF_TEXT(trace, 2, "L2sdvcb");
+        cmd = (struct qeth_ipa_cmd *) data;
+        if (cmd->hdr.return_code) {
+               PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
+                         "Continuing\n",cmd->data.setdelvlan.vlan_id,
+                         QETH_CARD_IFNAME(card), cmd->hdr.return_code);
+               QETH_DBF_TEXT_(trace, 2, "L2VL%4x", cmd->hdr.command);
+               QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
+               QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
+       }
+        return 0;
+}
+
+static int
 qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
                            enum qeth_ipa_cmds ipacmd)
 {
-       int rc;
        struct qeth_ipa_cmd *cmd;
        struct qeth_cmd_buffer *iob;
 
@@ -5264,15 +5395,8 @@ qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
        iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
        cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
         cmd->data.setdelvlan.vlan_id = i;
-
-       rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-        if (rc) {
-                PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
-                         "Continuing\n",i, QETH_CARD_IFNAME(card), rc);
-               QETH_DBF_TEXT_(trace, 2, "L2VL%4x", ipacmd);
-               QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
-               QETH_DBF_TEXT_(trace, 2, "err%d", rc);
-        }
+       return qeth_send_ipa_cmd(card, iob,
+                                qeth_layer2_send_setdelvlan_cb, NULL);
 }
 
 static void
@@ -5322,8 +5446,7 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        qeth_free_vlan_skbs(card, vid);
        spin_lock_irqsave(&card->vlanlock, flags);
        /* unregister IP addresses of vlan device */
-       qeth_free_vlan_addresses4(card, vid);
-       qeth_free_vlan_addresses6(card, vid);
+       qeth_free_vlan_addresses(card, vid);
        if (card->vlangrp)
                card->vlangrp->vlan_devices[vid] = NULL;
        spin_unlock_irqrestore(&card->vlanlock, flags);
@@ -5332,6 +5455,59 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        qeth_set_multicast_list(card->dev);
 }
 #endif
+/**
+ * Examine hardware response to SET_PROMISC_MODE
+ */
+static int
+qeth_setadp_promisc_mode_cb(struct qeth_card *card,
+                           struct qeth_reply *reply,
+                           unsigned long data)
+{
+       struct qeth_ipa_cmd *cmd;
+       struct qeth_ipacmd_setadpparms *setparms;
+
+       QETH_DBF_TEXT(trace,4,"prmadpcb");
+
+       cmd = (struct qeth_ipa_cmd *) data;
+       setparms = &(cmd->data.setadapterparms);
+
+        qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
+       if (cmd->hdr.return_code) {
+               QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code);
+               setparms->data.mode = SET_PROMISC_MODE_OFF;
+       }
+       card->info.promisc_mode = setparms->data.mode;
+       return 0;
+}
+/*
+ * Set promiscuous mode (on or off) (SET_PROMISC_MODE command)
+ */
+static void
+qeth_setadp_promisc_mode(struct qeth_card *card)
+{
+       enum qeth_ipa_promisc_modes mode;
+       struct net_device *dev = card->dev;
+       struct qeth_cmd_buffer *iob;
+       struct qeth_ipa_cmd *cmd;
+
+       QETH_DBF_TEXT(trace, 4, "setprom");
+
+       if (((dev->flags & IFF_PROMISC) &&
+            (card->info.promisc_mode == SET_PROMISC_MODE_ON)) ||
+           (!(dev->flags & IFF_PROMISC) &&
+            (card->info.promisc_mode == SET_PROMISC_MODE_OFF)))
+               return;
+       mode = SET_PROMISC_MODE_OFF;
+       if (dev->flags & IFF_PROMISC)
+               mode = SET_PROMISC_MODE_ON;
+       QETH_DBF_TEXT_(trace, 4, "mode:%x", mode);
+
+       iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE,
+                       sizeof(struct qeth_ipacmd_setadpparms));
+       cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
+       cmd->data.setadapterparms.data.mode = mode;
+       qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL);
+}
 
 /**
  * set multicast address on card
@@ -5341,14 +5517,26 @@ qeth_set_multicast_list(struct net_device *dev)
 {
        struct qeth_card *card = (struct qeth_card *) dev->priv;
 
-       QETH_DBF_TEXT(trace,3,"setmulti");
+       if (card->info.type == QETH_CARD_TYPE_OSN)
+               return ;
+
+       QETH_DBF_TEXT(trace, 3, "setmulti");
        qeth_delete_mc_addresses(card);
+       if (card->options.layer2) {
+               qeth_layer2_add_multicast(card);
+               goto out;
+       }
        qeth_add_multicast_ipv4(card);
 #ifdef CONFIG_QETH_IPV6
        qeth_add_multicast_ipv6(card);
 #endif
+out:
        if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
                schedule_work(&card->kernel_thread_starter);
+       if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
+               return;
+       if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
+               schedule_work(&card->kernel_thread_starter);
 }
 
 static int
@@ -5371,17 +5559,104 @@ qeth_get_addr_buffer(enum qeth_prot_versions prot)
 {
        struct qeth_ipaddr *addr;
 
-       addr = kmalloc(sizeof(struct qeth_ipaddr), GFP_ATOMIC);
+       addr = kzalloc(sizeof(struct qeth_ipaddr), GFP_ATOMIC);
        if (addr == NULL) {
                PRINT_WARN("Not enough memory to add address\n");
                return NULL;
        }
-       memset(addr,0,sizeof(struct qeth_ipaddr));
        addr->type = QETH_IP_TYPE_NORMAL;
        addr->proto = 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)
 {
@@ -5468,6 +5743,24 @@ qeth_add_multicast_ipv4(struct qeth_card *card)
        in_dev_put(in4_dev);
 }
 
+static void
+qeth_layer2_add_multicast(struct qeth_card *card)
+{
+       struct qeth_ipaddr *ipm;
+       struct dev_mc_list *dm;
+
+       QETH_DBF_TEXT(trace,4,"L2addmc");
+       for (dm = card->dev->mc_list; dm; dm = dm->next) {
+               ipm = qeth_get_addr_buffer(QETH_PROT_IPV4);
+               if (!ipm)
+                       continue;
+               memcpy(ipm->mac,dm->dmi_addr,MAX_ADDR_LEN);
+               ipm->is_multicast = 1;
+               if (!qeth_add_ip(card, ipm))
+                       kfree(ipm);
+       }
+}
+
 #ifdef CONFIG_QETH_IPV6
 static inline void
 qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
@@ -5527,10 +5820,8 @@ qeth_add_multicast_ipv6(struct qeth_card *card)
        struct inet6_dev *in6_dev;
 
        QETH_DBF_TEXT(trace,4,"chkmcv6");
-       if ((card->options.layer2 == 0) &&
-           (!qeth_is_supported(card, IPA_IPV6)) )
+       if (!qeth_is_supported(card, IPA_IPV6))
                return ;
-
        in6_dev = in6_dev_get(card->dev);
        if (in6_dev == NULL)
                return;
@@ -5636,10 +5927,10 @@ qeth_layer2_send_setmac_cb(struct qeth_card *card,
                PRINT_WARN("Error in registering MAC address on " \
                           "device %s: x%x\n", CARD_BUS_ID(card),
                           cmd->hdr.return_code);
-               card->info.layer2_mac_registered = 0;
+               card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
                cmd->hdr.return_code = -EIO;
        } else {
-               card->info.layer2_mac_registered = 1;
+               card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
                memcpy(card->dev->dev_addr,cmd->data.setdelmac.mac,
                       OSA_ADDR_LEN);
                PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
@@ -5677,7 +5968,7 @@ qeth_layer2_send_delmac_cb(struct qeth_card *card,
                cmd->hdr.return_code = -EIO;
                return 0;
        }
-       card->info.layer2_mac_registered = 0;
+       card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
 
        return 0;
 }
@@ -5685,7 +5976,7 @@ static int
 qeth_layer2_send_delmac(struct qeth_card *card, __u8 *mac)
 {
        QETH_DBF_TEXT(trace, 2, "L2Delmac");
-       if (!card->info.layer2_mac_registered)
+       if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
                return 0;
        return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELVMAC,
                                          qeth_layer2_send_delmac_cb);
@@ -5707,11 +5998,17 @@ qeth_layer2_set_mac_address(struct net_device *dev, void *p)
        card = (struct qeth_card *) dev->priv;
 
        if (!card->options.layer2) {
-               PRINT_WARN("Setting MAC address on %s is not supported"
+               PRINT_WARN("Setting MAC address on %s is not supported "
                           "in Layer 3 mode.\n", dev->name);
                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]);
@@ -6064,12 +6361,9 @@ qeth_netdev_init(struct net_device *dev)
        dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
        dev->vlan_rx_add_vid = qeth_vlan_rx_add_vid;
 #endif
-       dev->hard_header = card->orig_hard_header;
        if (qeth_get_netdev_flags(card) & IFF_NOARP) {
                dev->rebuild_header = NULL;
                dev->hard_header = NULL;
-               if (card->options.fake_ll)
-                       dev->hard_header = qeth_fake_header;
                dev->header_cache_update = NULL;
                dev->hard_header_cache = NULL;
        }
@@ -6078,6 +6372,9 @@ qeth_netdev_init(struct net_device *dev)
        if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
                card->dev->dev_id = card->info.unique_id & 0xffff;
 #endif
+       if (card->options.fake_ll &&
+               (qeth_get_netdev_flags(card) & IFF_NOARP))
+                       dev->hard_header = qeth_fake_header;
        dev->hard_header_parse = NULL;
        dev->set_mac_address = qeth_layer2_set_mac_address;
        dev->flags |= qeth_get_netdev_flags(card);
@@ -6088,9 +6385,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;
 }
@@ -6107,6 +6403,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
@@ -6136,7 +6433,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;
@@ -6182,14 +6479,17 @@ retry:
        /*network device will be recovered*/
        if (card->dev) {
                card->dev->hard_header = card->orig_hard_header;
+               if (card->options.fake_ll &&
+                   (qeth_get_netdev_flags(card) & IFF_NOARP))
+                       card->dev->hard_header = qeth_fake_header;
                return 0;
        }
        /* at first set_online allocate netdev */
        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;
@@ -6246,6 +6546,8 @@ qeth_default_setadapterparms_cb(struct qeth_card *card,
        return 0;
 }
 
+
+
 static int
 qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply,
                              unsigned long data)
@@ -6286,8 +6588,13 @@ qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
        QETH_DBF_TEXT(trace,4,"chgmaccb");
 
        cmd = (struct qeth_ipa_cmd *) data;
-       memcpy(card->dev->dev_addr,
-              &cmd->data.setadapterparms.data.change_addr.addr,OSA_ADDR_LEN);
+       if (!card->options.layer2 || card->info.guestlan ||
+           !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
+               memcpy(card->dev->dev_addr,
+                      &cmd->data.setadapterparms.data.change_addr.addr,
+                      OSA_ADDR_LEN);
+               card->info.mac_bits |= QETH_LAYER2_MAC_READ;
+       }
        qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
        return 0;
 }
@@ -6407,6 +6714,12 @@ qeth_layer2_initialize(struct qeth_card *card)
         QETH_DBF_TEXT(setup, 2, "doL2init");
         QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card));
 
+       rc = qeth_query_setadapterparms(card);
+       if (rc) {
+               PRINT_WARN("could not query adapter parameters on device %s: "
+                          "x%x\n", CARD_BUS_ID(card), rc);
+       }
+
        rc = qeth_setadpparms_change_macaddr(card);
        if (rc) {
                PRINT_WARN("couldn't get MAC address on "
@@ -6476,6 +6789,9 @@ qeth_query_ipassists_cb(struct qeth_card *card, struct qeth_reply *reply,
        if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
                card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
                card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
+               /* Disable IPV6 support hard coded for Hipersockets */
+               if(card->info.type == QETH_CARD_TYPE_IQD)
+                       card->options.ipa4.supported_funcs &= ~IPA_IPV6;
        } else {
 #ifdef CONFIG_QETH_IPV6
                card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
@@ -6541,7 +6857,7 @@ qeth_send_setassparms(struct qeth_card *card, struct qeth_cmd_buffer *iob,
        cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
        if (len <= sizeof(__u32))
                cmd->data.setassparms.data.flags_32bit = (__u32) data;
-       else if (len > sizeof(__u32))
+       else   /* (len > sizeof(__u32)) */
                memcpy(&cmd->data.setassparms.data, (void *) data, len);
 
        rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);
@@ -6720,14 +7036,12 @@ qeth_softsetup_ipv6(struct qeth_card *card)
 
        QETH_DBF_TEXT(trace,3,"softipv6");
 
-       netif_stop_queue(card->dev);
        rc = qeth_send_startlan(card, QETH_PROT_IPV6);
        if (rc) {
                PRINT_ERR("IPv6 startlan failed on %s\n",
                          QETH_CARD_IFNAME(card));
                return rc;
        }
-       netif_wake_queue(card->dev);
        rc = qeth_query_ipassists(card,QETH_PROT_IPV6);
        if (rc) {
                PRINT_ERR("IPv6 query ipassist failed on %s\n",
@@ -7020,11 +7334,6 @@ qeth_setrouting_v6(struct qeth_card *card)
        qeth_correct_routing_type(card, &card->options.route6.type,
                                  QETH_PROT_IPV6);
 
-       if ((card->options.route6.type == NO_ROUTER) ||
-           ((card->info.type == QETH_CARD_TYPE_OSAE) &&
-            (card->options.route6.type == MULTICAST_ROUTER) &&
-            !qeth_is_supported6(card,IPA_OSA_MC_ROUTER)))
-               return 0;
        rc = qeth_send_setrouting(card, card->options.route6.type,
                                  QETH_PROT_IPV6);
        if (rc) {
@@ -7038,14 +7347,17 @@ qeth_setrouting_v6(struct qeth_card *card)
 }
 
 int
-qeth_set_large_send(struct qeth_card *card)
+qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
 {
        int rc = 0;
 
-       if (card->dev == NULL)
+       if (card->dev == NULL) {
+               card->options.large_send = type;
                return 0;
-
-       netif_stop_queue(card->dev);
+       }
+       if (card->state == CARD_STATE_UP)
+               netif_tx_disable(card->dev);
+       card->options.large_send = type;
        switch (card->options.large_send) {
        case QETH_LARGE_SEND_EDDP:
                card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
@@ -7066,8 +7378,8 @@ qeth_set_large_send(struct qeth_card *card)
                card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
                break;
        }
-
-       netif_wake_queue(card->dev);
+       if (card->state == CARD_STATE_UP)
+               netif_wake_queue(card->dev);
        return rc;
 }
 
@@ -7092,6 +7404,9 @@ qeth_softsetup_card(struct qeth_card *card)
                        return rc;
        } else
                card->lan_online = 1;
+       if (card->info.type==QETH_CARD_TYPE_OSN)
+               goto out;
+       qeth_set_large_send(card, card->options.large_send);
        if (card->options.layer2) {
                card->dev->features |=
                        NETIF_F_HW_VLAN_FILTER |
@@ -7108,12 +7423,6 @@ qeth_softsetup_card(struct qeth_card *card)
 #endif
                goto out;
        }
-       if ((card->options.large_send == QETH_LARGE_SEND_EDDP) ||
-           (card->options.large_send == QETH_LARGE_SEND_TSO))
-               card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
-       else
-               card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
-
        if ((rc = qeth_setadapter_parms(card)))
                QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
        if ((rc = qeth_start_ipassists(card)))
@@ -7123,7 +7432,7 @@ qeth_softsetup_card(struct qeth_card *card)
        if ((rc = qeth_setrouting_v6(card)))
                QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
 out:
-       netif_stop_queue(card->dev);
+       netif_tx_disable(card->dev);
        return 0;
 }
 
@@ -7263,7 +7572,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();
@@ -7431,10 +7741,8 @@ static int
 qeth_register_netdev(struct qeth_card *card)
 {
        QETH_DBF_TEXT(setup, 3, "regnetd");
-       if (card->dev->reg_state != NETREG_UNINITIALIZED) {
-               qeth_netdev_init(card->dev);
+       if (card->dev->reg_state != NETREG_UNINITIALIZED)
                return 0;
-       }
        /* sysfs magic */
        SET_NETDEV_DEV(card->dev, &card->gdev->dev);
        return register_netdev(card->dev);
@@ -7445,7 +7753,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();
@@ -7477,33 +7786,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");
 }
 
 
@@ -7533,8 +7845,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);
@@ -7564,8 +7875,8 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
                QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
                goto out_remove;
        }
-/*maybe it was set offline without ifconfig down
- * we can also use this state for recovery purposes*/
+       netif_carrier_on(card->dev);
+
        qeth_set_allowed_threads(card, 0xffffffff, 0);
        if (recover_flag == CARD_STATE_RECOVER)
                qeth_start_again(card, recovery_mode);
@@ -7593,6 +7904,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);
@@ -7639,31 +7951,31 @@ static int
 qeth_register_dbf_views(void)
 {
        qeth_dbf_setup = debug_register(QETH_DBF_SETUP_NAME,
-                                       QETH_DBF_SETUP_INDEX,
+                                       QETH_DBF_SETUP_PAGES,
                                        QETH_DBF_SETUP_NR_AREAS,
                                        QETH_DBF_SETUP_LEN);
        qeth_dbf_misc = debug_register(QETH_DBF_MISC_NAME,
-                                      QETH_DBF_MISC_INDEX,
+                                      QETH_DBF_MISC_PAGES,
                                       QETH_DBF_MISC_NR_AREAS,
                                       QETH_DBF_MISC_LEN);
        qeth_dbf_data = debug_register(QETH_DBF_DATA_NAME,
-                                      QETH_DBF_DATA_INDEX,
+                                      QETH_DBF_DATA_PAGES,
                                       QETH_DBF_DATA_NR_AREAS,
                                       QETH_DBF_DATA_LEN);
        qeth_dbf_control = debug_register(QETH_DBF_CONTROL_NAME,
-                                         QETH_DBF_CONTROL_INDEX,
+                                         QETH_DBF_CONTROL_PAGES,
                                          QETH_DBF_CONTROL_NR_AREAS,
                                          QETH_DBF_CONTROL_LEN);
        qeth_dbf_sense = debug_register(QETH_DBF_SENSE_NAME,
-                                       QETH_DBF_SENSE_INDEX,
+                                       QETH_DBF_SENSE_PAGES,
                                        QETH_DBF_SENSE_NR_AREAS,
                                        QETH_DBF_SENSE_LEN);
        qeth_dbf_qerr = debug_register(QETH_DBF_QERR_NAME,
-                                      QETH_DBF_QERR_INDEX,
+                                      QETH_DBF_QERR_PAGES,
                                       QETH_DBF_QERR_NR_AREAS,
                                       QETH_DBF_QERR_LEN);
        qeth_dbf_trace = debug_register(QETH_DBF_TRACE_NAME,
-                                       QETH_DBF_TRACE_INDEX,
+                                       QETH_DBF_TRACE_PAGES,
                                        QETH_DBF_TRACE_NR_AREAS,
                                        QETH_DBF_TRACE_LEN);
 
@@ -7705,7 +8017,6 @@ static int (*qeth_old_arp_constructor) (struct neighbour *);
 
 static struct neigh_ops arp_direct_ops_template = {
        .family = AF_INET,
-       .destructor = NULL,
        .solicit = NULL,
        .error_report = NULL,
        .output = dev_queue_xmit,
@@ -7730,7 +8041,7 @@ qeth_arp_constructor(struct neighbour *neigh)
                goto out;
 
        rcu_read_lock();
-       in_dev = rcu_dereference(__in_dev_get(dev));
+       in_dev = __in_dev_get_rcu(dev);
        if (in_dev == NULL) {
                rcu_read_unlock();
                return -EINVAL;
@@ -8120,20 +8431,22 @@ static struct notifier_block qeth_ip6_notifier = {
 #endif
 
 static int
-qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+__qeth_reboot_event_card(struct device *dev, void *data)
 {
-
-       struct device *entry;
        struct qeth_card *card;
 
-       down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
-              list_for_each_entry(entry, &qeth_ccwgroup_driver.driver.devices,
-                                  driver_list) {
-                      card = (struct qeth_card *) entry->driver_data;
-                      qeth_clear_ip_list(card, 0, 0);
-                      qeth_qdio_clear_card(card, 0);
-              }
-       up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
+       card = (struct qeth_card *) dev->driver_data;
+       qeth_clear_ip_list(card, 0, 0);
+       qeth_qdio_clear_card(card, 0);
+       return 0;
+}
+
+static int
+qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+
+       driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+                              __qeth_reboot_event_card);
        return NOTIFY_DONE;
 }
 
@@ -8255,13 +8568,7 @@ qeth_init(void)
 {
        int rc=0;
 
-       qeth_eyecatcher();
-       PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n",
-                  version, VERSION_QETH_C, VERSION_QETH_H,
-                  VERSION_QETH_MPC_H, VERSION_QETH_MPC_C,
-                  VERSION_QETH_FS_H, VERSION_QETH_PROC_C,
-                  VERSION_QETH_SYS_C, QETH_VERSION_IPV6,
-                  QETH_VERSION_VLAN);
+       PRINT_INFO("loading %s\n", version);
 
        INIT_LIST_HEAD(&qeth_card_list.list);
        INIT_LIST_HEAD(&qeth_notify_list);
@@ -8336,10 +8643,12 @@ again:
        printk("qeth: removed\n");
 }
 
-EXPORT_SYMBOL(qeth_eyecatcher);
+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>");
+MODULE_AUTHOR("Frank Pavlic <fpavlic@de.ibm.com>");
 MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \
                                      "Copyright 2000,2003 IBM Corporation\n");