Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / s390 / net / qeth_l2_main.c
index 4417a36..f682f7b 100644 (file)
 #include "qeth_core.h"
 #include "qeth_core_offl.h"
 
-#define QETH_DBF_TEXT_(name, level, text...) \
-       do { \
-               if (qeth_dbf_passes(qeth_dbf_##name, level)) { \
-                       char *dbf_txt_buf = get_cpu_var(qeth_l2_dbf_txt_buf); \
-                       sprintf(dbf_txt_buf, text); \
-                       debug_text_event(qeth_dbf_##name, level, dbf_txt_buf); \
-                       put_cpu_var(qeth_l2_dbf_txt_buf); \
-               } \
-       } while (0)
-
-static DEFINE_PER_CPU(char[256], qeth_l2_dbf_txt_buf);
-
 static int qeth_l2_set_offline(struct ccwgroup_device *);
 static int qeth_l2_stop(struct net_device *);
 static int qeth_l2_send_delmac(struct qeth_card *, __u8 *);
@@ -87,7 +75,7 @@ static int qeth_l2_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                rc = -EOPNOTSUPP;
        }
        if (rc)
-               QETH_DBF_TEXT_(trace, 2, "ioce%d", rc);
+               QETH_DBF_TEXT_(TRACE, 2, "ioce%d", rc);
        return rc;
 }
 
@@ -113,19 +101,16 @@ static struct net_device *qeth_l2_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;
+       __u16 temp_dev_no;
        unsigned long flags;
