Patch "s390/qeth: unbreak OSM and OSN support" has been added to the 3.18-stable tree
Subsystems (4)
This is a note to let you know that I've just added the patch titled
s390/qeth: unbreak OSM and OSN support
to the 3.18-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
s390-qeth-unbreak-osm-and-osn-support.patch
and it can be found in the queue-3.18 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Fri Jun 2 12:04:25 JST 2017
From: Julian Wiedmann <[email protected]>
Date: Wed, 10 May 2017 19:07:52 +0200
Subject: s390/qeth: unbreak OSM and OSN support
From: Julian Wiedmann <[email protected]>
[ Upstream commit 2d2ebb3ed0c6acfb014f98e427298673a5d07b82 ]
commit b4d72c08b358 ("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.
--- drivers/s390/net/qeth_core.h | 4 ++++ drivers/s390/net/qeth_core_main.c | 17 +++++++++-------- drivers/s390/net/qeth_core_sys.c | 22 ++++++++++++++-------- drivers/s390/net/qeth_l2.h | 2 ++ drivers/s390/net/qeth_l2_main.c | 17 +++++++++++++---- drivers/s390/net/qeth_l2_sys.c | 8 ++++++++ drivers/s390/net/qeth_l3_main.c | 1 + 7 files changed, 51 insertions(+), 20 deletions(-)
drivers/s390/net/qeth_core.h +4 -0
@@ -722,6 +722,7 @@ enum qeth_discipline_id { };struct qeth_discipline { +const struct device_type *devtype;void (*start_poll)(struct ccw_device *,int ,unsigned long );qdio_handler_t *input_handler;qdio_handler_t *output_handler;
@@ -887,6 +888,9 @@ extern struct qeth_discipline qeth_l2_diextern struct qeth_discipline qeth_l3_discipline;extern const struct attribute_group *qeth_generic_attr_groups[];extern const struct attribute_group *qeth_osn_attr_groups[]; +extern const struct attribute_group qeth_device_attr_group; +extern const struct attribute_group qeth_device_blkt_group; +extern const struct device_type qeth_generic_devtype;extern struct workqueue_struct *qeth_wq;int qeth_card_hw_is_reachable (struct qeth_card *);
drivers/s390/net/qeth_core_main.c +9 -8
@@ -5304,10 +5304,12 @@ void qeth_core_free_discipline(struct qe card->discipline =NULL ; } -static const struct device_type qeth_generic_devtype = { +const struct device_type qeth_generic_devtype = { .name ="qeth_generic" , .groups = qeth_generic_attr_groups, }; +EXPORT_SYMBOL_GPL (qeth_generic_devtype); +static const struct device_type qeth_osn_devtype = { .name ="qeth_osn" , .groups = qeth_osn_attr_groups,
@@ -5433,23 +5435,22 @@ static int qeth_core_probe_device(struct goto err_card; } -if (card->info.type ==QETH_CARD_TYPE_OSN ) - gdev->dev.type = &qeth_osn_devtype; -else - gdev->dev.type = &qeth_generic_devtype; -switch (card->info.type) {case QETH_CARD_TYPE_OSN :case QETH_CARD_TYPE_OSM : rc =qeth_core_load_discipline (card,QETH_DISCIPLINE_LAYER2 );if (rc) goto err_card; + + gdev->dev.type = (card->info.type !=QETH_CARD_TYPE_OSN ) + ? card->discipline->devtype + : &qeth_osn_devtype; rc = card->discipline->setup (card->gdev);if (rc) goto err_disc; -case QETH_CARD_TYPE_OSD : -case QETH_CARD_TYPE_OSX : +break ;default : + gdev->dev.type = &qeth_generic_devtype;break ; }
drivers/s390/net/qeth_core_sys.c +14 -8
@@ -446,12 +446,16 @@ static ssize_t qeth_dev_layer2_store(strif (card->options.layer2 == newdis) goto out; -else { - card->info.mac_bits =0 ; -if (card->discipline) { - card->discipline->remove (card->gdev); -qeth_core_free_discipline (card); - } +if (card->info.type ==QETH_CARD_TYPE_OSM ) { +/* fixed layer, can't switch */ + rc = -EOPNOTSUPP ; + goto out; + } + + card->info.mac_bits =0 ; +if (card->discipline) { + card->discipline->remove (card->gdev); +qeth_core_free_discipline (card); } rc =qeth_core_load_discipline (card, newdis);
@@ -745,10 +749,11 @@ static struct attribute *qeth_blkt_devic &dev_attr_inter_jumbo.attr, NULL, }; -static struct attribute_group qeth_device_blkt_group = { +const struct attribute_group qeth_device_blkt_group = { .name ="blkt" , .attrs = qeth_blkt_device_attrs, }; +EXPORT_SYMBOL_GPL (qeth_device_blkt_group);static struct attribute *qeth_device_attrs[] = { &dev_attr_state.attr,
@@ -768,9 +773,10 @@ static struct attribute *qeth_device_att &dev_attr_switch_attrs.attr, NULL, }; -static struct attribute_group qeth_device_attr_group = { +const struct attribute_group qeth_device_attr_group = { .attrs = qeth_device_attrs, }; +EXPORT_SYMBOL_GPL (qeth_device_attr_group);const struct attribute_group *qeth_generic_attr_groups[] = { &qeth_device_attr_group,
drivers/s390/net/qeth_l2.h +2 -0
@@ -8,6 +8,8 @@#include "qeth_core.h" +extern const struct attribute_group *qeth_l2_attr_groups[]; +int qeth_l2_create_device_attributes (struct device *);void qeth_l2_remove_device_attributes (struct device *);void qeth_l2_setup_bridgeport_attrs (struct qeth_card *card);
drivers/s390/net/qeth_l2_main.c +13 -4
@@ -887,14 +887,21 @@ static int qeth_l2_stop(struct net_devicreturn 0 ; } +static const struct device_type qeth_l2_devtype = { + .name ="qeth_layer2" , + .groups = qeth_l2_attr_groups, +}; +static int qeth_l2_probe_device (struct ccwgroup_device *gdev) {struct qeth_card *card =dev_get_drvdata (&gdev->dev);int rc; - rc =qeth_l2_create_device_attributes (&gdev->dev); -if (rc) -return rc; +if (gdev->dev.type == &qeth_generic_devtype) { + rc =qeth_l2_create_device_attributes (&gdev->dev); +if (rc) +return rc; + }INIT_LIST_HEAD (&card->vid_list);INIT_LIST_HEAD (&card->mc_list); card->options.layer2 =1 ;
@@ -906,7 +913,8 @@ static void qeth_l2_remove_device(struct {struct qeth_card *card =dev_get_drvdata (&cgdev->dev); -qeth_l2_remove_device_attributes (&cgdev->dev); +if (cgdev->dev.type == &qeth_generic_devtype) +qeth_l2_remove_device_attributes (&cgdev->dev);qeth_set_allowed_threads (card,0 ,1 );wait_event (card->wait_q,qeth_threads_running (card,0xffffffff ) ==0 );
@@ -1276,6 +1284,7 @@ static int qeth_l2_control_event(struct }struct qeth_discipline qeth_l2_discipline = { + .devtype = &qeth_l2_devtype, .start_poll = qeth_qdio_start_poll, .input_handler = (qdio_handler_t *) qeth_qdio_input_handler, .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
drivers/s390/net/qeth_l2_sys.c +8 -0
@@ -216,3 +216,11 @@ void qeth_l2_setup_bridgeport_attrs(stru }else qeth_bridgeport_an_set (card,0 ); } + +const struct attribute_group *qeth_l2_attr_groups[] = { + &qeth_device_attr_group, + &qeth_device_blkt_group, +/* l2 specific, see l2_{create,remove}_device_attributes(): */ + &qeth_l2_bridgeport_attr_group, +NULL , +};
drivers/s390/net/qeth_l3_main.c +1 -0
@@ -3612,6 +3612,7 @@ static int qeth_l3_control_event(struct }struct qeth_discipline qeth_l3_discipline = { + .devtype = &qeth_generic_devtype, .start_poll = qeth_qdio_start_poll, .input_handler = (qdio_handler_t *) qeth_qdio_input_handler, .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
Patches currently in stable-queue which might be from [email protected] are
queue-3.18/s390-qeth-avoid-null-pointer-dereference-on-osn.patch queue-3.18/s390-qeth-unbreak-osm-and-osn-support.patch queue-3.18/s390-qeth-handle-sysfs-error-during-initialization.patch