]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/s390/net/qeth_main.c
[IPV4]: Replace __in_dev_get with __in_dev_get_rcu/rtnl
[net-next-2.6.git] / drivers / s390 / net / qeth_main.c
index 79c74f3a11f5f471d79fa6c3507e56d9fe553a33..71de834ece1ac532ccc4a68736c453c0e958dbf8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,7 +12,7 @@
  *                       Frank Pavlic (pavlic@de.ibm.com) and
  *                       Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.214 $        $Date: 2005/05/04 20:19:18 $
+ *    $Revision: 1.224 $        $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
  * 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>
@@ -80,7 +72,7 @@ qeth_eyecatcher(void)
 #include "qeth_eddp.h"
 #include "qeth_tso.h"
 
-#define VERSION_QETH_C "$Revision: 1.214 $"
+#define VERSION_QETH_C "$Revision: 1.224 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -2759,11 +2751,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 +2899,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);
@@ -3356,26 +3343,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 +3438,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);
@@ -3795,12 +3788,16 @@ static inline int
 qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
                 struct qeth_hdr **hdr, int ipv)
 {
+       int rc;
 #ifdef CONFIG_QETH_VLAN
        u16 *tag;
 #endif
 
        QETH_DBF_TEXT(trace, 6, "prepskb");
 
+        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) ) {
@@ -4251,7 +4248,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 +4259,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,7 +4274,7 @@ 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;
@@ -4337,9 +4336,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)
@@ -4504,7 +4505,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 +4686,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 "
@@ -4894,10 +4891,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 +4933,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 +4973,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)) {
@@ -5206,7 +5200,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
        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) {
@@ -7038,14 +7032,16 @@ 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);
+       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,7 +7062,6 @@ qeth_set_large_send(struct qeth_card *card)
                card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
                break;
        }
-
        netif_wake_queue(card->dev);
        return rc;
 }
@@ -7730,7 +7725,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;
@@ -8257,7 +8252,6 @@ 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,
@@ -8338,7 +8332,6 @@ again:
        printk("qeth: removed\n");
 }
 
-EXPORT_SYMBOL(qeth_eyecatcher);
 module_init(qeth_init);
 module_exit(qeth_exit);
 MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>");