Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[linux-2.6-block.git] / drivers / s390 / net / qeth_core_main.c
index e89f38c3117606dd8d4a83226c44baf2e4f22bb1..f54bec54d677635154f190fc73e26f896d17bd34 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/kthread.h>
 #include <linux/slab.h>
 #include <net/iucv/af_iucv.h>
+#include <net/dsfield.h>
 
 #include <asm/ebcdic.h>
 #include <asm/chpid.h>
@@ -1013,7 +1014,7 @@ static long __qeth_check_irb_error(struct ccw_device *cdev,
 
        card = CARD_FROM_CDEV(cdev);
 
-       if (!IS_ERR(irb))
+       if (!card || !IS_ERR(irb))
                return 0;
 
        switch (PTR_ERR(irb)) {
@@ -1029,7 +1030,7 @@ static long __qeth_check_irb_error(struct ccw_device *cdev,
                QETH_CARD_TEXT(card, 2, "ckirberr");
                QETH_CARD_TEXT_(card, 2, "  rc%d", -ETIMEDOUT);
                if (intparm == QETH_RCD_PARM) {
-                       if (card && (card->data.ccwdev == cdev)) {
+                       if (card->data.ccwdev == cdev) {
                                card->data.state = CH_STATE_DOWN;
                                wake_up(&card->wait_q);
                        }
@@ -3662,42 +3663,56 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
 }
 EXPORT_SYMBOL_GPL(qeth_qdio_output_handler);
 
+/**
+ * Note: Function assumes that we have 4 outbound queues.
+ */
 int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
                        int ipv, int cast_type)
 {
-       if (!ipv && (card->info.type == QETH_CARD_TYPE_OSD ||
-                    card->info.type == QETH_CARD_TYPE_OSX))
-               return card->qdio.default_out_queue;
-       switch (card->qdio.no_out_queues) {
-       case 4:
-               if (cast_type && card->info.is_multicast_different)
-                       return card->info.is_multicast_different &
-                               (card->qdio.no_out_queues - 1);
-               if (card->qdio.do_prio_queueing && (ipv == 4)) {
-                       const u8 tos = ip_hdr(skb)->tos;
-
-                       if (card->qdio.do_prio_queueing ==
-                               QETH_PRIO_Q_ING_TOS) {
-                               if (tos & IP_TOS_NOTIMPORTANT)
-                                       return 3;
-                               if (tos & IP_TOS_HIGHRELIABILITY)
-                                       return 2;
-                               if (tos & IP_TOS_HIGHTHROUGHPUT)
-                                       return 1;
-                               if (tos & IP_TOS_LOWDELAY)
-                                       return 0;
-                       }
-                       if (card->qdio.do_prio_queueing ==
-                               QETH_PRIO_Q_ING_PREC)
-                               return 3 - (tos >> 6);
-               } else if (card->qdio.do_prio_queueing && (ipv == 6)) {
-                       /* TODO: IPv6!!! */
+       __be16 *tci;
+       u8 tos;
+
+       if (cast_type && card->info.is_multicast_different)
+               return card->info.is_multicast_different &
+                       (card->qdio.no_out_queues - 1);
+
+       switch (card->qdio.do_prio_queueing) {
+       case QETH_PRIO_Q_ING_TOS:
+       case QETH_PRIO_Q_ING_PREC:
+               switch (ipv) {
+               case 4:
+                       tos = ipv4_get_dsfield(ip_hdr(skb));
+                       break;
+               case 6:
+                       tos = ipv6_get_dsfield(ipv6_hdr(skb));
+                       break;
+               default:
+                       return card->qdio.default_out_queue;
                }
-               return card->qdio.default_out_queue;
-       case 1: /* fallthrough for single-out-queue 1920-device */
+               if (card->qdio.do_prio_queueing == QETH_PRIO_Q_ING_PREC)
+                       return ~tos >> 6 & 3;
+               if (tos & IPTOS_MINCOST)
+                       return 3;
+               if (tos & IPTOS_RELIABILITY)
+                       return 2;
+               if (tos & IPTOS_THROUGHPUT)
+                       return 1;
+               if (tos & IPTOS_LOWDELAY)
+                       return 0;
+               break;
+       case QETH_PRIO_Q_ING_SKB:
+               if (skb->priority > 5)
+                       return 0;
+               return ~skb->priority >> 1 & 3;
+       case QETH_PRIO_Q_ING_VLAN:
+               tci = &((struct ethhdr *)skb->data)->h_proto;
+               if (*tci == ETH_P_8021Q)
+                       return ~*(tci + 1) >> (VLAN_PRIO_SHIFT + 1) & 3;
+               break;
        default:
-               return card->qdio.default_out_queue;
+               break;
        }
+       return card->qdio.default_out_queue;
 }
 EXPORT_SYMBOL_GPL(qeth_get_priority_queue);
 
@@ -5703,6 +5718,7 @@ int qeth_core_ethtool_get_settings(struct net_device *netdev,
        struct qeth_card *card = netdev->ml_priv;
        enum qeth_link_types link_type;
        struct carrier_info carrier_info;
+       u32 speed;
 
        if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan))
                link_type = QETH_LINK_TYPE_10GBIT_ETH;
@@ -5717,28 +5733,29 @@ int qeth_core_ethtool_get_settings(struct net_device *netdev,
        case QETH_LINK_TYPE_FAST_ETH:
        case QETH_LINK_TYPE_LANE_ETH100:
                qeth_set_ecmd_adv_sup(ecmd, SPEED_100, PORT_TP);
-               ecmd->speed = SPEED_100;
+               speed = SPEED_100;
                ecmd->port = PORT_TP;
                break;
 
        case QETH_LINK_TYPE_GBIT_ETH:
        case QETH_LINK_TYPE_LANE_ETH1000:
                qeth_set_ecmd_adv_sup(ecmd, SPEED_1000, PORT_FIBRE);
-               ecmd->speed = SPEED_1000;
+               speed = SPEED_1000;
                ecmd->port = PORT_FIBRE;
                break;
 
        case QETH_LINK_TYPE_10GBIT_ETH:
                qeth_set_ecmd_adv_sup(ecmd, SPEED_10000, PORT_FIBRE);
-               ecmd->speed = SPEED_10000;
+               speed = SPEED_10000;
                ecmd->port = PORT_FIBRE;
                break;
 
        default:
                qeth_set_ecmd_adv_sup(ecmd, SPEED_10, PORT_TP);
-               ecmd->speed = SPEED_10;
+               speed = SPEED_10;
                ecmd->port = PORT_TP;
        }
+       ethtool_cmd_speed_set(ecmd, speed);
 
        /* Check if we can obtain more accurate information.     */
        /* If QUERY_CARD_INFO command is not supported or fails, */
@@ -5783,18 +5800,19 @@ int qeth_core_ethtool_get_settings(struct net_device *netdev,
 
        switch (carrier_info.port_speed) {
        case CARD_INFO_PORTS_10M:
-               ecmd->speed = SPEED_10;
+               speed = SPEED_10;
                break;
        case CARD_INFO_PORTS_100M:
-               ecmd->speed = SPEED_100;
+               speed = SPEED_100;
                break;
        case CARD_INFO_PORTS_1G:
-               ecmd->speed = SPEED_1000;
+               speed = SPEED_1000;
                break;
        case CARD_INFO_PORTS_10G:
-               ecmd->speed = SPEED_10000;
+               speed = SPEED_10000;
                break;
        }
+       ethtool_cmd_speed_set(ecmd, speed);
 
        return 0;
 }
@@ -5816,7 +5834,7 @@ static int __init qeth_core_init(void)
        if (rc)
                goto out_err;
        qeth_core_root_dev = root_device_register("qeth");
-       rc = PTR_RET(qeth_core_root_dev);
+       rc = PTR_ERR_OR_ZERO(qeth_core_root_dev);
        if (rc)
                goto register_err;
        qeth_core_header_cache = kmem_cache_create("qeth_hdr",