Commit c7f653e0 authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents bc800e8b d025da9e
...@@ -829,6 +829,17 @@ struct qeth_trap_id { ...@@ -829,6 +829,17 @@ struct qeth_trap_id {
/*some helper functions*/ /*some helper functions*/
#define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "") #define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "")
static inline void qeth_scrub_qdio_buffer(struct qdio_buffer *buf,
unsigned int elements)
{
unsigned int i;
for (i = 0; i < elements; i++)
memset(&buf->element[i], 0, sizeof(struct qdio_buffer_element));
buf->element[14].sflags = 0;
buf->element[15].sflags = 0;
}
/** /**
* qeth_get_elements_for_range() - find number of SBALEs to cover range. * qeth_get_elements_for_range() - find number of SBALEs to cover range.
* @start: Start of the address range. * @start: Start of the address range.
...@@ -1029,7 +1040,7 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *, ...@@ -1029,7 +1040,7 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *,
__u16, __u16, __u16, __u16,
enum qeth_prot_versions); enum qeth_prot_versions);
int qeth_set_features(struct net_device *, netdev_features_t); int qeth_set_features(struct net_device *, netdev_features_t);
void qeth_recover_features(struct net_device *dev); void qeth_enable_hw_features(struct net_device *dev);
netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t); netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t);
netdev_features_t qeth_features_check(struct sk_buff *skb, netdev_features_t qeth_features_check(struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
......
...@@ -73,9 +73,6 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue, ...@@ -73,9 +73,6 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue,
struct qeth_qdio_out_buffer *buf, struct qeth_qdio_out_buffer *buf,
enum iucv_tx_notify notification); enum iucv_tx_notify notification);
static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf); static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf);
static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
struct qeth_qdio_out_buffer *buf,
enum qeth_qdio_buffer_states newbufstate);
static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int); static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int);
struct workqueue_struct *qeth_wq; struct workqueue_struct *qeth_wq;
...@@ -489,6 +486,7 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, ...@@ -489,6 +486,7 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
struct qaob *aob; struct qaob *aob;
struct qeth_qdio_out_buffer *buffer; struct qeth_qdio_out_buffer *buffer;
enum iucv_tx_notify notification; enum iucv_tx_notify notification;
unsigned int i;
aob = (struct qaob *) phys_to_virt(phys_aob_addr); aob = (struct qaob *) phys_to_virt(phys_aob_addr);
QETH_CARD_TEXT(card, 5, "haob"); QETH_CARD_TEXT(card, 5, "haob");
...@@ -513,10 +511,18 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, ...@@ -513,10 +511,18 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
qeth_notify_skbs(buffer->q, buffer, notification); qeth_notify_skbs(buffer->q, buffer, notification);
buffer->aob = NULL; buffer->aob = NULL;
qeth_clear_output_buffer(buffer->q, buffer, /* Free dangling allocations. The attached skbs are handled by
QETH_QDIO_BUF_HANDLED_DELAYED); * qeth_cleanup_handled_pending().
*/
for (i = 0;
i < aob->sb_count && i < QETH_MAX_BUFFER_ELEMENTS(card);
i++) {
if (aob->sba[i] && buffer->is_header[i])
kmem_cache_free(qeth_core_header_cache,
(void *) aob->sba[i]);
}
atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED);
/* from here on: do not touch buffer anymore */
qdio_release_aob(aob); qdio_release_aob(aob);
} }
...@@ -3759,6 +3765,10 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev, ...@@ -3759,6 +3765,10 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev,
QETH_CARD_TEXT(queue->card, 5, "aob"); QETH_CARD_TEXT(queue->card, 5, "aob");
QETH_CARD_TEXT_(queue->card, 5, "%lx", QETH_CARD_TEXT_(queue->card, 5, "%lx",
virt_to_phys(buffer->aob)); virt_to_phys(buffer->aob));
/* prepare the queue slot for re-use: */
qeth_scrub_qdio_buffer(buffer->buffer,
QETH_MAX_BUFFER_ELEMENTS(card));
if (qeth_init_qdio_out_buf(queue, bidx)) { if (qeth_init_qdio_out_buf(queue, bidx)) {
QETH_CARD_TEXT(card, 2, "outofbuf"); QETH_CARD_TEXT(card, 2, "outofbuf");
qeth_schedule_recovery(card); qeth_schedule_recovery(card);
...@@ -4834,7 +4844,7 @@ int qeth_vm_request_mac(struct qeth_card *card) ...@@ -4834,7 +4844,7 @@ int qeth_vm_request_mac(struct qeth_card *card)
goto out; goto out;
} }
ccw_device_get_id(CARD_RDEV(card), &id); ccw_device_get_id(CARD_DDEV(card), &id);
request->resp_buf_len = sizeof(*response); request->resp_buf_len = sizeof(*response);
request->resp_version = DIAG26C_VERSION2; request->resp_version = DIAG26C_VERSION2;
request->op_code = DIAG26C_GET_MAC; request->op_code = DIAG26C_GET_MAC;
...@@ -6459,28 +6469,27 @@ static int qeth_set_ipa_rx_csum(struct qeth_card *card, bool on) ...@@ -6459,28 +6469,27 @@ static int qeth_set_ipa_rx_csum(struct qeth_card *card, bool on)
#define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO | \ #define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO | \
NETIF_F_IPV6_CSUM) NETIF_F_IPV6_CSUM)
/** /**
* qeth_recover_features() - Restore device features after recovery * qeth_enable_hw_features() - (Re-)Enable HW functions for device features
* @dev: the recovering net_device * @dev: a net_device
*
* Caller must hold rtnl lock.
*/ */
void qeth_recover_features(struct net_device *dev) void qeth_enable_hw_features(struct net_device *dev)
{ {
netdev_features_t features = dev->features;
struct qeth_card *card = dev->ml_priv; struct qeth_card *card = dev->ml_priv;
netdev_features_t features;
rtnl_lock();
features = dev->features;
/* force-off any feature that needs an IPA sequence. /* force-off any feature that needs an IPA sequence.
* netdev_update_features() will restart them. * netdev_update_features() will restart them.
*/ */
dev->features &= ~QETH_HW_FEATURES; dev->features &= ~QETH_HW_FEATURES;
netdev_update_features(dev); netdev_update_features(dev);
if (features != dev->features)
if (features == dev->features)
return;
dev_warn(&card->gdev->dev, dev_warn(&card->gdev->dev,
"Device recovery failed to restore all offload features\n"); "Device recovery failed to restore all offload features\n");
rtnl_unlock();
} }
EXPORT_SYMBOL_GPL(qeth_recover_features); EXPORT_SYMBOL_GPL(qeth_enable_hw_features);
int qeth_set_features(struct net_device *dev, netdev_features_t features) int qeth_set_features(struct net_device *dev, netdev_features_t features)
{ {
......
...@@ -140,7 +140,7 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac) ...@@ -140,7 +140,7 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac) static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac)
{ {
enum qeth_ipa_cmds cmd = is_multicast_ether_addr_64bits(mac) ? enum qeth_ipa_cmds cmd = is_multicast_ether_addr(mac) ?
IPA_CMD_SETGMAC : IPA_CMD_SETVMAC; IPA_CMD_SETGMAC : IPA_CMD_SETVMAC;
int rc; int rc;
...@@ -157,7 +157,7 @@ static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac) ...@@ -157,7 +157,7 @@ static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac)
static int qeth_l2_remove_mac(struct qeth_card *card, u8 *mac) static int qeth_l2_remove_mac(struct qeth_card *card, u8 *mac)
{ {
enum qeth_ipa_cmds cmd = is_multicast_ether_addr_64bits(mac) ? enum qeth_ipa_cmds cmd = is_multicast_ether_addr(mac) ?
IPA_CMD_DELGMAC : IPA_CMD_DELVMAC; IPA_CMD_DELGMAC : IPA_CMD_DELVMAC;
int rc; int rc;
...@@ -501,27 +501,34 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) ...@@ -501,27 +501,34 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
return -ERESTARTSYS; return -ERESTARTSYS;
} }
/* avoid racing against concurrent state change: */
if (!mutex_trylock(&card->conf_mutex))
return -EAGAIN;
if (!qeth_card_hw_is_reachable(card)) { if (!qeth_card_hw_is_reachable(card)) {
ether_addr_copy(dev->dev_addr, addr->sa_data); ether_addr_copy(dev->dev_addr, addr->sa_data);
return 0; goto out_unlock;
} }
/* don't register the same address twice */ /* don't register the same address twice */
if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) && if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) &&
(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)) (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
return 0; goto out_unlock;
/* add the new address, switch over, drop the old */ /* add the new address, switch over, drop the old */
rc = qeth_l2_send_setmac(card, addr->sa_data); rc = qeth_l2_send_setmac(card, addr->sa_data);
if (rc) if (rc)
return rc; goto out_unlock;
ether_addr_copy(old_addr, dev->dev_addr); ether_addr_copy(old_addr, dev->dev_addr);
ether_addr_copy(dev->dev_addr, addr->sa_data); ether_addr_copy(dev->dev_addr, addr->sa_data);
if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED) if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)
qeth_l2_remove_mac(card, old_addr); qeth_l2_remove_mac(card, old_addr);
card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
return 0;
out_unlock:
mutex_unlock(&card->conf_mutex);
return rc;
} }
static void qeth_promisc_to_bridge(struct qeth_card *card) 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,6 +1119,8 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
netif_carrier_off(card->dev); netif_carrier_off(card->dev);
qeth_set_allowed_threads(card, 0xffffffff, 0); qeth_set_allowed_threads(card, 0xffffffff, 0);
qeth_enable_hw_features(card->dev);
if (recover_flag == CARD_STATE_RECOVER) { if (recover_flag == CARD_STATE_RECOVER) {
if (recovery_mode && if (recovery_mode &&
card->info.type != QETH_CARD_TYPE_OSN) { 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,9 +1132,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
} }
/* this also sets saved unicast addresses */ /* this also sets saved unicast addresses */
qeth_l2_set_rx_mode(card->dev); qeth_l2_set_rx_mode(card->dev);
rtnl_lock();
qeth_recover_features(card->dev);
rtnl_unlock();
} }
/* let user_space know that device is online */ /* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
......
...@@ -2662,6 +2662,8 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -2662,6 +2662,8 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
netif_carrier_on(card->dev); netif_carrier_on(card->dev);
else else
netif_carrier_off(card->dev); netif_carrier_off(card->dev);
qeth_enable_hw_features(card->dev);
if (recover_flag == CARD_STATE_RECOVER) { if (recover_flag == CARD_STATE_RECOVER) {
rtnl_lock(); rtnl_lock();
if (recovery_mode) if (recovery_mode)
...@@ -2669,7 +2671,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -2669,7 +2671,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
else else
dev_open(card->dev); dev_open(card->dev);
qeth_l3_set_rx_mode(card->dev); qeth_l3_set_rx_mode(card->dev);
qeth_recover_features(card->dev);
rtnl_unlock(); rtnl_unlock();
} }
qeth_trace_features(card); qeth_trace_features(card);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment