Skip to content

Commit 21b8715

Browse files
julianwiedmanngregkh
authored andcommitted
s390/qeth: unbreak OSM and OSN support
[ Upstream commit 2d2ebb3ed0c6acfb014f98e427298673a5d07b82 ] commit b4d72c0 ("qeth: bridgeport support - basic control") broke the support for OSM and OSN devices as follows: As OSM and OSN are L2 only, qeth_core_probe_device() does an early setup by loading the l2 discipline and calling qeth_l2_probe_device(). In this context, adding the l2-specific bridgeport sysfs attributes via qeth_l2_create_device_attributes() hits a BUG_ON in fs/sysfs/group.c, since the basic sysfs infrastructure for the device hasn't been established yet. Note that OSN actually has its own unique sysfs attributes (qeth_osn_devtype), so the additional attributes shouldn't be created at all. For OSM, add a new qeth_l2_devtype that contains all the common and l2-specific sysfs attributes. When qeth_core_probe_device() does early setup for OSM or OSN, assign the corresponding devtype so that the ccwgroup probe code creates the full set of sysfs attributes. This allows us to skip qeth_l2_create_device_attributes() in case of an early setup. Any device that can't do early setup will initially have only the generic sysfs attributes, and when it's probed later qeth_l2_probe_device() adds the l2-specific attributes. If an early-setup device is removed (by calling ccwgroup_ungroup()), device_unregister() will - using the devtype - delete the l2-specific attributes before qeth_l2_remove_device() is called. So make sure to not remove them twice. What complicates the issue is that qeth_l2_probe_device() and qeth_l2_remove_device() is also called on a device when its layer2 attribute changes (ie. its layer mode is switched). For early-setup devices this wouldn't work properly - we wouldn't remove the l2-specific attributes when switching to L3. But switching the layer mode doesn't actually make any sense; we already decided that the device can only operate in L2! So just refuse to switch the layer mode on such devices. Note that OSN doesn't have a layer2 attribute, so we only need to special-case OSM. Based on an initial patch by Ursula Braun. Fixes: b4d72c0 ("qeth: bridgeport support - basic control") Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 2ac3709 commit 21b8715

7 files changed

Lines changed: 51 additions & 20 deletions

File tree

drivers/s390/net/qeth_core.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,7 @@ enum qeth_discipline_id {
717717
};
718718

719719
struct qeth_discipline {
720+
const struct device_type *devtype;
720721
void (*start_poll)(struct ccw_device *, int, unsigned long);
721722
qdio_handler_t *input_handler;
722723
qdio_handler_t *output_handler;
@@ -881,6 +882,9 @@ extern struct qeth_discipline qeth_l2_discipline;
881882
extern struct qeth_discipline qeth_l3_discipline;
882883
extern const struct attribute_group *qeth_generic_attr_groups[];
883884
extern const struct attribute_group *qeth_osn_attr_groups[];
885+
extern const struct attribute_group qeth_device_attr_group;
886+
extern const struct attribute_group qeth_device_blkt_group;
887+
extern const struct device_type qeth_generic_devtype;
884888
extern struct workqueue_struct *qeth_wq;
885889

886890
int qeth_card_hw_is_reachable(struct qeth_card *);

drivers/s390/net/qeth_core_main.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5449,10 +5449,12 @@ void qeth_core_free_discipline(struct qeth_card *card)
54495449
card->discipline = NULL;
54505450
}
54515451

