qeth: synchronize configuration interface
[safe/jmp/linux-2.6] / drivers / s390 / net / qeth_core_sys.c
index 25dfd5a..cbac405 100644 (file)
@@ -122,23 +122,32 @@ static ssize_t qeth_dev_portno_store(struct device *dev,
        struct qeth_card *card = dev_get_drvdata(dev);
        char *tmp;
        unsigned int portno, limit;
+       int rc = 0;
 
        if (!card)
                return -EINVAL;
 
+       mutex_lock(&card->conf_mutex);
        if ((card->state != CARD_STATE_DOWN) &&
-           (card->state != CARD_STATE_RECOVER))
-               return -EPERM;
+           (card->state != CARD_STATE_RECOVER)) {
+               rc = -EPERM;
+               goto out;
+       }
 
        portno = simple_strtoul(buf, &tmp, 16);
-       if (portno > QETH_MAX_PORTNO)
-               return -EINVAL;
+       if (portno > QETH_MAX_PORTNO) {
+               rc = -EINVAL;
+               goto out;
+       }
        limit = (card->ssqd.pcnt ? card->ssqd.pcnt - 1 : card->ssqd.pcnt);
-       if (portno > limit)
-               return -EINVAL;
-
+       if (portno > limit) {
+               rc = -EINVAL;
+               goto out;
+       }
        card->info.portno = portno;
-       return count;
+out:
+       mutex_unlock(&card->conf_mutex);
+       return rc ? rc : count;
 }
 
 static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
@@ -165,18 +174,23 @@ static ssize_t qeth_dev_portname_store(struct device *dev,
 {
        struct qeth_card *card = dev_get_drvdata(dev);
        char *tmp;
-       int i;
+       int i, rc = 0;
 
        if (!card)
                return -EINVAL;
 
+       mutex_lock(&card->conf_mutex);
        if ((card->state != CARD_STATE_DOWN) &&
-           (card->state != CARD_STATE_RECOVER))
-               return -EPERM;
+           (card->state != CARD_STATE_RECOVER)) {
+               rc = -EPERM;
+               goto out;
+       }
 
        tmp = strsep((char **) &buf, "\n");
-       if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
-               return -EINVAL;
+       if ((strlen(tmp) > 8) || (strlen(tmp) == 0)) {
+               rc = -EINVAL;
+               goto out;
+       }
 
        card->info.portname[0] = strlen(tmp);
        /* for beauty reasons */
@@ -184,8 +198,9 @@ static ssize_t qeth_dev_portname_store(struct device *dev,
                card->info.portname[i] = ' ';
        strcpy(card->info.portname + 1, tmp);
        ASCEBC(card->info.portname + 1, 8);
-
-       return count;
+out:
+       mutex_unlock(&card->conf_mutex);
+       return rc ? rc : count;
 }
 
 static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
@@ -215,20 +230,25 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev,
 {
        struct qeth_card *card = dev_get_drvdata(dev);
        char *tmp;
+       int rc = 0;
 
        if (!card)
                return -EINVAL;
 
+       mutex_lock(&card->conf_mutex);
        if ((card->state != CARD_STATE_DOWN) &&
-           (card->state != CARD_STATE_RECOVER))
-               return -EPERM;
+           (card->state != CARD_STATE_RECOVER)) {
+               rc = -EPERM;
+               goto out;
+       }
 
        /* check if 1920 devices are supported ,
         * if though we have to permit priority queueing
         */
        if (card->qdio.no_out_queues == 1) {
                card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
-               return -EPERM;
+               rc = -EPERM;
+               goto out;
        }
 
        tmp = strsep((char **) &buf, "\n");
@@ -251,10 +271,11 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev,
        } else if (!strcmp(tmp, "no_prio_queueing")) {
                card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
                card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
-       } else {
-               return -EINVAL;
-       }
-       return count;
+       } else
+               rc = -EINVAL;
+out:
+       mutex_unlock(&card->conf_mutex);
+       return rc ? rc : count;
 }
 
 static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
@@ -277,14 +298,17 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev,
        struct qeth_card *card = dev_get_drvdata(dev);
        char *tmp;
        int cnt, old_cnt;
-       int rc;
+       int rc = 0;
 
        if (!card)
                return -EINVAL;
 
+       mutex_lock(&card->conf_mutex);
        if ((card->state != CARD_STATE_DOWN) &&
-           (card->state != CARD_STATE_RECOVER))
-               return -EPERM;
+           (card->state != CARD_STATE_RECOVER)) {
+               rc = -EPERM;
+               goto out;
+       }
 
        old_cnt = card->qdio.in_buf_pool.buf_count;
        cnt = simple_strtoul(buf, &tmp, 10);
