]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/s390/net/qeth_core_main.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / s390 / net / qeth_core_main.c
index e6b2df0e73f56a4b143365be8302875c600c49bc..019ae58ab91352c55d979362854dab4fd2a157a2 100644 (file)
@@ -988,16 +988,30 @@ static void qeth_get_channel_path_desc(struct qeth_card *card)
        chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
        if (chp_dsc != NULL) {
                /* CHPP field bit 6 == 1 -> single queue */
-               if ((chp_dsc->chpp & 0x02) == 0x02)
+               if ((chp_dsc->chpp & 0x02) == 0x02) {
+                       if ((atomic_read(&card->qdio.state) !=
+                               QETH_QDIO_UNINITIALIZED) &&
+                           (card->qdio.no_out_queues == 4))
+                               /* change from 4 to 1 outbound queues */
+                               qeth_free_qdio_buffers(card);
                        card->qdio.no_out_queues = 1;
+                       if (card->qdio.default_out_queue != 0)
+                               dev_info(&card->gdev->dev,
+                                       "Priority Queueing not supported\n");
+                       card->qdio.default_out_queue = 0;
+               } else {
+                       if ((atomic_read(&card->qdio.state) !=
+                               QETH_QDIO_UNINITIALIZED) &&
+                           (card->qdio.no_out_queues == 1)) {
+                               /* change from 1 to 4 outbound queues */
+                               qeth_free_qdio_buffers(card);
+                               card->qdio.default_out_queue = 2;
+                       }
+                       card->qdio.no_out_queues = 4;
+               }
                card->info.func_level = 0x4100 + chp_dsc->desc;
                kfree(chp_dsc);
        }
-       if (card->qdio.no_out_queues == 1) {
-               card->qdio.default_out_queue = 0;
-               dev_info(&card->gdev->dev,
-                       "Priority Queueing not supported\n");
-       }
        QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues);
        QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level);
        return;
@@ -1832,33 +1846,6 @@ static inline int qeth_get_initial_mtu_for_card(struct qeth_card *card)
        }
 }
 
-static inline int qeth_get_max_mtu_for_card(int cardtype)
-{
-       switch (cardtype) {
-
-       case QETH_CARD_TYPE_UNKNOWN:
-       case QETH_CARD_TYPE_OSD:
-       case QETH_CARD_TYPE_OSN:
-       case QETH_CARD_TYPE_OSM:
-       case QETH_CARD_TYPE_OSX:
-               return 61440;
-       case QETH_CARD_TYPE_IQD:
-               return 57344;
-       default:
-               return 1500;
-       }
-}
-
-static inline int qeth_get_mtu_out_of_mpc(int cardtype)
-{
-       switch (cardtype) {
-       case QETH_CARD_TYPE_IQD:
-               return 1;
-       default:
-               return 0;
-       }
-}
-
 static inline int qeth_get_mtu_outof_framesize(int framesize)
 {
        switch (framesize) {
@@ -1881,10 +1868,9 @@ static inline int qeth_mtu_is_valid(struct qeth_card *card, int mtu)
        case QETH_CARD_TYPE_OSD:
        case QETH_CARD_TYPE_OSM:
        case QETH_CARD_TYPE_OSX:
-               return ((mtu >= 576) && (mtu <= 61440));
        case QETH_CARD_TYPE_IQD:
                return ((mtu >= 576) &&
-                       (mtu <= card->info.max_mtu + 4096 - 32));
+                       (mtu <= card->info.max_mtu));
        case QETH_CARD_TYPE_OSN:
        case QETH_CARD_TYPE_UNKNOWN:
        default:
@@ -1907,7 +1893,7 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
        memcpy(&card->token.ulp_filter_r,
               QETH_ULP_ENABLE_RESP_FILTER_TOKEN(iob->data),
               QETH_MPC_TOKEN_LENGTH);
-       if (qeth_get_mtu_out_of_mpc(card->info.type)) {
+       if (card->info.type == QETH_CARD_TYPE_IQD) {
                memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2);
                mtu = qeth_get_mtu_outof_framesize(framesize);
                if (!mtu) {
@@ -1915,12 +1901,21 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
                        QETH_DBF_TEXT_(SETUP, 2, "  rc%d", iob->rc);
                        return 0;
                }
-               card->info.max_mtu = mtu;
+               if (card->info.initial_mtu && (card->info.initial_mtu != mtu)) {
+                       /* frame size has changed */
+                       if (card->dev &&
+                           ((card->dev->mtu == card->info.initial_mtu) ||
+                            (card->dev->mtu > mtu)))
+                               card->dev->mtu = mtu;
+                       qeth_free_qdio_buffers(card);
+               }
                card->info.initial_mtu = mtu;
+               card->info.max_mtu = mtu;
                card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE;
        } else {
                card->info.initial_mtu = qeth_get_initial_mtu_for_card(card);
-               card->info.max_mtu = qeth_get_max_mtu_for_card(card->info.type);
+               card->info.max_mtu = *(__u16 *)QETH_ULP_ENABLE_RESP_MAX_MTU(
+                       iob->data);
                card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
        }
 
@@ -2840,6 +2835,7 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
                queue->card->perf_stats.outbound_do_qdio_time +=
                        qeth_get_micros() -
                        queue->card->perf_stats.outbound_do_qdio_start_time;
+       atomic_add(count, &queue->used_buffers);
        if (rc) {
                queue->card->stats.tx_errors += count;
                /* ignore temporary SIGA errors without busy condition */
@@ -2853,7 +2849,6 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
                qeth_schedule_recovery(queue->card);
                return;
        }
-       atomic_add(count, &queue->used_buffers);
        if (queue->card->options.performance_stats)
                queue->card->perf_stats.bufs_sent += count;
 }
