Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp2989420pxj; Mon, 17 May 2021 15:02:45 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz/UNhgIhR2wgEVW9S//xVmkzAsbCNgjX/0hm+OD1WRq9YBRsP7rhPSQwG/twon9ilCGB2C X-Received: by 2002:a17:906:63d2:: with SMTP id u18mr2161882ejk.186.1621288964987; Mon, 17 May 2021 15:02:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1621288964; cv=none; d=google.com; s=arc-20160816; b=KXpR1KW9fQ0zcOJ/w0dRIMWpLwLpjr8VaV3O+rI/mUTZQYsCALMooWh6MqDJsRsPdY Z8BeciAuXCt2mdgv9U8+RHKjMNsLj7bCLtjmJtuBoOrXB1f6WGcE9vDSReML2xpPIbMI D8ShGiEiDBEMSLm6xDJ9Ocv6QxCToe2GAlOu0yUHJAiVhkEMw8o4VrVyMyYuNUt8p7KE PDW0da505TwQy9LDcDs7QKicfhygeBaqk0lIbSURYfXGSI0L+RmzHYvhKlKVR3S7P44Q o7f3Q1TFFi4EdQyq9t2eaD+Xo0/s3Gfpa47/c8jfV9CDqPANOPZQmk47hljrKBX80aGb KtgA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=LbLukIf2q0Ye7+sQjbb+EAjZYER7cC9blCAjYIfIpy4=; b=ambSr0F28lr12uXsmP2uwDusFwBC1Kw7PnLUv5vA18QLO17K2xMgfkHV+5NGHBKkP3 aCC0a4NOVmisAXBFmLjq5GvBMkvwpDOEd4ZSDGWZsQ0O2IILzI4gCljqKZmV5wvqu2Hw XszwyHp9puGiuGFyetjJV6rAaACw7eyidU90cqEUA4GuLTsUNaJbo9tEuYNBYPYJkPXf XJnd+O01t5Dye8JajDUI0g0eI7AWWS/GYN+R6Y7v638a5UMdJsRbRvbCcqn0DkTEnoy9 XVZCwBESbU6ZF3lstxreaeMcyWqbNVOB/X7B27sQCCEtL4+7Fyt+S+fSq6/IRODithem 5QQQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=AQhZrIHL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id l21si6386110ejn.568.2021.05.17.15.02.21; Mon, 17 May 2021 15:02:44 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=AQhZrIHL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238707AbhEQOMF (ORCPT + 99 others); Mon, 17 May 2021 10:12:05 -0400 Received: from mail.kernel.org ([198.145.29.99]:58828 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238324AbhEQOKA (ORCPT ); Mon, 17 May 2021 10:10:00 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id A6AF6613AF; Mon, 17 May 2021 14:07:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1621260429; bh=pstObWc4s3VCMIBz08bVRP4wjecVlqHtlaHyx1NNe24=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AQhZrIHLW7LMajjB9xmuCLXIMzJJ6C00LZdF7RFtn6MHDrMfNdiO9vLSRgJqX/q3Q Mxl8AYqnRL/edY2hFHwN1omfd2eSHSm8FkKoPgS1nUR4Kyd+CNVXhSfZGUEGKGLjEv qN72VkZo17N7Xl6B4YA2X8TO7F9r4kCIJoZ2ift4= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Johannes Berg , Luca Coelho , Sasha Levin Subject: [PATCH 5.12 078/363] iwlwifi: trans/pcie: defer transport initialisation Date: Mon, 17 May 2021 15:59:04 +0200 Message-Id: <20210517140305.233424135@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210517140302.508966430@linuxfoundation.org> References: <20210517140302.508966430@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Johannes Berg [ Upstream commit d12455fdbfe9430affd88bfbfee51777356667a0 ] In a few PCIe devices we may have to swap out the configuration after we allocate/initialise some parts of the device because we only know the correct one after reading some registers. This causes some things such as the byte-count table allocations to be incorrect, since the configuration is swapped for one with a bigger queue size. Fix this by initialising most of the transport much later, only after the configuration has finally been determined. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/iwlwifi.20210411132130.8f5db97db1e4.Ic622da559b586a04ca536a0ec49ed5ecf03a9354@changeid Signed-off-by: Luca Coelho Signed-off-by: Sasha Levin --- .../net/wireless/intel/iwlwifi/iwl-trans.c | 91 +++++++++++-------- .../net/wireless/intel/iwlwifi/iwl-trans.h | 1 + drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4 + 3 files changed, 57 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 60e0db4a5e20..9236f9106826 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -2,7 +2,7 @@ /* * Copyright (C) 2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH - * Copyright (C) 2019-2020 Intel Corporation + * Copyright (C) 2019-2021 Intel Corporation */ #include #include @@ -21,7 +21,6 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, const struct iwl_cfg_trans_params *cfg_trans) { struct iwl_trans *trans; - int txcmd_size, txcmd_align; #ifdef CONFIG_LOCKDEP static struct lock_class_key __key; #endif @@ -31,10 +30,40 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, return NULL; trans->trans_cfg = cfg_trans; - if (!cfg_trans->gen2) { + +#ifdef CONFIG_LOCKDEP + lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map", + &__key, 0); +#endif + + trans->dev = dev; + trans->ops = ops; + trans->num_rx_queues = 1; + + WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty); + + if (trans->trans_cfg->use_tfh) { + trans->txqs.tfd.addr_size = 64; + trans->txqs.tfd.max_tbs = IWL_TFH_NUM_TBS; + trans->txqs.tfd.size = sizeof(struct iwl_tfh_tfd); + } else { + trans->txqs.tfd.addr_size = 36; + trans->txqs.tfd.max_tbs = IWL_NUM_OF_TBS; + trans->txqs.tfd.size = sizeof(struct iwl_tfd); + } + trans->max_skb_frags = IWL_TRANS_MAX_FRAGS(trans); + + return trans; +} + +int iwl_trans_init(struct iwl_trans *trans) +{ + int txcmd_size, txcmd_align; + + if (!trans->trans_cfg->gen2) { txcmd_size = sizeof(struct iwl_tx_cmd); txcmd_align = sizeof(void *); - } else if (cfg_trans->device_family < IWL_DEVICE_FAMILY_AX210) { + } else if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) { txcmd_size = sizeof(struct iwl_tx_cmd_gen2); txcmd_align = 64; } else { @@ -46,17 +75,8 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, txcmd_size += 36; /* biggest possible 802.11 header */ /* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */ - if (WARN_ON(cfg_trans->gen2 && txcmd_size >= txcmd_align)) - return ERR_PTR(-EINVAL); - -#ifdef CONFIG_LOCKDEP - lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map", - &__key, 0); -#endif - - trans->dev = dev; - trans->ops = ops; - trans->num_rx_queues = 1; + if (WARN_ON(trans->trans_cfg->gen2 && txcmd_size >= txcmd_align)) + return -EINVAL; if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) trans->txqs.bc_tbl_size = sizeof(struct iwl_gen3_bc_tbl); @@ -68,23 +88,16 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, * allocate here. */ if (trans->trans_cfg->gen2) { - trans->txqs.bc_pool = dmam_pool_create("iwlwifi:bc", dev, + trans->txqs.bc_pool = dmam_pool_create("iwlwifi:bc", trans->dev, trans->txqs.bc_tbl_size, 256, 0); if (!trans->txqs.bc_pool) - return NULL; + return -ENOMEM; } - if (trans->trans_cfg->use_tfh) { - trans->txqs.tfd.addr_size = 64; - trans->txqs.tfd.max_tbs = IWL_TFH_NUM_TBS; - trans->txqs.tfd.size = sizeof(struct iwl_tfh_tfd); - } else { - trans->txqs.tfd.addr_size = 36; - trans->txqs.tfd.max_tbs = IWL_NUM_OF_TBS; - trans->txqs.tfd.size = sizeof(struct iwl_tfd); - } - trans->max_skb_frags = IWL_TRANS_MAX_FRAGS(trans); + /* Some things must not change even if the config does */ + WARN_ON(trans->txqs.tfd.addr_size != + (trans->trans_cfg->use_tfh ? 64 : 36)); snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), "iwl_cmd_pool:%s", dev_name(trans->dev)); @@ -93,35 +106,35 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, txcmd_size, txcmd_align, SLAB_HWCACHE_ALIGN, NULL); if (!trans->dev_cmd_pool) - return NULL; - - WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty); + return -ENOMEM; trans->txqs.tso_hdr_page = alloc_percpu(struct iwl_tso_hdr_page); if (!trans->txqs.tso_hdr_page) { kmem_cache_destroy(trans->dev_cmd_pool); - return NULL; + return -ENOMEM; } /* Initialize the wait queue for commands */ init_waitqueue_head(&trans->wait_command_queue); - return trans; + return 0; } void iwl_trans_free(struct iwl_trans *trans) { int i; - for_each_possible_cpu(i) { - struct iwl_tso_hdr_page *p = - per_cpu_ptr(trans->txqs.tso_hdr_page, i); + if (trans->txqs.tso_hdr_page) { + for_each_possible_cpu(i) { + struct iwl_tso_hdr_page *p = + per_cpu_ptr(trans->txqs.tso_hdr_page, i); - if (p->page) - __free_page(p->page); - } + if (p && p->page) + __free_page(p->page); + } - free_percpu(trans->txqs.tso_hdr_page); + free_percpu(trans->txqs.tso_hdr_page); + } kmem_cache_destroy(trans->dev_cmd_pool); } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 4a5822c1be13..3e0df6fbb642 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1438,6 +1438,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, struct device *dev, const struct iwl_trans_ops *ops, const struct iwl_cfg_trans_params *cfg_trans); +int iwl_trans_init(struct iwl_trans *trans); void iwl_trans_free(struct iwl_trans *trans); /***************************************************** diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 6f4db04ead4a..66faf7914bd8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1243,6 +1243,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) trans_pcie->num_rx_bufs = RX_QUEUE_SIZE; } + ret = iwl_trans_init(iwl_trans); + if (ret) + goto out_free_trans; + pci_set_drvdata(pdev, iwl_trans); iwl_trans->drv = iwl_drv_start(iwl_trans); -- 2.30.2