@@ -293,7 +317,9 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev,
        if (old_cnt != cnt) {
                rc = qeth_realloc_buffer_pool(card, cnt);
        }
-       return count;
+out:
+       mutex_unlock(&card->conf_mutex);
+       return rc ? rc : count;
 }
 
 static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
@@ -337,25 +363,27 @@ static ssize_t qeth_dev_performance_stats_store(struct device *dev,
 {
        struct qeth_card *card = dev_get_drvdata(dev);
        char *tmp;
-       int i;
+       int i, rc = 0;
 
        if (!card)
                return -EINVAL;
 
+       mutex_lock(&card->conf_mutex);
        i = simple_strtoul(buf, &tmp, 16);
        if ((i == 0) || (i == 1)) {
                if (i == card->options.performance_stats)
-                       return count;
+                       goto out;;
                card->options.performance_stats = i;
                if (i == 0)
                        memset(&card->perf_stats, 0,
                                sizeof(struct qeth_perf_stats));
                card->perf_stats.initial_rx_packets = card->stats.rx_packets;
                card->perf_stats.initial_tx_packets = card->stats.tx_packets;
-       } else {
-               return -EINVAL;
-       }
-       return count;
+       } else
+               rc = -EINVAL;
+out:
+       mutex_unlock(&card->conf_mutex);
+       return rc ? rc : count;
 }
 
 static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
@@ -377,15 +405,17 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
 {
        struct qeth_card *card = dev_get_drvdata(dev);
        char *tmp;
-       int i, rc;
+       int i, rc = 0;
        enum qeth_discipline_id newdis;
 
        if (!card)
                return -EINVAL;
 
-       if (((card->state != CARD_STATE_DOWN) &&
-            (card->state != CARD_STATE_RECOVER)))
-               return -EPERM;
+       mutex_lock(&card->conf_mutex);
+       if (card->state != CARD_STATE_DOWN) {
+               rc = -EPERM;
+               goto out;
+       }
 
        i = simple_strtoul(buf, &tmp, 16);
        switch (i) {
@@ -396,12 +426,13 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
                newdis = QETH_DISCIPLINE_LAYER2;
                break;
        default:
-               return -EINVAL;
+               rc = -EINVAL;
+               goto out;
        }
 
-       if (card->options.layer2 == newdis) {
-               return count;
-       else {
+       if (card->options.layer2 == newdis)
+               goto out;
+       else {
                if (card->discipline.ccwgdriver) {
                        card->discipline.ccwgdriver->remove(card->gdev);
                        qeth_core_free_discipline(card);
@@ -410,12 +441,12 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
 
        rc = qeth_core_load_discipline(card, newdis);
        if (rc)
-               return rc;
+               goto out;
 
        rc = card->discipline.ccwgdriver->probe(card->gdev);
-       if (rc)
-               return rc;
-       return count;
+out:
+       mutex_unlock(&card->conf_mutex);
+       return rc ? rc : count;
 }
 
 static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
@@ -454,11 +485,10 @@ static ssize_t qeth_dev_isolation_store(struct device *dev,
        char *tmp, *curtoken;
        curtoken = (char *) buf;
 
-       if (!card) {
-               rc = -EINVAL;
-               goto out;
-       }
+       if (!card)
+               return -EINVAL;
 
+       mutex_lock(&card->conf_mutex);
        /* check for unknown, too, in case we do not yet know who we are */
        if (card->info.type != QETH_CARD_TYPE_OSAE &&
            card->info.type != QETH_CARD_TYPE_UNKNOWN) {
@@ -491,6 +521,7 @@ static ssize_t qeth_dev_isolation_store(struct device *dev,
                        rc = ipa_rc;
        }
 out:
+       mutex_unlock(&card->conf_mutex);
        return rc;
 }
 
@@ -510,22 +541,25 @@ static ssize_t qeth_dev_blkt_store(struct qeth_card *card,
                const char *buf, size_t count, int *value, int max_value)
 {
        char *tmp;
-       int i;
+       int i, rc = 0;
 
        if (!card)
                return -EINVAL;
 
+       mutex_lock(&card->conf_mutex);
        if ((card->state != CARD_STATE_DOWN) &&
-           (card->state != CARD_STATE_RECOVER))
-               return -EPERM;
-
+           (card->state != CARD_STATE_RECOVER)) {
+               rc = -EPERM;
+               goto out;
+       }
        i = simple_strtoul(buf, &tmp, 10);
-       if (i <= max_value) {
+       if (i <= max_value)
                *value = i;
-       } else {
-               return -EINVAL;
-       }
-       return count;
+       else
+               rc = -EINVAL;
+out:
+       mutex_unlock(&card->conf_mutex);
+       return rc ? rc : count;
 }
 
 static ssize_t qeth_dev_blkt_total_show(struct device *dev,