Skip to content

Commit bcacfcb

Browse files
julianwiedmanndavem330
authored andcommitted
s390/qeth: fix MAC address update sequence
When changing the MAC address on a L2 qeth device, current code first unregisters the old address, then registers the new one. If HW rejects the new address (or the IO fails), the device ends up with no operable address at all. Re-order the code flow so that the old address only gets dropped if the new address was registered successfully. While at it, add logic to catch some corner-cases. Signed-off-by: Julian Wiedmann <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a936b1e commit bcacfcb

File tree

1 file changed

+31
-24
lines changed

1 file changed

+31
-24
lines changed

drivers/s390/net/qeth_l2_main.c

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,10 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
121121
QETH_CARD_TEXT(card, 2, "L2Setmac");
122122
rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC);
123123
if (rc == 0) {
124-
card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
125-
ether_addr_copy(card->dev->dev_addr, mac);
126124
dev_info(&card->gdev->dev,
127-
"MAC address %pM successfully registered on device %s\n",
128-
card->dev->dev_addr, card->dev->name);
125+
"MAC address %pM successfully registered on device %s\n",
126+
mac, card->dev->name);
129127
} else {
130-
card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
131128
switch (rc) {
132129
case -EEXIST:
133130
dev_warn(&card->gdev->dev,
@@ -142,19 +139,6 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
142139
return rc;
143140
}
144141

145-
static int qeth_l2_send_delmac(struct qeth_card *card, __u8 *mac)
146-
{
147-
int rc;
148-
149-
QETH_CARD_TEXT(card, 2, "L2Delmac");
150-
if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
151-
return 0;
152-
rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELVMAC);
153-
if (rc == 0)
154-
card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
155-
return rc;
156-
}
157-
158142
static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac)
159143
{
160144
enum qeth_ipa_cmds cmd = is_multicast_ether_addr_64bits(mac) ?
@@ -519,6 +503,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
519503
{
520504
struct sockaddr *addr = p;
521505
struct qeth_card *card = dev->ml_priv;
506+
u8 old_addr[ETH_ALEN];
522507
int rc = 0;
523508

524509
QETH_CARD_TEXT(card, 3, "setmac");
@@ -530,14 +515,35 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
530515
return -EOPNOTSUPP;
531516
}
532517
QETH_CARD_HEX(card, 3, addr->sa_data, ETH_ALEN);
518+
if (!is_valid_ether_addr(addr->sa_data))
519+
return -EADDRNOTAVAIL;
520+
533521
if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
534522
QETH_CARD_TEXT(card, 3, "setmcREC");
535523
return -ERESTARTSYS;
536524
}
537-
rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
538-
if (!rc || (rc == -ENOENT))
539-
rc = qeth_l2_send_setmac(card, addr->sa_data);
540-
return rc ? -EINVAL : 0;
525+
526+
if (!qeth_card_hw_is_reachable(card)) {
527+
ether_addr_copy(dev->dev_addr, addr->sa_data);
528+
return 0;
529+
}
530+
531+
/* don't register the same address twice */
532+
if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) &&
533+
(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
534+
return 0;
535+
536+
/* add the new address, switch over, drop the old */
537+
rc = qeth_l2_send_setmac(card, addr->sa_data);
538+
if (rc)
539+
return rc;
540+
ether_addr_copy(old_addr, dev->dev_addr);
541+
ether_addr_copy(dev->dev_addr, addr->sa_data);
542+
543+
if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)
544+
qeth_l2_remove_mac(card, old_addr);
545+
card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
546+
return 0;
541547
}
542548

543549
static void qeth_promisc_to_bridge(struct qeth_card *card)
@@ -1067,8 +1073,9 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
10671073
goto out_remove;
10681074
}
10691075

1070-
if (card->info.type != QETH_CARD_TYPE_OSN)
1071-
qeth_l2_send_setmac(card, &card->dev->dev_addr[0]);
1076+
if (card->info.type != QETH_CARD_TYPE_OSN &&
1077+
!qeth_l2_send_setmac(card, card->dev->dev_addr))
1078+
card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
10721079

10731080
if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
10741081
if (card->info.hwtrap &&

0 commit comments

Comments
 (0)