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>
This commit is contained in:
commit
c7f653e0a8
4 changed files with 57 additions and 30 deletions
|
@ -829,6 +829,17 @@ struct qeth_trap_id {
|
|||
/*some helper functions*/
|
||||
#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.
|
||||
* @start: Start of the address range.
|
||||
|
@ -1029,7 +1040,7 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *,
|
|||
__u16, __u16,
|
||||
enum qeth_prot_versions);
|
||||
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_features_check(struct sk_buff *skb,
|
||||
struct net_device *dev,
|
||||
|
|
|
@ -73,9 +73,6 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue,
|
|||
struct qeth_qdio_out_buffer *buf,
|
||||
enum iucv_tx_notify notification);
|
||||
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);
|
||||
|
||||
struct workqueue_struct *qeth_wq;
|
||||
|
@ -489,6 +486,7 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
|
|||
struct qaob *aob;
|
||||
struct qeth_qdio_out_buffer *buffer;
|
||||
enum iucv_tx_notify notification;
|
||||
unsigned int i;
|
||||
|
||||
aob = (struct qaob *) phys_to_virt(phys_aob_addr);
|
||||
QETH_CARD_TEXT(card, 5, "haob");
|
||||
|
@ -513,10 +511,18 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
|
|||
qeth_notify_skbs(buffer->q, buffer, notification);
|
||||
|
||||
buffer->aob = NULL;
|
||||
qeth_clear_output_buffer(buffer->q, buffer,
|
||||
QETH_QDIO_BUF_HANDLED_DELAYED);
|
||||
/* Free dangling allocations. The attached skbs are handled by
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
@ -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, "%lx",
|
||||
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)) {
|
||||
QETH_CARD_TEXT(card, 2, "outofbuf");
|
||||
qeth_schedule_recovery(card);
|
||||
|
@ -4834,7 +4844,7 @@ int qeth_vm_request_mac(struct qeth_card *card)
|
|||
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_version = DIAG26C_VERSION2;
|
||||
request->op_code = DIAG26C_GET_MAC;
|
||||
|
@ -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 | \
|
||||
NETIF_F_IPV6_CSUM)
|
||||
/**
|
||||
* qeth_recover_features() - Restore device features after recovery
|
||||
* @dev: the recovering net_device
|
||||
*
|
||||
* Caller must hold rtnl lock.
|
||||
* qeth_enable_hw_features() - (Re-)Enable HW functions for device features
|
||||
* @dev: a net_device
|
||||
*/
|
||||
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;
|
||||
netdev_features_t features;
|
||||
|
||||
rtnl_lock();
|
||||
features = dev->features;
|
||||
/* force-off any feature that needs an IPA sequence.
|
||||
* netdev_update_features() will restart them.
|
||||
*/
|
||||
dev->features &= ~QETH_HW_FEATURES;
|
||||
netdev_update_features(dev);
|
||||
|
||||
if (features == dev->features)
|
||||
return;
|
||||
dev_warn(&card->gdev->dev,
|
||||
"Device recovery failed to restore all offload features\n");
|
||||
if (features != dev->features)
|
||||
dev_warn(&card->gdev->dev,
|
||||
"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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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;
|
||||
int rc;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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;
|
||||
int rc;
|
||||
|
||||
|
@ -501,27 +501,34 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
|
|||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
/* avoid racing against concurrent state change: */
|
||||
if (!mutex_trylock(&card->conf_mutex))
|
||||
return -EAGAIN;
|
||||
|
||||
if (!qeth_card_hw_is_reachable(card)) {
|
||||
ether_addr_copy(dev->dev_addr, addr->sa_data);
|
||||
return 0;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* don't register the same address twice */
|
||||
if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) &&
|
||||
(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
|
||||
return 0;
|
||||
goto out_unlock;
|
||||
|
||||
/* add the new address, switch over, drop the old */
|
||||
rc = qeth_l2_send_setmac(card, addr->sa_data);
|
||||
if (rc)
|
||||
return rc;
|
||||
goto out_unlock;
|
||||
ether_addr_copy(old_addr, dev->dev_addr);
|
||||
ether_addr_copy(dev->dev_addr, addr->sa_data);
|
||||
|
||||
if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)
|
||||
qeth_l2_remove_mac(card, old_addr);
|
||||
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)
|
||||
|
@ -1112,6 +1119,8 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
netif_carrier_off(card->dev);
|
||||
|
||||
qeth_set_allowed_threads(card, 0xffffffff, 0);
|
||||
|
||||
qeth_enable_hw_features(card->dev);
|
||||
if (recover_flag == CARD_STATE_RECOVER) {
|
||||
if (recovery_mode &&
|
||||
card->info.type != QETH_CARD_TYPE_OSN) {
|
||||
|
@ -1123,9 +1132,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
}
|
||||
/* this also sets saved unicast addresses */
|
||||
qeth_l2_set_rx_mode(card->dev);
|
||||
rtnl_lock();
|
||||
qeth_recover_features(card->dev);
|
||||
rtnl_unlock();
|
||||
}
|
||||
/* let user_space know that device is online */
|
||||
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
|
||||
|
|
|
@ -2662,6 +2662,8 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
netif_carrier_on(card->dev);
|
||||
else
|
||||
netif_carrier_off(card->dev);
|
||||
|
||||
qeth_enable_hw_features(card->dev);
|
||||
if (recover_flag == CARD_STATE_RECOVER) {
|
||||
rtnl_lock();
|
||||
if (recovery_mode)
|
||||
|
@ -2669,7 +2671,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
else
|
||||
dev_open(card->dev);
|
||||
qeth_l3_set_rx_mode(card->dev);
|
||||
qeth_recover_features(card->dev);
|
||||
rtnl_unlock();
|
||||
}
|
||||
qeth_trace_features(card);
|
||||
|
|
Loading…
Reference in a new issue