Skip to content

Commit 0f54761

Browse files
Stefan Raspldavem330
authored andcommitted
qeth: Support VEPA mode
The existing port isolation mode 'forward' will now verify that the adjacent switch port supports the required reflective relay (RR) mode. This patch adds the required error handling for the cases where enabling port isolation mode 'forward' can now fail. Furthermore, once established, we never fall back from one of the port isolation modes to a non-isolated mode without further user-interaction. This includes cases where the isolation mode was enabled successfully, but ceases to work e.g. due to configuration changes at the switch port. Finally, configuring an isolation mode with the device being offline will make onlining the device fail permanently upon errors encountered until either errors are resolved or the isolation mode is changed by the user to a different mode. Signed-off-by: Stefan Raspl <[email protected]> Signed-off-by: Frank Blaschka <[email protected]> Reviewed-by: Ursula Braun <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent eb3fb0b commit 0f54761

File tree

7 files changed

+112
-67
lines changed

7 files changed

+112
-67
lines changed

drivers/s390/net/qeth_core.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,7 @@ struct qeth_card_options {
678678
int performance_stats;
679679
int rx_sg_cb;
680680
enum qeth_ipa_isolation_modes isolation;
681+
enum qeth_ipa_isolation_modes prev_isolation;
681682
int sniffer;
682683
enum qeth_cq cq;
683684
char hsuid[9];
@@ -789,6 +790,7 @@ struct qeth_card {
789790
struct qeth_rx rx;
790791
struct delayed_work buffer_reclaim_work;
791792
int reclaim_index;
793+
struct work_struct close_dev_work;
792794
};
793795

794796
struct qeth_card_list_struct {
@@ -925,12 +927,13 @@ void qeth_core_get_strings(struct net_device *, u32, u8 *);
925927
void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
926928
void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
927929
int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *);
928-
int qeth_set_access_ctrl_online(struct qeth_card *card);
930+
int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback);
929931
int qeth_hdr_chk_and_bounce(struct sk_buff *, int);
930932
int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
931933
int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
932934
int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot);
933935
void qeth_trace_features(struct qeth_card *);
936+
void qeth_close_dev(struct qeth_card *);
934937

935938
/* exports for OSN */
936939
int qeth_osn_assist(struct net_device *, void *, int);

drivers/s390/net/qeth_core_main.c

Lines changed: 84 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,27 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
6868
enum qeth_qdio_buffer_states newbufstate);
6969
static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int);
7070

71+
static struct workqueue_struct *qeth_wq;
72+
73+
static void qeth_close_dev_handler(struct work_struct *work)
74+
{
75+
struct qeth_card *card;
76+
77+
card = container_of(work, struct qeth_card, close_dev_work);
78+
QETH_CARD_TEXT(card, 2, "cldevhdl");
79+
rtnl_lock();
80+
dev_close(card->dev);
81+
rtnl_unlock();
82+
ccwgroup_set_offline(card->gdev);
83+
}
84+
85+
void qeth_close_dev(struct qeth_card *card)
86+
{
87+
QETH_CARD_TEXT(card, 2, "cldevsubm");
88+
queue_work(qeth_wq, &card->close_dev_work);
89+
}
90+
EXPORT_SYMBOL_GPL(qeth_close_dev);
91+
7192
static inline const char *qeth_get_cardname(struct qeth_card *card)
7293
{
7394
if (card->info.guestlan) {
@@ -542,11 +563,23 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
542563
} else {
543564
switch (cmd->hdr.command) {
544565
case IPA_CMD_STOPLAN:
545-
dev_warn(&card->gdev->dev,
566+
if (cmd->hdr.return_code ==
567+
IPA_RC_VEPA_TO_VEB_TRANSITION) {
568+
dev_err(&card->gdev->dev,
569+
"Interface %s is down because the "
570+
"adjacent port is no longer in "
571+
"reflective relay mode\n",
572+
QETH_CARD_IFNAME(card));
573+
qeth_close_dev(card);
574+
} else {
575+
dev_warn(&card->gdev->dev,
546576
"The link for interface %s on CHPID"
547577
" 0x%X failed\n",
548578
QETH_CARD_IFNAME(card),
549579
card->info.chpid);
580+
qeth_issue_ipa_msg(cmd,
581+
cmd->hdr.return_code, card);
582+
}
550583
card->lan_online = 0;
551584
if (card->dev && netif_carrier_ok(card->dev))
552585
netif_carrier_off(card->dev);
@@ -1416,6 +1449,7 @@ static int qeth_setup_card(struct qeth_card *card)
14161449
/* init QDIO stuff */
14171450
qeth_init_qdio_info(card);
14181451
INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work);
1452+
INIT_WORK(&card->close_dev_work, qeth_close_dev_handler);
14191453
return 0;
14201454
}
14211455

@@ -4057,6 +4091,7 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
40574091
{
40584092
struct qeth_ipa_cmd *cmd;
40594093
struct qeth_set_access_ctrl *access_ctrl_req;
4094+
int fallback = *(int *)reply->param;
40604095

40614096
QETH_CARD_TEXT(card, 4, "setaccb");
40624097

@@ -4066,85 +4101,79 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
40664101
QETH_DBF_TEXT_(SETUP, 2, "%s", card->gdev->dev.kobj.name);
40674102
QETH_DBF_TEXT_(SETUP, 2, "rc=%d",
40684103
cmd->data.setadapterparms.hdr.return_code);
4104+
if (cmd->data.setadapterparms.hdr.return_code !=
4105+
SET_ACCESS_CTRL_RC_SUCCESS)
4106+
QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%s,%d)==%d\n",
4107+
card->gdev->dev.kobj.name,
4108+
access_ctrl_req->subcmd_code,
4109+
cmd->data.setadapterparms.hdr.return_code);
40694110
switch (cmd->data.setadapterparms.hdr.return_code) {
40704111
case SET_ACCESS_CTRL_RC_SUCCESS:
4071-
case SET_ACCESS_CTRL_RC_ALREADY_NOT_ISOLATED:
4072-
case SET_ACCESS_CTRL_RC_ALREADY_ISOLATED:
4073-
{
4074-
card->options.isolation = access_ctrl_req->subcmd_code;
40754112
if (card->options.isolation == ISOLATION_MODE_NONE) {
40764113
dev_info(&card->gdev->dev,
40774114
"QDIO data connection isolation is deactivated\n");
40784115
} else {
40794116
dev_info(&card->gdev->dev,
40804117
"QDIO data connection isolation is activated\n");
40814118
}
4082-
QETH_DBF_MESSAGE(3, "OK:SET_ACCESS_CTRL(%s, %d)==%d\n",
4083-
card->gdev->dev.kobj.name,
4084-
access_ctrl_req->subcmd_code,
4085-
cmd->data.setadapterparms.hdr.return_code);
40864119
break;
4087-
}
4120+
case SET_ACCESS_CTRL_RC_ALREADY_NOT_ISOLATED:
4121+
QETH_DBF_MESSAGE(2, "%s QDIO data connection isolation already "
4122+
"deactivated\n", dev_name(&card->gdev->dev));
4123+
if (fallback)
4124+
card->options.isolation = card->options.prev_isolation;
4125+
break;
4126+
case SET_ACCESS_CTRL_RC_ALREADY_ISOLATED:
4127+
QETH_DBF_MESSAGE(2, "%s QDIO data connection isolation already"
4128+
" activated\n", dev_name(&card->gdev->dev));
4129+
if (fallback)
4130+
card->options.isolation = card->options.prev_isolation;
4131+
break;
40884132
case SET_ACCESS_CTRL_RC_NOT_SUPPORTED:
4089-
{
4090-
QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%s,%d)==%d\n",
4091-
card->gdev->dev.kobj.name,
4092-
access_ctrl_req->subcmd_code,
4093-
cmd->data.setadapterparms.hdr.return_code);
40944133
dev_err(&card->gdev->dev, "Adapter does not "
40954134
"support QDIO data connection isolation\n");
4096-
4097-
/* ensure isolation mode is "none" */
4098-
card->options.isolation = ISOLATION_MODE_NONE;
40994135
break;
4100-
}
41014136
case SET_ACCESS_CTRL_RC_NONE_SHARED_ADAPTER:
4102-
{
4103-
QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_MODE(%s,%d)==%d\n",
4104-
card->gdev->dev.kobj.name,
4105-
access_ctrl_req->subcmd_code,
4106-
cmd->data.setadapterparms.hdr.return_code);
41074137
dev_err(&card->gdev->dev,
41084138
"Adapter is dedicated. "
41094139
"QDIO data connection isolation not supported\n");
4110-
4111-
/* ensure isolation mode is "none" */
4112-
card->options.isolation = ISOLATION_MODE_NONE;
4140+
if (fallback)
4141+
card->options.isolation = card->options.prev_isolation;
41134142
break;
4114-
}
41154143
case SET_ACCESS_CTRL_RC_ACTIVE_CHECKSUM_OFF:
4116-
{
4117-
QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_MODE(%s,%d)==%d\n",
4118-
card->gdev->dev.kobj.name,
4119-
access_ctrl_req->subcmd_code,
4120-
cmd->data.setadapterparms.hdr.return_code);
41214144
dev_err(&card->gdev->dev,
41224145
"TSO does not permit QDIO data connection isolation\n");
4123-
4124-
/* ensure isolation mode is "none" */
4125-
card->options.isolation = ISOLATION_MODE_NONE;
4146+
if (fallback)
4147+
card->options.isolation = card->options.prev_isolation;
4148+
break;
4149+
case SET_ACCESS_CTRL_RC_REFLREL_UNSUPPORTED:
4150+
dev_err(&card->gdev->dev, "The adjacent switch port does not "
4151+
"support reflective relay mode\n");
4152+
if (fallback)
4153+
card->options.isolation = card->options.prev_isolation;
4154+
break;
4155+
case SET_ACCESS_CTRL_RC_REFLREL_FAILED:
4156+
dev_err(&card->gdev->dev, "The reflective relay mode cannot be "
4157+
"enabled at the adjacent switch port");
4158+
if (fallback)
4159+
card->options.isolation = card->options.prev_isolation;
4160+
break;
4161+
case SET_ACCESS_CTRL_RC_REFLREL_DEACT_FAILED:
4162+
dev_warn(&card->gdev->dev, "Turning off reflective relay mode "
4163+
"at the adjacent switch failed\n");
41264164
break;
4127-
}
41284165
default:
4129-
{
41304166
/* this should never happen */
4131-
QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_MODE(%s,%d)==%d"
4132-
"==UNKNOWN\n",
4133-
card->gdev->dev.kobj.name,
4134-
access_ctrl_req->subcmd_code,
4135-
cmd->data.setadapterparms.hdr.return_code);
4136-
4137-
/* ensure isolation mode is "none" */
4138-
card->options.isolation = ISOLATION_MODE_NONE;
4167+
if (fallback)
4168+
card->options.isolation = card->options.prev_isolation;
41394169
break;
41404170
}
4141-
}
41424171
qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
41434172
return 0;
41444173
}
41454174