@@ -3775,6 +3770,47 @@ static inline int qeth_get_qdio_q_format(struct qeth_card *card)
        }
 }
 
+static void qeth_determine_capabilities(struct qeth_card *card)
+{
+       int rc;
+       int length;
+       char *prcd;
+       struct ccw_device *ddev;
+       int ddev_offline = 0;
+
+       QETH_DBF_TEXT(SETUP, 2, "detcapab");
+       ddev = CARD_DDEV(card);
+       if (!ddev->online) {
+               ddev_offline = 1;
+               rc = ccw_device_set_online(ddev);
+               if (rc) {
+                       QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
+                       goto out;
+               }
+       }
+
+       rc = qeth_read_conf_data(card, (void **) &prcd, &length);
+       if (rc) {
+               QETH_DBF_MESSAGE(2, "%s qeth_read_conf_data returned %i\n",
+                       dev_name(&card->gdev->dev), rc);
+               QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
+               goto out_offline;
+       }
+       qeth_configure_unitaddr(card, prcd);
+       qeth_configure_blkt_default(card, prcd);
+       kfree(prcd);
+
+       rc = qdio_get_ssqd_desc(ddev, &card->ssqd);
+       if (rc)
+               QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
+
+out_offline:
+       if (ddev_offline == 1)
+               ccw_device_set_offline(ddev);
+out:
+       return;
+}
+
 static int qeth_qdio_establish(struct qeth_card *card)
 {
        struct qdio_initialize init_data;
@@ -3831,6 +3867,8 @@ static int qeth_qdio_establish(struct qeth_card *card)
        init_data.int_parm               = (unsigned long) card;
        init_data.input_sbal_addr_array  = (void **) in_sbal_ptrs;
        init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
+       init_data.scan_threshold =
+               (card->info.type == QETH_CARD_TYPE_IQD) ? 8 : 32;
 
        if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED,
                QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) {
@@ -3903,6 +3941,7 @@ int qeth_core_hardsetup_card(struct qeth_card *card)
 
        QETH_DBF_TEXT(SETUP, 2, "hrdsetup");
        atomic_set(&card->force_alloc_skb, 0);
+       qeth_get_channel_path_desc(card);
 retry:
        if (retries)
                QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n",
@@ -3931,6 +3970,7 @@ retriable:
                else
                        goto retry;
        }
+       qeth_determine_capabilities(card);
        qeth_init_tokens(card);
        qeth_init_func_level(card);
        rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb);
@@ -4200,41 +4240,6 @@ void qeth_core_free_discipline(struct qeth_card *card)
        card->discipline.ccwgdriver = NULL;
 }
 
-static void qeth_determine_capabilities(struct qeth_card *card)
-{
-       int rc;
-       int length;
-       char *prcd;
-
-       QETH_DBF_TEXT(SETUP, 2, "detcapab");
-       rc = ccw_device_set_online(CARD_DDEV(card));
-       if (rc) {
-               QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
-               goto out;
-       }
-
-
-       rc = qeth_read_conf_data(card, (void **) &prcd, &length);
-       if (rc) {
-               QETH_DBF_MESSAGE(2, "%s qeth_read_conf_data returned %i\n",
-                       dev_name(&card->gdev->dev), rc);
-               QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
-               goto out_offline;
-       }
-       qeth_configure_unitaddr(card, prcd);
-       qeth_configure_blkt_default(card, prcd);
-       kfree(prcd);
-
-       rc = qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd);
-       if (rc)
-               QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
-
-out_offline:
-       ccw_device_set_offline(CARD_DDEV(card));
-out:
-       return;
-}
-
 static int qeth_core_probe_device(struct ccwgroup_device *gdev)
 {
        struct qeth_card *card;