+       struct ccw_dev_id read_devid;
 
        ndev = NULL;
        memcpy(&temp_dev_no, read_dev_no, 2);
        read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
        list_for_each_entry(card, &qeth_core_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) {
+               ccw_device_get_id(CARD_RDEV(card), &read_devid);
+               if (read_devid.devno == temp_dev_no) {
                        ndev = card->dev;
                        break;
                }
@@ -141,19 +126,19 @@ static int qeth_l2_send_setgroupmac_cb(struct qeth_card *card,
        struct qeth_ipa_cmd *cmd;
        __u8 *mac;
 
-       QETH_DBF_TEXT(trace, 2, "L2Sgmacb");
+       QETH_DBF_TEXT(TRACE, 2, "L2Sgmacb");
        cmd = (struct qeth_ipa_cmd *) data;
        mac = &cmd->data.setdelmac.mac[0];
        /* MAC already registered, needed in couple/uncouple case */
        if (cmd->hdr.return_code == 0x2005) {
-               PRINT_WARN("Group MAC %02x:%02x:%02x:%02x:%02x:%02x " \
+               QETH_DBF_MESSAGE(2, "Group MAC %02x:%02x:%02x:%02x:%02x:%02x "
                          "already existing on %s \n",
                          mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
                          QETH_CARD_IFNAME(card));
                cmd->hdr.return_code = 0;
        }
        if (cmd->hdr.return_code)
-               PRINT_ERR("Could not set group MAC " \
+               QETH_DBF_MESSAGE(2, "Could not set group MAC "
                          "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
                          mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
                          QETH_CARD_IFNAME(card), cmd->hdr.return_code);
@@ -162,7 +147,7 @@ static int qeth_l2_send_setgroupmac_cb(struct qeth_card *card,
 
 static int qeth_l2_send_setgroupmac(struct qeth_card *card, __u8 *mac)
 {
-       QETH_DBF_TEXT(trace, 2, "L2Sgmac");
+       QETH_DBF_TEXT(TRACE, 2, "L2Sgmac");
        return qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETGMAC,
                                          qeth_l2_send_setgroupmac_cb);
 }
@@ -174,11 +159,11 @@ static int qeth_l2_send_delgroupmac_cb(struct qeth_card *card,
        struct qeth_ipa_cmd *cmd;
        __u8 *mac;
 
-       QETH_DBF_TEXT(trace, 2, "L2Dgmacb");
+       QETH_DBF_TEXT(TRACE, 2, "L2Dgmacb");
        cmd = (struct qeth_ipa_cmd *) data;
        mac = &cmd->data.setdelmac.mac[0];
        if (cmd->hdr.return_code)
-               PRINT_ERR("Could not delete group MAC " \
+               QETH_DBF_MESSAGE(2, "Could not delete group MAC "
                          "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
                          mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
                          QETH_CARD_IFNAME(card), cmd->hdr.return_code);
@@ -187,7 +172,7 @@ static int qeth_l2_send_delgroupmac_cb(struct qeth_card *card,
 
 static int qeth_l2_send_delgroupmac(struct qeth_card *card, __u8 *mac)
 {
-       QETH_DBF_TEXT(trace, 2, "L2Dgmac");
+       QETH_DBF_TEXT(TRACE, 2, "L2Dgmac");
        return qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELGMAC,
                                          qeth_l2_send_delgroupmac_cb);
 }
@@ -198,10 +183,8 @@ static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac)
 
        mc = kmalloc(sizeof(struct qeth_mc_mac), GFP_ATOMIC);
 
-       if (!mc) {
-               PRINT_ERR("no mem vor mc mac address\n");
+       if (!mc)
                return;
-       }
 
        memcpy(mc->mc_addr, mac, OSA_ADDR_LEN);
        mc->mc_addrlen = OSA_ADDR_LEN;
@@ -289,15 +272,15 @@ static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card,
 {
        struct qeth_ipa_cmd *cmd;
 
-       QETH_DBF_TEXT(trace, 2, "L2sdvcb");
+       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. "
+               QETH_DBF_MESSAGE(2, "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);
+               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;
 }
@@ -308,7 +291,7 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
        struct qeth_ipa_cmd *cmd;
        struct qeth_cmd_buffer *iob;
 
-       QETH_DBF_TEXT_(trace, 4, "L2sdv%x", ipacmd);
+       QETH_DBF_TEXT_(TRACE, 4, "L2sdv%x", ipacmd);
        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;
@@ -319,7 +302,7 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
 static void qeth_l2_process_vlans(struct qeth_card *card, int clear)
 {
        struct qeth_vlan_vid *id;
-       QETH_DBF_TEXT(trace, 3, "L2prcvln");
+       QETH_DBF_TEXT(TRACE, 3, "L2prcvln");
        spin_lock_bh(&card->vlanlock);
        list_for_each_entry(id, &card->vid_list, list) {
                if (clear)
@@ -337,7 +320,7 @@ static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
        struct qeth_card *card = netdev_priv(dev);
        struct qeth_vlan_vid *id;
 
-       QETH_DBF_TEXT_(trace, 4, "aid:%d", vid);
+       QETH_DBF_TEXT_(TRACE, 4, "aid:%d", vid);
        id = kmalloc(sizeof(struct qeth_vlan_vid), GFP_ATOMIC);
        if (id) {
                id->vid = vid;
@@ -345,8 +328,6 @@ static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
                spin_lock_bh(&card->vlanlock);
                list_add_tail(&id->list, &card->vid_list);
                spin_unlock_bh(&card->vlanlock);
-       } else {
-               PRINT_ERR("no memory for vid\n");
        }
 }
 
@@ -355,7 +336,7 @@ static void qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        struct qeth_vlan_vid *id, *tmpid = NULL;
        struct qeth_card *card = netdev_priv(dev);
 
-       QETH_DBF_TEXT_(trace, 4, "kid:%d", vid);
+       QETH_DBF_TEXT_(TRACE, 4, "kid:%d", vid);
        spin_lock_bh(&card->vlanlock);
        list_for_each_entry(id, &card->vid_list, list) {
                if (id->vid == vid) {
@@ -376,8 +357,8 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
 {
        int rc = 0;
 
-       QETH_DBF_TEXT(setup , 2, "stopcard");
-       QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+       QETH_DBF_TEXT(SETUP , 2, "stopcard");
+       QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
 
        qeth_set_allowed_threads(card, 0, 1);
        if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD))
@@ -396,7 +377,7 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
                if (!card->use_hard_stop) {
                        __u8 *mac = &card->dev->dev_addr[0];
                        rc = qeth_l2_send_delmac(card, mac);
-                       QETH_DBF_TEXT_(setup, 2, "Lerr%d", rc);
+                       QETH_DBF_TEXT_(SETUP, 2, "Lerr%d", rc);
                }
                card->state = CARD_STATE_SOFTSETUP;
        }
@@ -451,7 +432,8 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
                                skb->ip_summed = CHECKSUM_UNNECESSARY;
                        else
                                skb->ip_summed = CHECKSUM_NONE;
-                       *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
+                       if (skb->protocol == htons(ETH_P_802_2))
+                               *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
                        len = skb->len;
                        netif_rx(skb);
                        break;
@@ -464,8 +446,8 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
                        break;
                default:
                        dev_kfree_skb_any(skb);
-                       QETH_DBF_TEXT(trace, 3, "inbunkno");
-                       QETH_DBF_HEX(control, 3, hdr, QETH_DBF_CONTROL_LEN);
+                       QETH_DBF_TEXT(TRACE, 3, "inbunkno");
+                       QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
                        continue;
                }
                card->dev->last_rx = jiffies;
@@ -483,7 +465,7 @@ static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
        struct qeth_ipa_cmd *cmd;
        struct qeth_cmd_buffer *iob;
 
-       QETH_DBF_TEXT(trace, 2, "L2sdmac");
+       QETH_DBF_TEXT(TRACE, 2, "L2sdmac");
        iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
        cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
        cmd->data.setdelmac.mac_length = OSA_ADDR_LEN;
@@ -497,10 +479,10 @@ static int qeth_l2_send_setmac_cb(struct qeth_card *card,
 {
        struct qeth_ipa_cmd *cmd;
 
-       QETH_DBF_TEXT(trace, 2, "L2Smaccb");
+       QETH_DBF_TEXT(TRACE, 2, "L2Smaccb");
        cmd = (struct qeth_ipa_cmd *) data;
        if (cmd->hdr.return_code) {
-               QETH_DBF_TEXT_(trace, 2, "L2er%x", cmd->hdr.return_code);
+               QETH_DBF_TEXT_(TRACE, 2, "L2er%x", cmd->hdr.return_code);
                card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
                cmd->hdr.return_code = -EIO;
        } else {
@@ -519,7 +501,7 @@ static int qeth_l2_send_setmac_cb(struct qeth_card *card,
 
 static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
 {
-       QETH_DBF_TEXT(trace, 2, "L2Setmac");
+       QETH_DBF_TEXT(TRACE, 2, "L2Setmac");
        return qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC,
                                          qeth_l2_send_setmac_cb);
 }
@@ -530,10 +512,10 @@ static int qeth_l2_send_delmac_cb(struct qeth_card *card,
 {
        struct qeth_ipa_cmd *cmd;
 
-       QETH_DBF_TEXT(trace, 2, "L2Dmaccb");
+       QETH_DBF_TEXT(TRACE, 2, "L2Dmaccb");
        cmd = (struct qeth_ipa_cmd *) data;
        if (cmd->hdr.return_code) {
-               QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
+               QETH_DBF_TEXT_(TRACE, 2, "err%d", cmd->hdr.return_code);
                cmd->hdr.return_code = -EIO;
                return 0;
        }
@@ -544,7 +526,7 @@ static int qeth_l2_send_delmac_cb(struct qeth_card *card,
 
 static int qeth_l2_send_delmac(struct qeth_card *card, __u8 *mac)
 {
-       QETH_DBF_TEXT(trace, 2, "L2Delmac");
+       QETH_DBF_TEXT(TRACE, 2, "L2Delmac");
        if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
                return 0;
        return qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELVMAC,
@@ -556,25 +538,24 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
        int rc = 0;
        char vendor_pre[] = {0x02, 0x00, 0x00};
 
-       QETH_DBF_TEXT(setup, 2, "doL2init");
-       QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(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);
+               QETH_DBF_MESSAGE(2, "could not query adapter parameters on "
+                       "device %s: x%x\n", CARD_BUS_ID(card), rc);
        }
 
        if (card->info.guestlan) {
                rc = qeth_setadpparms_change_macaddr(card);
                if (rc) {
-                       PRINT_WARN("couldn't get MAC address on "
-                          "device %s: x%x\n",
-                          CARD_BUS_ID(card), rc);
-                       QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+                       QETH_DBF_MESSAGE(2, "couldn't get MAC address on "
+                               "device %s: x%x\n", CARD_BUS_ID(card), rc);
+                       QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
                        return rc;
                }
-               QETH_DBF_HEX(setup, 2, card->dev->dev_addr, OSA_ADDR_LEN);
+               QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, OSA_ADDR_LEN);
        } else {
                random_ether_addr(card->dev->dev_addr);
                memcpy(card->dev->dev_addr, vendor_pre, 3);
@@ -588,21 +569,19 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
        struct qeth_card *card = netdev_priv(dev);
        int rc = 0;
 
-       QETH_DBF_TEXT(trace, 3, "setmac");
+       QETH_DBF_TEXT(TRACE, 3, "setmac");
 
        if (qeth_l2_verify_dev(dev) != QETH_REAL_CARD) {
-               QETH_DBF_TEXT(trace, 3, "setmcINV");
+               QETH_DBF_TEXT(TRACE, 3, "setmcINV");
                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");
+               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);
+       QETH_DBF_TEXT_(TRACE, 3, "%s", CARD_BUS_ID(card));
+       QETH_DBF_HEX(TRACE, 3, addr->sa_data, OSA_ADDR_LEN);
        rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
        if (!rc)
                rc = qeth_l2_send_setmac(card, addr->sa_data);
@@ -617,7 +596,7 @@ static void qeth_l2_set_multicast_list(struct net_device *dev)
        if (card->info.type == QETH_CARD_TYPE_OSN)
                return ;
 
-       QETH_DBF_TEXT(trace, 3, "setmulti");
+       QETH_DBF_TEXT(TRACE, 3, "setmulti");
        qeth_l2_del_all_mc(card);
        spin_lock_bh(&card->mclock);
        for (dm = dev->mc_list; dm; dm = dm->next)
@@ -643,8 +622,6 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
        struct qeth_eddp_context *ctx = NULL;
 
-       QETH_DBF_TEXT(trace, 6, "l2xmit");
-
        if ((card->state != CARD_STATE_UP) || !card->lan_online) {
                card->stats.tx_carrier_errors++;
                goto tx_drop;
@@ -666,9 +643,12 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (card->info.type == QETH_CARD_TYPE_OSN)
                hdr = (struct qeth_hdr *)skb->data;
        else {
-               new_skb = qeth_prepare_skb(card, skb, &hdr);
+               /* create a clone with writeable headroom */
+               new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr));
                if (!new_skb)
                        goto tx_drop;
+               hdr = (struct qeth_hdr *)skb_push(new_skb,
+                                               sizeof(struct qeth_hdr));
                qeth_l2_fill_header(card, hdr, new_skb, ipv, cast_type);
        }
 
@@ -676,7 +656,7 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
                ctx = qeth_eddp_create_context(card, new_skb, hdr,
                                                skb->sk->sk_protocol);
                if (ctx == NULL) {
-                       PRINT_WARN("could not create eddp context\n");
+                       QETH_DBF_MESSAGE(2, "could not create eddp context\n");
                        goto tx_drop;
                }
        } else {
@@ -741,6 +721,7 @@ tx_drop:
        if ((new_skb != skb) && new_skb)
                dev_kfree_skb_any(new_skb);
        dev_kfree_skb_any(skb);
+       netif_wake_queue(dev);
        return NETDEV_TX_OK;
 }
 
@@ -755,7 +736,6 @@ static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
        int index;
        int i;
 
-       QETH_DBF_TEXT(trace, 6, "qdinput");
        card = (struct qeth_card *) card_ptr;
        net_dev = card->dev;
        if (card->options.performance_stats) {
@@ -764,11 +744,11 @@ static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
        }
        if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
                if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
-                       QETH_DBF_TEXT(trace, 1, "qdinchk");
-                       QETH_DBF_TEXT_(trace, 1, "%s", CARD_BUS_ID(card));
-                       QETH_DBF_TEXT_(trace, 1, "%04X%04X", first_element,
+                       QETH_DBF_TEXT(TRACE, 1, "qdinchk");
+                       QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
+                       QETH_DBF_TEXT_(TRACE, 1, "%04X%04X", first_element,
                                        count);
-                       QETH_DBF_TEXT_(trace, 1, "%04X%04X", queue, status);
+                       QETH_DBF_TEXT_(TRACE, 1, "%04X%04X", queue, status);
                        qeth_schedule_recovery(card);
                        return;
                }
@@ -793,13 +773,13 @@ static int qeth_l2_open(struct net_device *dev)
 {
        struct qeth_card *card = netdev_priv(dev);
 
-       QETH_DBF_TEXT(trace, 4, "qethopen");
+       QETH_DBF_TEXT(TRACE, 4, "qethopen");
        if (card->state != CARD_STATE_SOFTSETUP)
                return -ENODEV;
 
        if ((card->info.type != QETH_CARD_TYPE_OSN) &&
             (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
-               QETH_DBF_TEXT(trace, 4, "nomacadr");
+               QETH_DBF_TEXT(TRACE, 4, "nomacadr");
                return -EPERM;
        }
        card->data.state = CH_STATE_UP;
@@ -817,7 +797,7 @@ static int qeth_l2_stop(struct net_device *dev)
 {
        struct qeth_card *card = netdev_priv(dev);
 
-       QETH_DBF_TEXT(trace, 4, "qethstop");
+       QETH_DBF_TEXT(TRACE, 4, "qethstop");
        netif_tx_disable(dev);
        card->dev->flags &= ~IFF_UP;
        if (card->state == CARD_STATE_UP)
@@ -860,6 +840,22 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
        return;
 }
 
+static int qeth_l2_ethtool_set_tso(struct net_device *dev, u32 data)
+{
+       struct qeth_card *card = netdev_priv(dev);
+
+       if (data) {
+               if (card->options.large_send == QETH_LARGE_SEND_NO) {
+                       card->options.large_send = QETH_LARGE_SEND_EDDP;
+                       dev->features |= NETIF_F_TSO;
+               }
+       } else {
+               dev->features &= ~NETIF_F_TSO;
+               card->options.large_send = QETH_LARGE_SEND_NO;
+       }
+       return 0;
+}
+
 static struct ethtool_ops qeth_l2_ethtool_ops = {
        .get_link = ethtool_op_get_link,
        .get_tx_csum = ethtool_op_get_tx_csum,
@@ -867,11 +863,12 @@ static struct ethtool_ops qeth_l2_ethtool_ops = {
        .get_sg = ethtool_op_get_sg,
        .set_sg = ethtool_op_set_sg,
        .get_tso = ethtool_op_get_tso,
-       .set_tso = ethtool_op_set_tso,
+       .set_tso = qeth_l2_ethtool_set_tso,
        .get_strings = qeth_core_get_strings,
        .get_ethtool_stats = qeth_core_get_ethtool_stats,
        .get_stats_count = qeth_core_get_stats_count,
        .get_drvinfo = qeth_core_get_drvinfo,
+       .get_settings = qeth_core_ethtool_get_settings,
 };
 
 static struct ethtool_ops qeth_l2_osn_ops = {
@@ -933,8 +930,8 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
        enum qeth_card_states recover_flag;
 
        BUG_ON(!card);
-       QETH_DBF_TEXT(setup, 2, "setonlin");
-       QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+       QETH_DBF_TEXT(SETUP, 2, "setonlin");
+       QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
 
        qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1);
        if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)) {
@@ -946,23 +943,23 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
        recover_flag = card->state;
        rc = ccw_device_set_online(CARD_RDEV(card));
        if (rc) {
-               QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+               QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
                return -EIO;
        }
        rc = ccw_device_set_online(CARD_WDEV(card));
        if (rc) {
-               QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+               QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
                return -EIO;
        }
        rc = ccw_device_set_online(CARD_DDEV(card));
        if (rc) {
-               QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+               QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
                return -EIO;
        }
 
        rc = qeth_core_hardsetup_card(card);
        if (rc) {
-               QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+               QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
                goto out_remove;
        }
 
@@ -976,11 +973,11 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
        qeth_print_status_message(card);
 
        /* softsetup */
-       QETH_DBF_TEXT(setup, 2, "softsetp");
+       QETH_DBF_TEXT(SETUP, 2, "softsetp");
 
        rc = qeth_send_startlan(card);
        if (rc) {
-               QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+               QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
                if (rc == 0xe080) {
                        PRINT_WARN("LAN on card %s if offline! "
                                   "Waiting for STARTLAN from card.\n",
@@ -1000,7 +997,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
 
        rc = qeth_init_qdio_queues(card);
        if (rc) {
-               QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
+               QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
                goto out_remove;
        }
        card->state = CARD_STATE_SOFTSETUP;
@@ -1047,8 +1044,8 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
        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 *));
+       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);
@@ -1064,7 +1061,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
        if (!rc)
                rc = (rc2) ? rc2 : rc3;
        if (rc)
-               QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+               QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
        if (recover_flag == CARD_STATE_UP)
                card->state = CARD_STATE_RECOVER;
        /* let user_space know that device is offline */
@@ -1083,11 +1080,11 @@ static int qeth_l2_recover(void *ptr)
        int rc = 0;
 
        card = (struct qeth_card *) ptr;
-       QETH_DBF_TEXT(trace, 2, "recover1");
-       QETH_DBF_HEX(trace, 2, &card, sizeof(void *));
+       QETH_DBF_TEXT(TRACE, 2, "recover1");
+       QETH_DBF_HEX(TRACE, 2, &card, sizeof(void *));
        if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
                return 0;
-       QETH_DBF_TEXT(trace, 2, "recover2");
+       QETH_DBF_TEXT(TRACE, 2, "recover2");
        PRINT_WARN("Recovery of device %s started ...\n",
                   CARD_BUS_ID(card));
        card->use_hard_stop = 1;
@@ -1138,20 +1135,20 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len,
        unsigned long flags;
        int rc = 0;
 
-       QETH_DBF_TEXT(trace, 5, "osndctrd");
+       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");
+       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: "
+               QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: "
                           "ccw_device_start rc = %i\n", rc);
-               QETH_DBF_TEXT_(trace, 2, " err%d", 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);
@@ -1164,7 +1161,7 @@ static int qeth_osn_send_ipa_cmd(struct qeth_card *card,
 {
        u16 s1, s2;
 
-       QETH_DBF_TEXT(trace, 4, "osndipa");
+       QETH_DBF_TEXT(TRACE, 4, "osndipa");
 
        qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
        s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
@@ -1182,7 +1179,7 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
        struct qeth_card *card;
        int rc;
 
-       QETH_DBF_TEXT(trace, 2, "osnsdmc");
+       QETH_DBF_TEXT(TRACE, 2, "osnsdmc");
        if (!dev)
                return -ENODEV;
        card = netdev_priv(dev);
@@ -1204,7 +1201,7 @@ int qeth_osn_register(unsigned char *read_dev_no, struct net_device **dev,
 {
        struct qeth_card *card;
 
-       QETH_DBF_TEXT(trace, 2, "osnreg");
+       QETH_DBF_TEXT(TRACE, 2, "osnreg");
        *dev = qeth_l2_netdev_by_devno(read_dev_no);
        if (*dev == NULL)
                return -ENODEV;
@@ -1223,7 +1220,7 @@ void qeth_osn_deregister(struct net_device *dev)
 {
        struct qeth_card *card;
 
-       QETH_DBF_TEXT(trace, 2, "osndereg");
+       QETH_DBF_TEXT(TRACE, 2, "osndereg");
        if (!dev)
                return;
        card = netdev_priv(dev);