diff options
author | David S. Miller <davem@davemloft.net> | 2018-06-30 08:19:55 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-06-30 08:19:55 -0400 |
commit | c7f653e0a8cf4e4a9951324f9b831cf88d813e48 (patch) | |
tree | cf29e525b6b7740ca89aabed8abbdbe2f052f3a0 | |
parent | bc800e8b39bad60ccdb83be828da63af71ab87b3 (diff) | |
parent | d025da9eb1e48d3e5f2a2ff13ac5ac536ba4be43 (diff) |
Merge branch 's390-qeth-fixes'
Julian Wiedmann says:
====================
s390/qeth: fixes 2018-06-29
please apply a few qeth fixes for -net and your 4.17 stable queue.
Patches 1-3 fix several issues wrt to MAC address management that were
introduced during the 4.17 cycle.
Patch 4 tackles a long-standing issue with busy multi-connection workloads
on devices in af_iucv mode.
Patch 5 makes sure to re-enable all active HW offloads, after a card was
previously set offline and thus lost its HW context.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/s390/net/qeth_core.h | 13 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 47 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 24 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 3 |
4 files changed, 57 insertions, 30 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 2a5fec55bf60..a246a618f9a4 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h | |||
@@ -829,6 +829,17 @@ struct qeth_trap_id { | |||
829 | /*some helper functions*/ | 829 | /*some helper functions*/ |
830 | #define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "") | 830 | #define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "") |
831 | 831 | ||
832 | static inline void qeth_scrub_qdio_buffer(struct qdio_buffer *buf, | ||
833 | unsigned int elements) | ||
834 | { | ||
835 | unsigned int i; | ||
836 | |||
837 | for (i = 0; i < elements; i++) | ||
838 | memset(&buf->element[i], 0, sizeof(struct qdio_buffer_element)); | ||
839 | buf->element[14].sflags = 0; | ||
840 | buf->element[15].sflags = 0; | ||
841 | } | ||
842 | |||
832 | /** | 843 | /** |
833 | * qeth_get_elements_for_range() - find number of SBALEs to cover range. | 844 | * qeth_get_elements_for_range() - find number of SBALEs to cover range. |
834 | * @start: Start of the address range. | 845 | * @start: Start of the address range. |
@@ -1029,7 +1040,7 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *, | |||
1029 | __u16, __u16, | 1040 | __u16, __u16, |
1030 | enum qeth_prot_versions); | 1041 | enum qeth_prot_versions); |
1031 | int qeth_set_features(struct net_device *, netdev_features_t); | 1042 | int qeth_set_features(struct net_device *, netdev_features_t); |
1032 | void qeth_recover_features(struct net_device *dev); | 1043 | void qeth_enable_hw_features(struct net_device *dev); |
1033 | netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t); | 1044 | netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t); |
1034 | netdev_features_t qeth_features_check(struct sk_buff *skb, | 1045 | netdev_features_t qeth_features_check(struct sk_buff *skb, |
1035 | struct net_device *dev, | 1046 | struct net_device *dev, |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 8e1474f1ffac..d01ac29fd986 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -73,9 +73,6 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue, | |||
73 | struct qeth_qdio_out_buffer *buf, | 73 | struct qeth_qdio_out_buffer *buf, |
74 | enum iucv_tx_notify notification); | 74 | enum iucv_tx_notify notification); |
75 | static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf); | 75 | static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf); |
76 | static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, | ||
77 | struct qeth_qdio_out_buffer *buf, | ||
78 | enum qeth_qdio_buffer_states newbufstate); | ||
79 | static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int); | 76 | static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int); |
80 | 77 | ||
81 | struct workqueue_struct *qeth_wq; | 78 | struct workqueue_struct *qeth_wq; |
@@ -489,6 +486,7 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, | |||
489 | struct qaob *aob; | 486 | struct qaob *aob; |
490 | struct qeth_qdio_out_buffer *buffer; | 487 | struct qeth_qdio_out_buffer *buffer; |
491 | enum iucv_tx_notify notification; | 488 | enum iucv_tx_notify notification; |
489 | unsigned int i; | ||
492 | 490 | ||
493 | aob = (struct qaob *) phys_to_virt(phys_aob_addr); | 491 | aob = (struct qaob *) phys_to_virt(phys_aob_addr); |
494 | QETH_CARD_TEXT(card, 5, "haob"); | 492 | QETH_CARD_TEXT(card, 5, "haob"); |
@@ -513,10 +511,18 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, | |||
513 | qeth_notify_skbs(buffer->q, buffer, notification); | 511 | qeth_notify_skbs(buffer->q, buffer, notification); |
514 | 512 | ||
515 | buffer->aob = NULL; | 513 | buffer->aob = NULL; |
516 | qeth_clear_output_buffer(buffer->q, buffer, | 514 | /* Free dangling allocations. The attached skbs are handled by |
517 | QETH_QDIO_BUF_HANDLED_DELAYED); | 515 | * qeth_cleanup_handled_pending(). |
516 | */ | ||
517 | for (i = 0; | ||
518 | i < aob->sb_count && i < QETH_MAX_BUFFER_ELEMENTS(card); | ||
519 | i++) { | ||
520 | if (aob->sba[i] && buffer->is_header[i]) | ||
521 | kmem_cache_free(qeth_core_header_cache, | ||
522 | (void *) aob->sba[i]); | ||
523 | } | ||
524 | atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED); | ||
518 | 525 | ||
519 | /* from here on: do not touch buffer anymore */ | ||
520 | qdio_release_aob(aob); | 526 | qdio_release_aob(aob); |
521 | } | 527 | } |
522 | 528 | ||
@@ -3759,6 +3765,10 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev, | |||
3759 | QETH_CARD_TEXT(queue->card, 5, "aob"); | 3765 | QETH_CARD_TEXT(queue->card, 5, "aob"); |
3760 | QETH_CARD_TEXT_(queue->card, 5, "%lx", | 3766 | QETH_CARD_TEXT_(queue->card, 5, "%lx", |
3761 | virt_to_phys(buffer->aob)); | 3767 | virt_to_phys(buffer->aob)); |
3768 | |||
3769 | /* prepare the queue slot for re-use: */ | ||
3770 | qeth_scrub_qdio_buffer(buffer->buffer, | ||
3771 | QETH_MAX_BUFFER_ELEMENTS(card)); | ||
3762 | if (qeth_init_qdio_out_buf(queue, bidx)) { | 3772 | if (qeth_init_qdio_out_buf(queue, bidx)) { |
3763 | QETH_CARD_TEXT(card, 2, "outofbuf"); | 3773 | QETH_CARD_TEXT(card, 2, "outofbuf"); |
3764 | qeth_schedule_recovery(card); | 3774 | qeth_schedule_recovery(card); |
@@ -4834,7 +4844,7 @@ int qeth_vm_request_mac(struct qeth_card *card) | |||
4834 | goto out; | 4844 | goto out; |
4835 | } | 4845 | } |
4836 | 4846 | ||
4837 | ccw_device_get_id(CARD_RDEV(card), &id); | 4847 | ccw_device_get_id(CARD_DDEV(card), &id); |
4838 | request->resp_buf_len = sizeof(*response); | 4848 | request->resp_buf_len = sizeof(*response); |
4839 | request->resp_version = DIAG26C_VERSION2; | 4849 | request->resp_version = DIAG26C_VERSION2; |
4840 | request->op_code = DIAG26C_GET_MAC; | 4850 | request->op_code = DIAG26C_GET_MAC; |
@@ -6459,28 +6469,27 @@ static int qeth_set_ipa_rx_csum(struct qeth_card *card, bool on) | |||
6459 | #define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO | \ | 6469 | #define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO | \ |
6460 | NETIF_F_IPV6_CSUM) | 6470 | NETIF_F_IPV6_CSUM) |
6461 | /** | 6471 | /** |
6462 | * qeth_recover_features() - Restore device features after recovery | 6472 | * qeth_enable_hw_features() - (Re-)Enable HW functions for device features |
6463 | * @dev: the recovering net_device | 6473 | * @dev: a net_device |
6464 | * | ||
6465 | * Caller must hold rtnl lock. | ||
6466 | */ | 6474 | */ |
6467 | void qeth_recover_features(struct net_device *dev) | 6475 | void qeth_enable_hw_features(struct net_device *dev) |
6468 | { | 6476 | { |
6469 | netdev_features_t features = dev->features; | ||
6470 | struct qeth_card *card = dev->ml_priv; | 6477 | struct qeth_card *card = dev->ml_priv; |
6478 | netdev_features_t features; | ||
6471 | 6479 | ||
6480 | rtnl_lock(); | ||
6481 | features = dev->features; | ||
6472 | /* force-off any feature that needs an IPA sequence. | 6482 | /* force-off any feature that needs an IPA sequence. |
6473 | * netdev_update_features() will restart them. | 6483 | * netdev_update_features() will restart them. |
6474 | */ | 6484 | */ |
6475 | dev->features &= ~QETH_HW_FEATURES; | 6485 | dev->features &= ~QETH_HW_FEATURES; |
6476 | netdev_update_features(dev); | 6486 | netdev_update_features(dev); |
6477 | 6487 | if (features != dev->features) | |
6478 | if (features == dev->features) | 6488 | dev_warn(&card->gdev->dev, |
6479 | return; | 6489 | "Device recovery failed to restore all offload features\n"); |
6480 | dev_warn(&card->gdev->dev, | 6490 | rtnl_unlock(); |
6481 | "Device recovery failed to restore all offload features\n"); | ||
6482 | } | 6491 | } |
6483 | EXPORT_SYMBOL_GPL(qeth_recover_features); | 6492 | EXPORT_SYMBOL_GPL(qeth_enable_hw_features); |
6484 | 6493 | ||
6485 | int qeth_set_features(struct net_device *dev, netdev_features_t features) | 6494 | int qeth_set_features(struct net_device *dev, netdev_features_t features) |
6486 | { | 6495 | { |
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index a7cb37da6a21..2487f0aeb165 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c | |||
@@ -140,7 +140,7 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac) | |||
140 | 140 | ||
141 | static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac) | 141 | static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac) |
142 | { | 142 | { |
143 | enum qeth_ipa_cmds cmd = is_multicast_ether_addr_64bits(mac) ? | 143 | enum qeth_ipa_cmds cmd = is_multicast_ether_addr(mac) ? |
144 | IPA_CMD_SETGMAC : IPA_CMD_SETVMAC; | 144 | IPA_CMD_SETGMAC : IPA_CMD_SETVMAC; |
145 | int rc; | 145 | int rc; |
146 | 146 | ||
@@ -157,7 +157,7 @@ static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac) | |||
157 | 157 | ||
158 | static int qeth_l2_remove_mac(struct qeth_card *card, u8 *mac) | 158 | static int qeth_l2_remove_mac(struct qeth_card *card, u8 *mac) |
159 | { | 159 | { |
160 | enum qeth_ipa_cmds cmd = is_multicast_ether_addr_64bits(mac) ? | 160 | enum qeth_ipa_cmds cmd = is_multicast_ether_addr(mac) ? |
161 | IPA_CMD_DELGMAC : IPA_CMD_DELVMAC; | 161 | IPA_CMD_DELGMAC : IPA_CMD_DELVMAC; |
162 | int rc; | 162 | int rc; |
163 | 163 | ||
@@ -501,27 +501,34 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) | |||
501 | return -ERESTARTSYS; | 501 | return -ERESTARTSYS; |
502 | } | 502 | } |
503 | 503 | ||
504 | /* avoid racing against concurrent state change: */ | ||
505 | if (!mutex_trylock(&card->conf_mutex)) | ||
506 | return -EAGAIN; | ||
507 | |||
504 | if (!qeth_card_hw_is_reachable(card)) { | 508 | if (!qeth_card_hw_is_reachable(card)) { |
505 | ether_addr_copy(dev->dev_addr, addr->sa_data); | 509 | ether_addr_copy(dev->dev_addr, addr->sa_data); |
506 | return 0; | 510 | goto out_unlock; |
507 | } | 511 | } |
508 | 512 | ||
509 | /* don't register the same address twice */ | 513 | /* don't register the same address twice */ |
510 | if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) && | 514 | if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) && |
511 | (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)) | 515 | (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)) |
512 | return 0; | 516 | goto out_unlock; |
513 | 517 | ||
514 | /* add the new address, switch over, drop the old */ | 518 | /* add the new address, switch over, drop the old */ |
515 | rc = qeth_l2_send_setmac(card, addr->sa_data); | 519 | rc = qeth_l2_send_setmac(card, addr->sa_data); |
516 | if (rc) | 520 | if (rc) |
517 | return rc; | 521 | goto out_unlock; |
518 | ether_addr_copy(old_addr, dev->dev_addr); | 522 | ether_addr_copy(old_addr, dev->dev_addr); |
519 | ether_addr_copy(dev->dev_addr, addr->sa_data); | 523 | ether_addr_copy(dev->dev_addr, addr->sa_data); |
520 | 524 | ||
521 | if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED) | 525 | if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED) |
522 | qeth_l2_remove_mac(card, old_addr); | 526 | qeth_l2_remove_mac(card, old_addr); |
523 | card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; | 527 | card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; |
524 | return 0; | 528 | |
529 | out_unlock: | ||
530 | mutex_unlock(&card->conf_mutex); | ||
531 | return rc; | ||
525 | } | 532 | } |
526 | 533 | ||
527 | static void qeth_promisc_to_bridge(struct qeth_card *card) | 534 | static void qeth_promisc_to_bridge(struct qeth_card *card) |
@@ -1112,6 +1119,8 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
1112 | netif_carrier_off(card->dev); | 1119 | netif_carrier_off(card->dev); |
1113 | 1120 | ||
1114 | qeth_set_allowed_threads(card, 0xffffffff, 0); | 1121 | qeth_set_allowed_threads(card, 0xffffffff, 0); |
1122 | |||
1123 | qeth_enable_hw_features(card->dev); | ||
1115 | if (recover_flag == CARD_STATE_RECOVER) { | 1124 | if (recover_flag == CARD_STATE_RECOVER) { |
1116 | if (recovery_mode && | 1125 | if (recovery_mode && |
1117 | card->info.type != QETH_CARD_TYPE_OSN) { | 1126 | card->info.type != QETH_CARD_TYPE_OSN) { |
@@ -1123,9 +1132,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
1123 | } | 1132 | } |
1124 | /* this also sets saved unicast addresses */ | 1133 | /* this also sets saved unicast addresses */ |
1125 | qeth_l2_set_rx_mode(card->dev); | 1134 | qeth_l2_set_rx_mode(card->dev); |
1126 | rtnl_lock(); | ||
1127 | qeth_recover_features(card->dev); | ||
1128 | rtnl_unlock(); | ||
1129 | } | 1135 | } |
1130 | /* let user_space know that device is online */ | 1136 | /* let user_space know that device is online */ |
1131 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); | 1137 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); |
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index e7fa479adf47..5905dc63e256 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -2662,6 +2662,8 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
2662 | netif_carrier_on(card->dev); | 2662 | netif_carrier_on(card->dev); |
2663 | else | 2663 | else |
2664 | netif_carrier_off(card->dev); | 2664 | netif_carrier_off(card->dev); |
2665 | |||
2666 | qeth_enable_hw_features(card->dev); | ||
2665 | if (recover_flag == CARD_STATE_RECOVER) { | 2667 | if (recover_flag == CARD_STATE_RECOVER) { |
2666 | rtnl_lock(); | 2668 | rtnl_lock(); |
2667 | if (recovery_mode) | 2669 | if (recovery_mode) |
@@ -2669,7 +2671,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
2669 | else | 2671 | else |
2670 | dev_open(card->dev); | 2672 | dev_open(card->dev); |
2671 | qeth_l3_set_rx_mode(card->dev); | 2673 | qeth_l3_set_rx_mode(card->dev); |
2672 | qeth_recover_features(card->dev); | ||
2673 | rtnl_unlock(); | 2674 | rtnl_unlock(); |
2674 | } | 2675 | } |
2675 | qeth_trace_features(card); | 2676 | qeth_trace_features(card); |