Commit c4949f07 authored by Frank Blaschka's avatar Frank Blaschka Committed by David S. Miller

qeth: synchronize configuration interface

Synchronize access to the drivers configuration interface.
Also do not allow configuration changes during online/offline
transition.
Signed-off-by: default avatarFrank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 65a1f898
...@@ -740,6 +740,7 @@ struct qeth_card { ...@@ -740,6 +740,7 @@ struct qeth_card {
atomic_t force_alloc_skb; atomic_t force_alloc_skb;
struct service_level qeth_service_level; struct service_level qeth_service_level;
struct qdio_ssqd_desc ssqd; struct qdio_ssqd_desc ssqd;
struct mutex conf_mutex;
}; };
struct qeth_card_list_struct { struct qeth_card_list_struct {
......
...@@ -1100,6 +1100,7 @@ static int qeth_setup_card(struct qeth_card *card) ...@@ -1100,6 +1100,7 @@ static int qeth_setup_card(struct qeth_card *card)
spin_lock_init(&card->lock); spin_lock_init(&card->lock);
spin_lock_init(&card->ip_lock); spin_lock_init(&card->ip_lock);
spin_lock_init(&card->thread_mask_lock); spin_lock_init(&card->thread_mask_lock);
mutex_init(&card->conf_mutex);
card->thread_start_mask = 0; card->thread_start_mask = 0;
card->thread_allowed_mask = 0; card->thread_allowed_mask = 0;
card->thread_running_mask = 0; card->thread_running_mask = 0;
......
...@@ -122,23 +122,32 @@ static ssize_t qeth_dev_portno_store(struct device *dev, ...@@ -122,23 +122,32 @@ static ssize_t qeth_dev_portno_store(struct device *dev,
struct qeth_card *card = dev_get_drvdata(dev); struct qeth_card *card = dev_get_drvdata(dev);
char *tmp; char *tmp;
unsigned int portno, limit; unsigned int portno, limit;
int rc = 0;
if (!card) if (!card)
return -EINVAL; return -EINVAL;
mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) && if ((card->state != CARD_STATE_DOWN) &&
(card->state != CARD_STATE_RECOVER)) (card->state != CARD_STATE_RECOVER)) {
return -EPERM; rc = -EPERM;
goto out;
}
portno = simple_strtoul(buf, &tmp, 16); portno = simple_strtoul(buf, &tmp, 16);
if (portno > QETH_MAX_PORTNO) if (portno > QETH_MAX_PORTNO) {
return -EINVAL; rc = -EINVAL;
goto out;
}
limit = (card->ssqd.pcnt ? card->ssqd.pcnt - 1 : card->ssqd.pcnt); limit = (card->ssqd.pcnt ? card->ssqd.pcnt - 1 : card->ssqd.pcnt);
if (portno > limit) if (portno > limit) {
return -EINVAL; rc = -EINVAL;
goto out;
}
card->info.portno = portno; 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); 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, ...@@ -165,18 +174,23 @@ static ssize_t qeth_dev_portname_store(struct device *dev,
{ {
struct qeth_card *card = dev_get_drvdata(dev); struct qeth_card *card = dev_get_drvdata(dev);
char *tmp; char *tmp;
int i; int i, rc = 0;
if (!card) if (!card)
return -EINVAL; return -EINVAL;
mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) && if ((card->state != CARD_STATE_DOWN) &&
(card->state != CARD_STATE_RECOVER)) (card->state != CARD_STATE_RECOVER)) {
return -EPERM; rc = -EPERM;
goto out;
}
tmp = strsep((char **) &buf, "\n"); tmp = strsep((char **) &buf, "\n");
if ((strlen(tmp) > 8) || (strlen(tmp) == 0)) if ((strlen(tmp) > 8) || (strlen(tmp) == 0)) {
return -EINVAL; rc = -EINVAL;
goto out;
}
card->info.portname[0] = strlen(tmp); card->info.portname[0] = strlen(tmp);
/* for beauty reasons */ /* for beauty reasons */
...@@ -184,8 +198,9 @@ static ssize_t qeth_dev_portname_store(struct device *dev, ...@@ -184,8 +198,9 @@ static ssize_t qeth_dev_portname_store(struct device *dev,
card->info.portname[i] = ' '; card->info.portname[i] = ' ';
strcpy(card->info.portname + 1, tmp); strcpy(card->info.portname + 1, tmp);
ASCEBC(card->info.portname + 1, 8); ASCEBC(card->info.portname + 1, 8);
out:
return count; mutex_unlock(&card->conf_mutex);
return rc ? rc : count;
} }
static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show, static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
...@@ -215,20 +230,25 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev, ...@@ -215,20 +230,25 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev,
{ {
struct qeth_card *card = dev_get_drvdata(dev); struct qeth_card *card = dev_get_drvdata(dev);
char *tmp; char *tmp;
int rc = 0;
if (!card) if (!card)
return -EINVAL; return -EINVAL;
mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) && if ((card->state != CARD_STATE_DOWN) &&
(card->state != CARD_STATE_RECOVER)) (card->state != CARD_STATE_RECOVER)) {
return -EPERM; rc = -EPERM;
goto out;
}
/* check if 1920 devices are supported , /* check if 1920 devices are supported ,
* if though we have to permit priority queueing * if though we have to permit priority queueing
*/ */
if (card->qdio.no_out_queues == 1) { if (card->qdio.no_out_queues == 1) {
card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT; card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
return -EPERM; rc = -EPERM;
goto out;
} }
tmp = strsep((char **) &buf, "\n"); tmp = strsep((char **) &buf, "\n");
...@@ -251,10 +271,11 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev, ...@@ -251,10 +271,11 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev,
} else if (!strcmp(tmp, "no_prio_queueing")) { } else if (!strcmp(tmp, "no_prio_queueing")) {
card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING; card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
card->qdio.default_out_queue = QETH_DEFAULT_QUEUE; card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
} else { } else
return -EINVAL; rc = -EINVAL;
} out:
return count; mutex_unlock(&card->conf_mutex);
return rc ? rc : count;
} }
static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show, static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
...@@ -277,14 +298,17 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev, ...@@ -277,14 +298,17 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev,
struct qeth_card *card = dev_get_drvdata(dev); struct qeth_card *card = dev_get_drvdata(dev);
char *tmp; char *tmp;
int cnt, old_cnt; int cnt, old_cnt;
int rc; int rc = 0;
if (!card) if (!card)
return -EINVAL; return -EINVAL;
mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) && if ((card->state != CARD_STATE_DOWN) &&
(card->state != CARD_STATE_RECOVER)) (card->state != CARD_STATE_RECOVER)) {
return -EPERM; rc = -EPERM;
goto out;
}
old_cnt = card->qdio.in_buf_pool.buf_count; old_cnt = card->qdio.in_buf_pool.buf_count;
cnt = simple_strtoul(buf, &tmp, 10); cnt = simple_strtoul(buf, &tmp, 10);
...@@ -293,7 +317,9 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev, ...@@ -293,7 +317,9 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev,
if (old_cnt != cnt) { if (old_cnt != cnt) {
rc = qeth_realloc_buffer_pool(card, 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, 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, ...@@ -337,25 +363,27 @@ static ssize_t qeth_dev_performance_stats_store(struct device *dev,
{ {
struct qeth_card *card = dev_get_drvdata(dev); struct qeth_card *card = dev_get_drvdata(dev);
char *tmp; char *tmp;
int i; int i, rc = 0;
if (!card) if (!card)
return -EINVAL; return -EINVAL;
mutex_lock(&card->conf_mutex);
i = simple_strtoul(buf, &tmp, 16); i = simple_strtoul(buf, &tmp, 16);
if ((i == 0) || (i == 1)) { if ((i == 0) || (i == 1)) {
if (i == card->options.performance_stats) if (i == card->options.performance_stats)
return count; goto out;;
card->options.performance_stats = i; card->options.performance_stats = i;
if (i == 0) if (i == 0)
memset(&card->perf_stats, 0, memset(&card->perf_stats, 0,
sizeof(struct qeth_perf_stats)); sizeof(struct qeth_perf_stats));
card->perf_stats.initial_rx_packets = card->stats.rx_packets; card->perf_stats.initial_rx_packets = card->stats.rx_packets;
card->perf_stats.initial_tx_packets = card->stats.tx_packets; card->perf_stats.initial_tx_packets = card->stats.tx_packets;
} else { } else
return -EINVAL; rc = -EINVAL;
} out:
return count; mutex_unlock(&card->conf_mutex);
return rc ? rc : count;
} }
static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show, 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, ...@@ -377,15 +405,17 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
{ {
struct qeth_card *card = dev_get_drvdata(dev); struct qeth_card *card = dev_get_drvdata(dev);
char *tmp; char *tmp;
int i, rc; int i, rc = 0;
enum qeth_discipline_id newdis; enum qeth_discipline_id newdis;
if (!card) if (!card)
return -EINVAL; return -EINVAL;
if (((card->state != CARD_STATE_DOWN) && mutex_lock(&card->conf_mutex);
(card->state != CARD_STATE_RECOVER))) if (card->state != CARD_STATE_DOWN) {
return -EPERM; rc = -EPERM;
goto out;
}
i = simple_strtoul(buf, &tmp, 16); i = simple_strtoul(buf, &tmp, 16);
switch (i) { switch (i) {
...@@ -396,12 +426,13 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, ...@@ -396,12 +426,13 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
newdis = QETH_DISCIPLINE_LAYER2; newdis = QETH_DISCIPLINE_LAYER2;
break; break;
default: default:
return -EINVAL; rc = -EINVAL;
goto out;
} }
if (card->options.layer2 == newdis) { if (card->options.layer2 == newdis)
return count; goto out;
} else { else {
if (card->discipline.ccwgdriver) { if (card->discipline.ccwgdriver) {
card->discipline.ccwgdriver->remove(card->gdev); card->discipline.ccwgdriver->remove(card->gdev);
qeth_core_free_discipline(card); qeth_core_free_discipline(card);
...@@ -410,12 +441,12 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, ...@@ -410,12 +441,12 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
rc = qeth_core_load_discipline(card, newdis); rc = qeth_core_load_discipline(card, newdis);
if (rc) if (rc)
return rc; goto out;
rc = card->discipline.ccwgdriver->probe(card->gdev); rc = card->discipline.ccwgdriver->probe(card->gdev);
if (rc) out:
return rc; mutex_unlock(&card->conf_mutex);
return count; return rc ? rc : count;
} }
static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show, static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
...@@ -454,11 +485,10 @@ static ssize_t qeth_dev_isolation_store(struct device *dev, ...@@ -454,11 +485,10 @@ static ssize_t qeth_dev_isolation_store(struct device *dev,
char *tmp, *curtoken; char *tmp, *curtoken;
curtoken = (char *) buf; curtoken = (char *) buf;
if (!card) { if (!card)
rc = -EINVAL; return -EINVAL;
goto out;
}
mutex_lock(&card->conf_mutex);
/* check for unknown, too, in case we do not yet know who we are */ /* check for unknown, too, in case we do not yet know who we are */
if (card->info.type != QETH_CARD_TYPE_OSAE && if (card->info.type != QETH_CARD_TYPE_OSAE &&
card->info.type != QETH_CARD_TYPE_UNKNOWN) { card->info.type != QETH_CARD_TYPE_UNKNOWN) {
...@@ -491,6 +521,7 @@ static ssize_t qeth_dev_isolation_store(struct device *dev, ...@@ -491,6 +521,7 @@ static ssize_t qeth_dev_isolation_store(struct device *dev,
rc = ipa_rc; rc = ipa_rc;
} }
out: out:
mutex_unlock(&card->conf_mutex);
return rc; return rc;
} }
...@@ -510,22 +541,25 @@ static ssize_t qeth_dev_blkt_store(struct qeth_card *card, ...@@ -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) const char *buf, size_t count, int *value, int max_value)
{ {
char *tmp; char *tmp;
int i; int i, rc = 0;
if (!card) if (!card)
return -EINVAL; return -EINVAL;
mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) && if ((card->state != CARD_STATE_DOWN) &&
(card->state != CARD_STATE_RECOVER)) (card->state != CARD_STATE_RECOVER)) {
return -EPERM; rc = -EPERM;
goto out;
}
i = simple_strtoul(buf, &tmp, 10); i = simple_strtoul(buf, &tmp, 10);
if (i <= max_value) { if (i <= max_value)
*value = i; *value = i;
} else { else
return -EINVAL; rc = -EINVAL;
} out:
return count; mutex_unlock(&card->conf_mutex);
return rc ? rc : count;
} }
static ssize_t qeth_dev_blkt_total_show(struct device *dev, static ssize_t qeth_dev_blkt_total_show(struct device *dev,
......
...@@ -924,6 +924,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -924,6 +924,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
enum qeth_card_states recover_flag; enum qeth_card_states recover_flag;
BUG_ON(!card); BUG_ON(!card);
mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 2, "setonlin"); QETH_DBF_TEXT(SETUP, 2, "setonlin");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
...@@ -956,7 +957,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -956,7 +957,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
dev_warn(&card->gdev->dev, dev_warn(&card->gdev->dev,
"The LAN is offline\n"); "The LAN is offline\n");
card->lan_online = 0; card->lan_online = 0;
return 0; goto out;
} }
rc = -ENODEV; rc = -ENODEV;
goto out_remove; goto out_remove;
...@@ -995,6 +996,8 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -995,6 +996,8 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
} }
/* let user_space know that device is online */ /* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
out:
mutex_unlock(&card->conf_mutex);
return 0; return 0;
out_remove: out_remove:
...@@ -1007,6 +1010,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -1007,6 +1010,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
card->state = CARD_STATE_RECOVER; card->state = CARD_STATE_RECOVER;
else else
card->state = CARD_STATE_DOWN; card->state = CARD_STATE_DOWN;
mutex_unlock(&card->conf_mutex);
return rc; return rc;
} }
...@@ -1022,6 +1026,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, ...@@ -1022,6 +1026,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
int rc = 0, rc2 = 0, rc3 = 0; int rc = 0, rc2 = 0, rc3 = 0;
enum qeth_card_states recover_flag; enum qeth_card_states recover_flag;
mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 3, "setoffl"); QETH_DBF_TEXT(SETUP, 3, "setoffl");
QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *)); QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
...@@ -1040,6 +1045,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, ...@@ -1040,6 +1045,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
card->state = CARD_STATE_RECOVER; card->state = CARD_STATE_RECOVER;
/* let user_space know that device is offline */ /* let user_space know that device is offline */
kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE); kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
mutex_unlock(&card->conf_mutex);
return 0; return 0;
} }
......
...@@ -3378,6 +3378,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -3378,6 +3378,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
enum qeth_card_states recover_flag; enum qeth_card_states recover_flag;
BUG_ON(!card); BUG_ON(!card);
mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 2, "setonlin"); QETH_DBF_TEXT(SETUP, 2, "setonlin");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
...@@ -3409,7 +3410,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -3409,7 +3410,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
dev_warn(&card->gdev->dev, dev_warn(&card->gdev->dev,
"The LAN is offline\n"); "The LAN is offline\n");
card->lan_online = 0; card->lan_online = 0;
return 0; goto out;
} }
rc = -ENODEV; rc = -ENODEV;
goto out_remove; goto out_remove;
...@@ -3456,6 +3457,8 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -3456,6 +3457,8 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
} }
/* let user_space know that device is online */ /* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
out:
mutex_unlock(&card->conf_mutex);
return 0; return 0;
out_remove: out_remove:
card->use_hard_stop = 1; card->use_hard_stop = 1;
...@@ -3467,6 +3470,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -3467,6 +3470,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
card->state = CARD_STATE_RECOVER; card->state = CARD_STATE_RECOVER;
else else
card->state = CARD_STATE_DOWN; card->state = CARD_STATE_DOWN;
mutex_unlock(&card->conf_mutex);
return rc; return rc;
} }
...@@ -3482,6 +3486,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, ...@@ -3482,6 +3486,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
int rc = 0, rc2 = 0, rc3 = 0; int rc = 0, rc2 = 0, rc3 = 0;
enum qeth_card_states recover_flag; enum qeth_card_states recover_flag;
mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 3, "setoffl"); QETH_DBF_TEXT(SETUP, 3, "setoffl");
QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *)); QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
...@@ -3500,6 +3505,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, ...@@ -3500,6 +3505,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
card->state = CARD_STATE_RECOVER; card->state = CARD_STATE_RECOVER;
/* let user_space know that device is offline */ /* let user_space know that device is offline */
kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE); kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
mutex_unlock(&card->conf_mutex);
return 0; return 0;
} }
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment