mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
net: aquantia: Detach SMMU during PCI device removal
Enable support for performing SMMU detach during PCI device removal that is required for converting the driver to a loadable module. Change-Id: Id5361db7607fa647308ba1eaaa5159cbc0add272 Signed-off-by: Jinesh K. Jayakumar <jineshk@codeaurora.org>
This commit is contained in:
parent
cdfc6e8ec4
commit
f4dc3ac72e
@ -29,20 +29,4 @@ config AQFWD
|
||||
|
||||
source "drivers/net/ethernet/aquantia/atlantic-fwd/Kconfig"
|
||||
|
||||
config AQFWD_QCOM
|
||||
bool "QTI MSM/MDM target support"
|
||||
depends on AQFWD
|
||||
depends on ARCH_QCOM
|
||||
help
|
||||
Enable support for integration with Qualcomm Technologies, Inc. chipsets.
|
||||
|
||||
config AQFWD_QCOM_IPA
|
||||
bool "QTI IPA offload support"
|
||||
depends on IPA_ETH
|
||||
select AQFWD_QCOM
|
||||
select ATLFWD_FWD
|
||||
help
|
||||
Enable support for Qualcomm Technologies, Inc. IPA (Internet Protocol Accelerator).
|
||||
If unsure, say N.
|
||||
|
||||
endif # NET_VENDOR_AQUANTIA
|
||||
|
@ -42,3 +42,24 @@ config ATLFWD_FWD_TXBUF
|
||||
API enabled, 0 otherwise.
|
||||
|
||||
endif
|
||||
|
||||
config AQFWD_QCOM
|
||||
bool "QTI MSM/MDM target support"
|
||||
depends on AQFWD
|
||||
depends on ARCH_QCOM
|
||||
help
|
||||
Some older targets using Qualcomm Technologies, Inc. chipsets
|
||||
require peripheral drivers to explicitly set IOMMU attributes
|
||||
and perform IOMMU attach. Enable this option if your platform
|
||||
is affected. Using this feature will also require the user to
|
||||
provide SMMU configuration via PCI device tree.
|
||||
If unsure, say N.
|
||||
|
||||
config AQFWD_QCOM_IPA
|
||||
bool "QTI IPA offload support"
|
||||
depends on IPA_ETH
|
||||
select AQFWD_QCOM
|
||||
select ATLFWD_FWD
|
||||
help
|
||||
Enable support for Qualcomm Technologies, Inc. IPA (Internet Protocol Accelerator).
|
||||
If unsure, say N.
|
||||
|
@ -40,8 +40,6 @@ atlantic-fwd-objs := atl_fw.o \
|
||||
|
||||
atlantic-fwd-$(CONFIG_ATLFWD_FWD) += atl_fwd.o
|
||||
|
||||
atlantic-fwd-$(CONFIG_OF) += atl_of.o
|
||||
|
||||
atlantic-fwd-$(CONFIG_AQFWD_QCOM) += atl_qcom.o
|
||||
atlantic-fwd-$(CONFIG_AQFWD_QCOM_IPA) += atl_qcom_ipa.o
|
||||
|
||||
|
@ -13,9 +13,7 @@
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include "atl_qcom_ipa.h"
|
||||
|
||||
#include "atl_of.h"
|
||||
#include "atl_qcom.h"
|
||||
|
||||
const char atl_driver_name[] = "atlantic-fwd";
|
||||
|
||||
@ -358,10 +356,6 @@ static int atl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
struct atl_hw *hw;
|
||||
int disable_needed;
|
||||
|
||||
ret = atl_parse_dt(&pdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pci_enable_device_mem(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -704,9 +698,9 @@ static int __init atl_module_init(void)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = atl_qcom_ipa_register(&atl_pci_ops);
|
||||
ret = atl_qcom_register(&atl_pci_ops);
|
||||
if (ret) {
|
||||
pr_err("%s: Failed to register driver with IPA\n",
|
||||
pr_err("%s: Failed to register driver with platform\n",
|
||||
atl_driver_name);
|
||||
destroy_workqueue(atl_wq);
|
||||
return ret;
|
||||
@ -714,7 +708,7 @@ static int __init atl_module_init(void)
|
||||
|
||||
ret = pci_register_driver(&atl_pci_ops);
|
||||
if (ret) {
|
||||
atl_qcom_ipa_unregister(&atl_pci_ops);
|
||||
atl_qcom_unregister(&atl_pci_ops);
|
||||
destroy_workqueue(atl_wq);
|
||||
return ret;
|
||||
}
|
||||
@ -727,7 +721,7 @@ static void __exit atl_module_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&atl_pci_ops);
|
||||
|
||||
atl_qcom_ipa_unregister(&atl_pci_ops);
|
||||
atl_qcom_unregister(&atl_pci_ops);
|
||||
|
||||
if (atl_wq) {
|
||||
destroy_workqueue(atl_wq);
|
||||
|
@ -1,41 +0,0 @@
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
|
||||
#include "atl_qcom.h"
|
||||
#include "atl_of.h"
|
||||
|
||||
static const struct of_device_id aqc_matches[] = {
|
||||
{ .compatible = "aquantia,aqc-107" },
|
||||
{ .compatible = "aquantia,aqc-108" },
|
||||
{ .compatible = "aquantia,aqc-109" },
|
||||
};
|
||||
|
||||
int atl_parse_dt(struct device *dev)
|
||||
{
|
||||
if (!dev->of_node) {
|
||||
dev_dbg(dev, "device tree node is not present\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!of_match_node(aqc_matches, dev->of_node)) {
|
||||
dev_notice(dev, "device tree node is not compatible\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Aquantia properties go here */
|
||||
|
||||
/* OEM properties go here */
|
||||
|
||||
return atl_qcom_parse_dt(dev);
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _ATL_OF_H_
|
||||
#define _ATL_OF_H_
|
||||
|
||||
#include <linux/device.h>
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
||||
int atl_parse_dt(struct device *dev);
|
||||
|
||||
#else
|
||||
|
||||
static inline int atl_parse_dt(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // CONFIG_OF
|
||||
|
||||
#endif // _ATL_OF_H_
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@ -10,12 +10,18 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/iommu.h>
|
||||
#include <asm/dma-iommu.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "atl_qcom_ipa.h"
|
||||
#include "atl_qcom.h"
|
||||
|
||||
static int (*atl_probe_real)(struct pci_dev *, const struct pci_device_id *);
|
||||
static void (*atl_remove_real)(struct pci_dev *);
|
||||
|
||||
static int atl_qcom_parse_smmu_attr(struct device *dev,
|
||||
struct iommu_domain *domain,
|
||||
const char *key,
|
||||
@ -60,7 +66,7 @@ static int atl_qcom_parse_smmu_attrs(struct device *dev,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int atl_qcom_parse_smmu(struct device *dev)
|
||||
static int __atl_qcom_attach_smmu(struct device *dev)
|
||||
{
|
||||
int rc;
|
||||
const char *key;
|
||||
@ -117,14 +123,110 @@ err_release_mapping:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int atl_qcom_parse_dt(struct device *dev)
|
||||
static int atl_qcom_attach_smmu(struct device *dev)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!dev->of_node) {
|
||||
dev_dbg(dev, "device tree node is not present\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (of_find_property(dev->of_node, "qcom,smmu", NULL))
|
||||
rc = atl_qcom_parse_smmu(dev);
|
||||
rc = __atl_qcom_attach_smmu(dev);
|
||||
else
|
||||
dev_dbg(dev, "SMMU config not present in DT\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void atl_qcom_detach_smmu(struct device *dev)
|
||||
{
|
||||
struct dma_iommu_mapping *mapping;
|
||||
|
||||
if (!dev->of_node || !of_find_property(dev->of_node, "qcom,smmu", NULL))
|
||||
return;
|
||||
|
||||
mapping = to_dma_iommu_mapping(dev);
|
||||
if (!mapping)
|
||||
return;
|
||||
|
||||
arm_iommu_detach_device(dev);
|
||||
arm_iommu_release_mapping(mapping);
|
||||
}
|
||||
|
||||
static int atl_qcom_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = atl_qcom_attach_smmu(&pdev->dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = atl_probe_real(pdev, id);
|
||||
if (rc) {
|
||||
atl_qcom_detach_smmu(&pdev->dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void atl_qcom_remove(struct pci_dev *pdev)
|
||||
{
|
||||
atl_remove_real(pdev);
|
||||
atl_qcom_detach_smmu(&pdev->dev);
|
||||
}
|
||||
|
||||
static int __atl_qcom_register(struct pci_driver *pdrv)
|
||||
{
|
||||
if (atl_probe_real || atl_remove_real) {
|
||||
pr_err("%s: Driver already registered\n", __func__);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
atl_probe_real = pdrv->probe;
|
||||
pdrv->probe = atl_qcom_probe;
|
||||
|
||||
atl_remove_real = pdrv->remove;
|
||||
pdrv->remove = atl_qcom_remove;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __atl_qcom_unregister(struct pci_driver *pdrv)
|
||||
{
|
||||
if (atl_probe_real) {
|
||||
pdrv->probe = atl_probe_real;
|
||||
atl_probe_real = NULL;
|
||||
}
|
||||
|
||||
if (atl_remove_real) {
|
||||
pdrv->remove = atl_remove_real;
|
||||
atl_remove_real = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int atl_qcom_register(struct pci_driver *pdrv)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = __atl_qcom_register(pdrv);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = atl_qcom_ipa_register(pdrv);
|
||||
if (rc) {
|
||||
pr_err("%s: Failed to register driver with IPA\n", __func__);
|
||||
__atl_qcom_unregister(pdrv);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void atl_qcom_unregister(struct pci_driver *pdrv)
|
||||
{
|
||||
atl_qcom_ipa_unregister(pdrv);
|
||||
__atl_qcom_unregister(pdrv);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@ -13,16 +13,17 @@
|
||||
#ifndef _ATL_QCOM_H_
|
||||
#define _ATL_QCOM_H_
|
||||
|
||||
#include <linux/pci.h>
|
||||
|
||||
#ifdef CONFIG_AQFWD_QCOM
|
||||
|
||||
int atl_qcom_parse_dt(struct device *dev);
|
||||
int atl_qcom_register(struct pci_driver *pdrv);
|
||||
void atl_qcom_unregister(struct pci_driver *pdrv);
|
||||
|
||||
#else
|
||||
|
||||
static inline int atl_qcom_parse_dt(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int atl_qcom_register(struct pci_driver *pdrv) { return 0; }
|
||||
static inline void atl_qcom_unregister(struct pci_driver *pdrv) { return; }
|
||||
|
||||
#endif // CONFIG_AQFWD_QCOM
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user