5452-
static const struct device_type qeth_generic_devtype = {
5452+
const struct device_type qeth_generic_devtype = {
54535453
.name = "qeth_generic",
54545454
.groups = qeth_generic_attr_groups,
54555455
};
5456+
EXPORT_SYMBOL_GPL(qeth_generic_devtype);
5457+
54565458
static const struct device_type qeth_osn_devtype = {
54575459
.name = "qeth_osn",
54585460
.groups = qeth_osn_attr_groups,
@@ -5578,23 +5580,22 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
55785580
goto err_card;
55795581
}
55805582

5581-
if (card->info.type == QETH_CARD_TYPE_OSN)
5582-
gdev->dev.type = &qeth_osn_devtype;
5583-
else
5584-
gdev->dev.type = &qeth_generic_devtype;
5585-
55865583
switch (card->info.type) {
55875584
case QETH_CARD_TYPE_OSN:
55885585
case QETH_CARD_TYPE_OSM:
55895586
rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
55905587
if (rc)
55915588
goto err_card;
5589+
5590+
gdev->dev.type = (card->info.type != QETH_CARD_TYPE_OSN)
5591+
? card->discipline->devtype
5592+
: &qeth_osn_devtype;
55925593
rc = card->discipline->setup(card->gdev);
55935594
if (rc)
55945595
goto err_disc;
5595-
case QETH_CARD_TYPE_OSD:
5596-
case QETH_CARD_TYPE_OSX:
5596+
break;
55975597
default:
5598+
gdev->dev.type = &qeth_generic_devtype;
55985599
break;
55995600
}
56005601

drivers/s390/net/qeth_core_sys.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -409,12 +409,16 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
409409

410410
if (card->options.layer2 == newdis)
411411
goto out;
412-
else {
413-
card->info.mac_bits = 0;
414-
if (card->discipline) {
415-
card->discipline->remove(card->gdev);
416-
qeth_core_free_discipline(card);
417-
}
412+
if (card->info.type == QETH_CARD_TYPE_OSM) {
413+
/* fixed layer, can't switch */
414+
rc = -EOPNOTSUPP;
415+
goto out;
416+
}
417+
418+
card->info.mac_bits = 0;
419+
if (card->discipline) {
420+
card->discipline->remove(card->gdev);
421+
qeth_core_free_discipline(card);
418422
}
419423

420424
rc = qeth_core_load_discipline(card, newdis);
@@ -701,10 +705,11 @@ static struct attribute *qeth_blkt_device_attrs[] = {
701705
&dev_attr_inter_jumbo.attr,
702706
NULL,
703707
};
704-
static struct attribute_group qeth_device_blkt_group = {
708+
const struct attribute_group qeth_device_blkt_group = {
705709
.name = "blkt",
706710
.attrs = qeth_blkt_device_attrs,
707711
};
712+
EXPORT_SYMBOL_GPL(qeth_device_blkt_group);
708713

709714
static struct attribute *qeth_device_attrs[] = {
710715
&dev_attr_state.attr,
@@ -724,9 +729,10 @@ static struct attribute *qeth_device_attrs[] = {
724729
&dev_attr_switch_attrs.attr,
725730
NULL,
726731
};
727-
static struct attribute_group qeth_device_attr_group = {
732+
const struct attribute_group qeth_device_attr_group = {
728733
.attrs = qeth_device_attrs,
729734
};
735+
EXPORT_SYMBOL_GPL(qeth_device_attr_group);
730736

731737
const struct attribute_group *qeth_generic_attr_groups[] = {
732738
&qeth_device_attr_group,

drivers/s390/net/qeth_l2.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include "qeth_core.h"
1010

11+
extern const struct attribute_group *qeth_l2_attr_groups[];
12+
1113
int qeth_l2_create_device_attributes(struct device *);
1214
void qeth_l2_remove_device_attributes(struct device *);
1315
void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card);

drivers/s390/net/qeth_l2_main.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,14 +1027,21 @@ static int qeth_l2_stop(struct net_device *dev)
10271027
return 0;
10281028
}
10291029

1030+
static const struct device_type qeth_l2_devtype = {
1031+
.name = "qeth_layer2",
1032+
.groups = qeth_l2_attr_groups,
1033+
};
1034+
10301035
static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
10311036
{
10321037
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
10331038
int rc;
10341039

1035-
rc = qeth_l2_create_device_attributes(&gdev->dev);
1036-
if (rc)
1037-
return rc;
1040+
if (gdev->dev.type == &qeth_generic_devtype) {
1041+
rc = qeth_l2_create_device_attributes(&gdev->dev);
1042+
if (rc)
1043+
return rc;
1044+
}
10381045
INIT_LIST_HEAD(&card->vid_list);
10391046
hash_init(card->mac_htable);
10401047
card->options.layer2 = 1;
@@ -1046,7 +1053,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
10461053
{
10471054
struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
10481055

1049-
qeth_l2_remove_device_attributes(&cgdev->dev);
1056+
if (cgdev->dev.type == &qeth_generic_devtype)
1057+
qeth_l2_remove_device_attributes(&cgdev->dev);
10501058
qeth_set_allowed_threads(card, 0, 1);
10511059
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
10521060

@@ -1432,6 +1440,7 @@ static int qeth_l2_control_event(struct qeth_card *card,
14321440
}
14331441

14341442
struct qeth_discipline qeth_l2_discipline = {
1443+
.devtype = &qeth_l2_devtype,
14351444
.start_poll = qeth_qdio_start_poll,
14361445
.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
14371446
.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,

drivers/s390/net/qeth_l2_sys.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,11 @@ void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
272272
} else
273273
qeth_bridgeport_an_set(card, 0);
274274
}
275+
276+
const struct attribute_group *qeth_l2_attr_groups[] = {
277+
&qeth_device_attr_group,
278+
&qeth_device_blkt_group,
279+
/* l2 specific, see l2_{create,remove}_device_attributes(): */
280+
&qeth_l2_bridgeport_attr_group,
281+
NULL,
282+
};

drivers/s390/net/qeth_l3_main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3522,6 +3522,7 @@ static int qeth_l3_control_event(struct qeth_card *card,
35223522
}
35233523

35243524
struct qeth_discipline qeth_l3_discipline = {
3525+
.devtype = &qeth_generic_devtype,
35253526
.start_poll = qeth_qdio_start_poll,
35263527
.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
35273528
.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,

0 commit comments

Comments
 (0)