41464175
static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
4147-
enum qeth_ipa_isolation_modes isolation)
4176+
enum qeth_ipa_isolation_modes isolation, int fallback)
41484177
{
41494178
int rc;
41504179
struct qeth_cmd_buffer *iob;
@@ -4164,12 +4193,12 @@ static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
41644193
access_ctrl_req->subcmd_code = isolation;
41654194

41664195
rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_set_access_ctrl_cb,
4167-
NULL);
4196+
&fallback);
41684197
QETH_DBF_TEXT_(SETUP, 2, "rc=%d", rc);
41694198
return rc;
41704199
}
41714200

4172-
int qeth_set_access_ctrl_online(struct qeth_card *card)
4201+
int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback)
41734202
{
41744203
int rc = 0;
41754204

@@ -4179,12 +4208,13 @@ int qeth_set_access_ctrl_online(struct qeth_card *card)
41794208
card->info.type == QETH_CARD_TYPE_OSX) &&
41804209
qeth_adp_supported(card, IPA_SETADP_SET_ACCESS_CONTROL)) {
41814210
rc = qeth_setadpparms_set_access_ctrl(card,
4182-
card->options.isolation);
4211+
card->options.isolation, fallback);
41834212
if (rc) {
41844213
QETH_DBF_MESSAGE(3,
41854214
"IPA(SET_ACCESS_CTRL,%s,%d) sent failed\n",
41864215
card->gdev->dev.kobj.name,
41874216
rc);
4217+
rc = -EOPNOTSUPP;
41884218
}
41894219
} else if (card->options.isolation != ISOLATION_MODE_NONE) {
41904220
card->options.isolation = ISOLATION_MODE_NONE;
@@ -5552,6 +5582,8 @@ static int __init qeth_core_init(void)
55525582
rwlock_init(&qeth_core_card_list.rwlock);
55535583
mutex_init(&qeth_mod_mutex);
55545584

5585+
qeth_wq = create_singlethread_workqueue("qeth_wq");
5586+
55555587
rc = qeth_register_dbf_views();
55565588
if (rc)
55575589
goto out_err;
@@ -5598,6 +5630,7 @@ static int __init qeth_core_init(void)
55985630

55995631
static void __exit qeth_core_exit(void)
56005632
{
5633+
destroy_workqueue(qeth_wq);
56015634
ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
56025635
ccw_driver_unregister(&qeth_ccw_driver);
56035636
kmem_cache_destroy(qeth_qdio_outbuf_cache);

drivers/s390/net/qeth_core_mpc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
204204
{IPA_RC_INVALID_SETRTG_INDICATOR, "Invalid SETRTG indicator"},
205205
{IPA_RC_MC_ADDR_ALREADY_DEFINED, "Multicast address already defined"},
206206
{IPA_RC_LAN_OFFLINE, "STRTLAN_LAN_DISABLED - LAN offline"},
207+
{IPA_RC_VEPA_TO_VEB_TRANSITION, "Adj. switch disabled port mode RR"},
207208
{IPA_RC_INVALID_IP_VERSION2, "Invalid IP version"},
208209
{IPA_RC_ENOMEM, "Memory problem"},
209210
{IPA_RC_FFFF, "Unknown Error"}

drivers/s390/net/qeth_core_mpc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ enum qeth_ipa_return_codes {
177177
IPA_RC_INVALID_SETRTG_INDICATOR = 0xe012,
178178
IPA_RC_MC_ADDR_ALREADY_DEFINED = 0xe013,
179179
IPA_RC_LAN_OFFLINE = 0xe080,
180+
IPA_RC_VEPA_TO_VEB_TRANSITION = 0xe090,
180181
IPA_RC_INVALID_IP_VERSION2 = 0xf001,
181182
IPA_RC_ENOMEM = 0xfffe,
182183
IPA_RC_FFFF = 0xffff
@@ -269,6 +270,9 @@ enum qeth_ipa_set_access_mode_rc {
269270
SET_ACCESS_CTRL_RC_ALREADY_ISOLATED = 0x0010,
270271
SET_ACCESS_CTRL_RC_NONE_SHARED_ADAPTER = 0x0014,
271272
SET_ACCESS_CTRL_RC_ACTIVE_CHECKSUM_OFF = 0x0018,
273+
SET_ACCESS_CTRL_RC_REFLREL_UNSUPPORTED = 0x0022,
274+
SET_ACCESS_CTRL_RC_REFLREL_FAILED = 0x0024,
275+
SET_ACCESS_CTRL_RC_REFLREL_DEACT_FAILED = 0x0028,
272276
};
273277

274278

@@ -386,6 +390,7 @@ struct qeth_snmp_ureq {
386390
/* SET_ACCESS_CONTROL: same format for request and reply */
387391
struct qeth_set_access_ctrl {
388392
__u32 subcmd_code;
393+
__u8 reserved[8];
389394
} __attribute__((packed));
390395

391396
struct qeth_query_oat {

drivers/s390/net/qeth_core_sys.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,10 +513,11 @@ static ssize_t qeth_dev_isolation_store(struct device *dev,
513513
rc = count;
514514

515515
/* defer IP assist if device is offline (until discipline->set_online)*/
516+
card->options.prev_isolation = card->options.isolation;
516517
card->options.isolation = isolation;
517518
if (card->state == CARD_STATE_SOFTSETUP ||
518519
card->state == CARD_STATE_UP) {
519-
int ipa_rc = qeth_set_access_ctrl_online(card);
520+
int ipa_rc = qeth_set_access_ctrl_online(card, 1);
520521
if (ipa_rc != 0)
521522
rc = ipa_rc;
522523
}

drivers/s390/net/qeth_l2_main.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,9 +1025,14 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
10251025

10261026
contin:
10271027
if ((card->info.type == QETH_CARD_TYPE_OSD) ||
1028-
(card->info.type == QETH_CARD_TYPE_OSX))
1028+
(card->info.type == QETH_CARD_TYPE_OSX)) {
10291029
/* configure isolation level */
1030-
qeth_set_access_ctrl_online(card);
1030+
rc = qeth_set_access_ctrl_online(card, 0);
1031+
if (rc) {
1032+
rc = -ENODEV;
1033+
goto out_remove;
1034+
}
1035+
}
10311036

10321037
if (card->info.type != QETH_CARD_TYPE_OSN &&
10331038
card->info.type != QETH_CARD_TYPE_OSM)
@@ -1144,12 +1149,9 @@ static int qeth_l2_recover(void *ptr)
11441149
dev_info(&card->gdev->dev,
11451150
"Device successfully recovered!\n");
11461151
else {
1147-
if (rtnl_trylock()) {
1148-
dev_close(card->dev);
1149-
rtnl_unlock();
1150-
dev_warn(&card->gdev->dev, "The qeth device driver "
1152+
qeth_close_dev(card);
1153+
dev_warn(&card->gdev->dev, "The qeth device driver "
11511154
"failed to recover an error on the device\n");
1152-
}
11531155
}
11541156
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
11551157
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);

drivers/s390/net/qeth_l3_main.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,7 +1449,8 @@ static int qeth_l3_start_ipassists(struct qeth_card *card)
14491449
{
14501450
QETH_CARD_TEXT(card, 3, "strtipas");
14511451

1452-
qeth_set_access_ctrl_online(card); /* go on*/
1452+
if (qeth_set_access_ctrl_online(card, 0))
1453+
return -EIO;
14531454
qeth_l3_start_ipa_arp_processing(card); /* go on*/
14541455
qeth_l3_start_ipa_ip_fragmentation(card); /* go on*/
14551456
qeth_l3_start_ipa_source_mac(card); /* go on*/
@@ -3388,8 +3389,10 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
33883389
QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
33893390
if (!card->options.sniffer) {
33903391
rc = qeth_l3_start_ipassists(card);
3391-
if (rc)
3392+
if (rc) {
33923393
QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
3394+
goto out_remove;
3395+
}
33933396
rc = qeth_l3_setrouting_v4(card);
33943397
if (rc)
33953398
QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc);
@@ -3511,12 +3514,9 @@ static int qeth_l3_recover(void *ptr)
35113514
dev_info(&card->gdev->dev,
35123515
"Device successfully recovered!\n");
35133516
else {
3514-
if (rtnl_trylock()) {
3515-
dev_close(card->dev);
3516-
rtnl_unlock();
3517-
dev_warn(&card->gdev->dev, "The qeth device driver "
3517+
qeth_close_dev(card);
3518+
dev_warn(&card->gdev->dev, "The qeth device driver "
35183519
"failed to recover an error on the device\n");
3519-
}
35203520
}
35213521
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
35223522
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);

0 commit comments

Comments
 (0)