From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A85F8C43381 for ; Thu, 28 Mar 2019 15:40:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 756CB2183F for ; Thu, 28 Mar 2019 15:40:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727089AbfC1Pjp (ORCPT ); Thu, 28 Mar 2019 11:39:45 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:49064 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726520AbfC1Pjn (ORCPT ); Thu, 28 Mar 2019 11:39:43 -0400 Received: from pps.filterd (m0098413.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x2SFUil4079238 for ; Thu, 28 Mar 2019 11:39:41 -0400 Received: from e06smtp07.uk.ibm.com (e06smtp07.uk.ibm.com [195.75.94.103]) by mx0b-001b2d01.pphosted.com with ESMTP id 2rgykdng1s-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Thu, 28 Mar 2019 11:39:41 -0400 Received: from localhost by e06smtp07.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 28 Mar 2019 15:39:39 -0000 Received: from b06cxnps4074.portsmouth.uk.ibm.com (9.149.109.196) by e06smtp07.uk.ibm.com (192.168.101.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Thu, 28 Mar 2019 15:39:37 -0000 Received: from d06av25.portsmouth.uk.ibm.com (d06av25.portsmouth.uk.ibm.com [9.149.105.61]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id x2SFdafo44957812 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 28 Mar 2019 15:39:36 GMT Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 14DB811C04A; Thu, 28 Mar 2019 15:39:36 +0000 (GMT) Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id BCD4211C04C; Thu, 28 Mar 2019 15:39:35 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av25.portsmouth.uk.ibm.com (Postfix) with ESMTPS; Thu, 28 Mar 2019 15:39:35 +0000 (GMT) From: Julian Wiedmann To: David Miller Cc: , , Martin Schwidefsky , Heiko Carstens , Stefan Raspl , Ursula Braun , Julian Wiedmann Subject: [PATCH net-next 01/10] s390/qeth: defer RX modesetting Date: Thu, 28 Mar 2019 16:39:19 +0100 X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190328153928.87692-1-jwi@linux.ibm.com> References: <20190328153928.87692-1-jwi@linux.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 19032815-0028-0000-0000-00000359A5CA X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 19032815-0029-0000-0000-000024186706 Message-Id: <20190328153928.87692-2-jwi@linux.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-03-28_09:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1903280104 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org .ndo_set_rx_mode gets called in process context, but while holding the addr_list spinlock. Which means we currently can't sleep while re-programming the HW, and need to poll for IO completion. That's bad, in particular since receiving the cmd response can fail silently and we're then polling until the timeout hits. As a first step towards eliminating the IO completion polling, run the RX modeset from a work element and only take the addr_list lock while updating the RX mode address cache. Signed-off-by: Julian Wiedmann --- drivers/s390/net/qeth_core.h | 1 + drivers/s390/net/qeth_l2_main.c | 22 +++++++++++++++++---- drivers/s390/net/qeth_l3_main.c | 42 ++++++++++++++++++++++++++++------------- 3 files changed, 48 insertions(+), 17 deletions(-) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index c851cf6e01c4..c3cf992ca985 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -780,6 +780,7 @@ struct qeth_card { DECLARE_HASHTABLE(mac_htable, 4); DECLARE_HASHTABLE(ip_htable, 4); DECLARE_HASHTABLE(ip_mc_htable, 4); + struct work_struct rx_mode_work; struct work_struct kernel_thread_starter; spinlock_t thread_mask_lock; unsigned long thread_start_mask; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index c3067fd3bd9e..437a399d5557 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -149,7 +149,7 @@ static int qeth_l2_remove_mac(struct qeth_card *card, u8 *mac) return rc; } -static void qeth_l2_del_all_macs(struct qeth_card *card) +static void qeth_l2_drain_rx_mode_cache(struct qeth_card *card) { struct qeth_mac *mac; struct hlist_node *tmp; @@ -292,8 +292,10 @@ static void qeth_l2_stop_card(struct qeth_card *card) qeth_set_allowed_threads(card, 0, 1); + cancel_work_sync(&card->rx_mode_work); + qeth_l2_drain_rx_mode_cache(card); + if (card->state == CARD_STATE_SOFTSETUP) { - qeth_l2_del_all_macs(card); qeth_clear_ipacmd_list(card); card->state = CARD_STATE_HARDSETUP; } @@ -515,9 +517,11 @@ static void qeth_l2_add_mac(struct qeth_card *card, struct netdev_hw_addr *ha) hash_add(card->mac_htable, &mac->hnode, mac_hash); } -static void qeth_l2_set_rx_mode(struct net_device *dev) +static void qeth_l2_rx_mode_work(struct work_struct *work) { - struct qeth_card *card = dev->ml_priv; + struct qeth_card *card = container_of(work, struct qeth_card, + rx_mode_work); + struct net_device *dev = card->dev; struct netdev_hw_addr *ha; struct qeth_mac *mac; struct hlist_node *tmp; @@ -528,10 +532,12 @@ static void qeth_l2_set_rx_mode(struct net_device *dev) spin_lock_bh(&card->mclock); + netif_addr_lock_bh(dev); netdev_for_each_mc_addr(ha, dev) qeth_l2_add_mac(card, ha); netdev_for_each_uc_addr(ha, dev) qeth_l2_add_mac(card, ha); + netif_addr_unlock_bh(dev); hash_for_each_safe(card->mac_htable, i, tmp, mac, hnode) { switch (mac->disp_flag) { @@ -653,6 +659,7 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev) } hash_init(card->mac_htable); + INIT_WORK(&card->rx_mode_work, qeth_l2_rx_mode_work); return 0; } @@ -673,6 +680,13 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) unregister_netdev(card->dev); } +static void qeth_l2_set_rx_mode(struct net_device *dev) +{ + struct qeth_card *card = dev->ml_priv; + + schedule_work(&card->rx_mode_work); +} + static const struct net_device_ops qeth_l2_netdev_ops = { .ndo_open = qeth_open, .ndo_stop = qeth_stop, diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 53712cf26406..b6df38f092e6 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -268,6 +268,20 @@ static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) return rc; } +static void qeth_l3_drain_rx_mode_cache(struct qeth_card *card) +{ + struct qeth_ipaddr *addr; + struct hlist_node *tmp; + int i; + + spin_lock_bh(&card->mclock); + hash_for_each_safe(card->ip_mc_htable, i, tmp, addr, hnode) { + hash_del(&addr->hnode); + kfree(addr); + } + spin_unlock_bh(&card->mclock); +} + static void qeth_l3_clear_ip_htable(struct qeth_card *card, int recover) { struct qeth_ipaddr *addr; @@ -288,18 +302,8 @@ static void qeth_l3_clear_ip_htable(struct qeth_card *card, int recover) } spin_unlock_bh(&card->ip_lock); - - spin_lock_bh(&card->mclock); - - hash_for_each_safe(card->ip_mc_htable, i, tmp, addr, hnode) { - hash_del(&addr->hnode); - kfree(addr); - } - - spin_unlock_bh(&card->mclock); - - } + static void qeth_l3_recover_ip(struct qeth_card *card) { struct qeth_ipaddr *addr; @@ -1413,6 +1417,9 @@ static void qeth_l3_stop_card(struct qeth_card *card) qeth_set_allowed_threads(card, 0, 1); + cancel_work_sync(&card->rx_mode_work); + qeth_l3_drain_rx_mode_cache(card); + if (card->options.sniffer && (card->info.promisc_mode == SET_PROMISC_MODE_ON)) qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE); @@ -1466,9 +1473,10 @@ qeth_l3_handle_promisc_mode(struct qeth_card *card) } } -static void qeth_l3_set_rx_mode(struct net_device *dev) +static void qeth_l3_rx_mode_work(struct work_struct *work) { - struct qeth_card *card = dev->ml_priv; + struct qeth_card *card = container_of(work, struct qeth_card, + rx_mode_work); struct qeth_ipaddr *addr; struct hlist_node *tmp; int i, rc; @@ -2101,6 +2109,13 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } +static void qeth_l3_set_rx_mode(struct net_device *dev) +{ + struct qeth_card *card = dev->ml_priv; + + schedule_work(&card->rx_mode_work); +} + /* * we need NOARP for IPv4 but we want neighbor solicitation for IPv6. Setting * NOARP on the netdevice is no option because it also turns off neighbor @@ -2261,6 +2276,7 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev) } hash_init(card->ip_mc_htable); + INIT_WORK(&card->rx_mode_work, qeth_l3_rx_mode_work); return 0; } -- 2.16.4