diff options
author | Frank Blaschka <frank.blaschka@de.ibm.com> | 2010-05-11 19:34:47 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-05-16 00:50:11 -0700 |
commit | c4949f074332a64baeb2ead6ab9319ca37642f96 (patch) | |
tree | 185005280b499114ba872560efe21ec75b0ba726 /drivers/s390/net/qeth_core_sys.c | |
parent | 65a1f898efac136aeea65509e61ac6cdecd4f6bf (diff) | |
download | lwn-c4949f074332a64baeb2ead6ab9319ca37642f96.tar.gz lwn-c4949f074332a64baeb2ead6ab9319ca37642f96.zip |
qeth: synchronize configuration interface
Synchronize access to the drivers configuration interface.
Also do not allow configuration changes during online/offline
transition.
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/s390/net/qeth_core_sys.c')
-rw-r--r-- | drivers/s390/net/qeth_core_sys.c | 148 |
1 files changed, 91 insertions, 57 deletions
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 25dfd5abd19b..cbac4050afb2 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -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, |