Skip to content

Commit 2d2ebb3

Browse files
julianwiedmanndavem330
authored andcommitted
s390/qeth: unbreak OSM and OSN support
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>
1 parent 9111e78 commit 2d2ebb3

File tree

7 files changed

+51
-20
lines changed

7 files changed

+51
-20
lines changed

drivers/s390/net/qeth_core.h

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

703703
struct qeth_discipline {
704+
const struct device_type *devtype;
704705
void (*start_poll)(struct ccw_device *, int, unsigned long);
705706
qdio_handler_t *input_handler;
706707
qdio_handler_t *output_handler;
@@ -875,6 +876,9 @@ extern struct qeth_discipline qeth_l2_discipline;
875876
extern struct qeth_discipline qeth_l3_discipline;
876877
extern const struct attribute_group *qeth_generic_attr_groups[];
877878
extern const struct attribute_group *qeth_osn_attr_groups[];
879+
extern const struct attribute_group qeth_device_attr_group;
880+
extern const struct attribute_group qeth_device_blkt_group;
881+
extern const struct device_type qeth_generic_devtype;
878882
extern struct workqueue_struct *qeth_wq;
879883

880884
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
@@ -5530,10 +5530,12 @@ void qeth_core_free_discipline(struct qeth_card *card)
55305530
card->discipline = NULL;
55315531
}
55325532

5533-
static const struct device_type qeth_generic_devtype = {
5533+
const struct device_type qeth_generic_devtype = {
55345534
.name = "qeth_generic",
55355535
.groups = qeth_generic_attr_groups,
55365536
};
5537+
EXPORT_SYMBOL_GPL(qeth_generic_devtype);
5538+
55375539
static const struct device_type qeth_osn_devtype = {
55385540
.name = "qeth_osn",
55395541
.groups = qeth_osn_attr_groups,
@@ -5659,23 +5661,22 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
56595661
goto err_card;
56605662
}
56615663

5662-
if (card->info.type == QETH_CARD_TYPE_OSN)
5663-
gdev->dev.type = &qeth_osn_devtype;
5664-
else
5665-
gdev->dev.type = &qeth_generic_devtype;
5666-
56675664
switch (card->info.type) {
56685665
case QETH_CARD_TYPE_OSN:
56695666
case QETH_CARD_TYPE_OSM:
56705667
rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
56715668
if (rc)
56725669
goto err_card;
5670+
5671+
gdev->dev.type = (card->info.type != QETH_CARD_TYPE_OSN)
5672+
? card->discipline->devtype
5673+
: &qeth_osn_devtype;
56735674
rc = card->discipline->setup(card->gdev);
56745675
if (rc)
56755676
goto err_disc;
5676-
case QETH_CARD_TYPE_OSD:
5677-
case QETH_CARD_TYPE_OSX:
5677+
break;
56785678
default:
5679+
gdev->dev.type = &qeth_generic_devtype;
56795680
break;
56805681
}
56815682

drivers/s390/net/qeth_core_sys.c

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

414414
if (card->options.layer2 == newdis)
415415
goto out;
416-
else {
417-
card->info.mac_bits = 0;
418-
if (card->discipline) {
419-
card->discipline->remove(card->gdev);
420-
qeth_core_free_discipline(card);
421-
}
416+
if (card->info.type == QETH_CARD_TYPE_OSM) {
417+
/* fixed layer, can't switch */
418+
rc = -EOPNOTSUPP;
419+
goto out;
420+
}
421+
422+
card->info.mac_bits = 0;
423+
if (card->discipline) {
424+
card->discipline->remove(card->gdev);
425+
qeth_core_free_discipline(card);
422426
}
423427

424428
rc = qeth_core_load_discipline(card, newdis);
@@ -705,10 +709,11 @@ static struct attribute *qeth_blkt_device_attrs[] = {
705709
&dev_attr_inter_jumbo.attr,
706710
NULL,
707711
};
708-
static struct attribute_group qeth_device_blkt_group = {
712+
const struct attribute_group qeth_device_blkt_group = {
709713
.name = "blkt",
710714
.attrs = qeth_blkt_device_attrs,
711715
};
716+
EXPORT_SYMBOL_GPL(qeth_device_blkt_group);
712717

713718
static struct attribute *qeth_device_attrs[] = {
714719
&dev_attr_state.attr,
@@ -728,9 +733,10 @@ static struct attribute *qeth_device_attrs[] = {
728733
&dev_attr_switch_attrs.attr,
729734
NULL,
730735
};
731-
static struct attribute_group qeth_device_attr_group = {
736+
const struct attribute_group qeth_device_attr_group = {
732737
.attrs = qeth_device_attrs,
733738
};
739+
EXPORT_SYMBOL_GPL(qeth_device_attr_group);
734740

735741
const struct attribute_group *qeth_generic_attr_groups[] = {
736742
&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
@@ -880,14 +880,21 @@ static int qeth_l2_stop(struct net_device *dev)
880880
return 0;
881881
}
882882

883+
static const struct device_type qeth_l2_devtype = {
884+
.name = "qeth_layer2",
885+
.groups = qeth_l2_attr_groups,
886+
};
887+
883888
static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
884889
{
885890
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
886891
int rc;
887892

888-
rc = qeth_l2_create_device_attributes(&gdev->dev);
889-
if (rc)
890-
return rc;
893+
if (gdev->dev.type == &qeth_generic_devtype) {
894+
rc = qeth_l2_create_device_attributes(&gdev->dev);
895+
if (rc)
896+
return rc;
897+
}
891898
INIT_LIST_HEAD(&card->vid_list);
892899
hash_init(card->mac_htable);
893900
card->options.layer2 = 1;
@@ -899,7 +906,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
899906
{
900907
struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
901908

902-
qeth_l2_remove_device_attributes(&cgdev->dev);
909+
if (cgdev->dev.type == &qeth_generic_devtype)
910+
qeth_l2_remove_device_attributes(&cgdev->dev);
903911
qeth_set_allowed_threads(card, 0, 1);
904912
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
905913

@@ -1272,6 +1280,7 @@ static int qeth_l2_control_event(struct qeth_card *card,
12721280
}
12731281

12741282
struct qeth_discipline qeth_l2_discipline = {
1283+
.devtype = &qeth_l2_devtype,
12751284
.start_poll = qeth_qdio_start_poll,
12761285
.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
12771286
.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
@@ -269,3 +269,11 @@ void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
269269
} else
270270
qeth_bridgeport_an_set(card, 0);
271271
}
272+
273+
const struct attribute_group *qeth_l2_attr_groups[] = {
274+
&qeth_device_attr_group,
275+
&qeth_device_blkt_group,
276+
/* l2 specific, see l2_{create,remove}_device_attributes(): */
277+
&qeth_l2_bridgeport_attr_group,
278+
NULL,
279+
};

drivers/s390/net/qeth_l3_main.c

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

33113311
struct qeth_discipline qeth_l3_discipline = {
3312+
.devtype = &qeth_generic_devtype,
33123313
.start_poll = qeth_qdio_start_poll,
33133314
.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
33143315
.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,

0 commit comments

Comments
 (0)