diff options
Diffstat (limited to 'drivers/net/ipa/ipa_main.c')
-rw-r--r-- | drivers/net/ipa/ipa_main.c | 103 |
1 files changed, 55 insertions, 48 deletions
diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c index 00475fd7a2..5f3dd5a2dc 100644 --- a/drivers/net/ipa/ipa_main.c +++ b/drivers/net/ipa/ipa_main.c @@ -1,39 +1,37 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. - * Copyright (C) 2018-2023 Linaro Ltd. + * Copyright (C) 2018-2024 Linaro Ltd. */ -#include <linux/types.h> -#include <linux/atomic.h> -#include <linux/bitfield.h> -#include <linux/device.h> #include <linux/bug.h> -#include <linux/io.h> #include <linux/firmware.h> +#include <linux/io.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/types.h> + #include <linux/firmware/qcom/qcom_scm.h> #include <linux/soc/qcom/mdt_loader.h> #include "ipa.h" -#include "ipa_power.h" +#include "ipa_cmd.h" #include "ipa_data.h" #include "ipa_endpoint.h" -#include "ipa_resource.h" -#include "ipa_cmd.h" -#include "ipa_reg.h" +#include "ipa_interrupt.h" #include "ipa_mem.h" -#include "ipa_table.h" -#include "ipa_smp2p.h" #include "ipa_modem.h" -#include "ipa_uc.h" -#include "ipa_interrupt.h" -#include "gsi_trans.h" +#include "ipa_power.h" +#include "ipa_reg.h" +#include "ipa_resource.h" +#include "ipa_smp2p.h" #include "ipa_sysfs.h" +#include "ipa_table.h" +#include "ipa_uc.h" +#include "ipa_version.h" /** * DOC: The IP Accelerator @@ -114,17 +112,13 @@ int ipa_setup(struct ipa *ipa) { struct ipa_endpoint *exception_endpoint; struct ipa_endpoint *command_endpoint; - struct device *dev = &ipa->pdev->dev; + struct device *dev = ipa->dev; int ret; ret = gsi_setup(&ipa->gsi); if (ret) return ret; - ret = ipa_power_setup(ipa); - if (ret) - goto err_gsi_teardown; - ipa_endpoint_setup(ipa); /* We need to use the AP command TX endpoint to perform other @@ -171,8 +165,6 @@ err_command_disable: ipa_endpoint_disable_one(command_endpoint); err_endpoint_teardown: ipa_endpoint_teardown(ipa); - ipa_power_teardown(ipa); -err_gsi_teardown: gsi_teardown(&ipa->gsi); return ret; @@ -197,7 +189,6 @@ static void ipa_teardown(struct ipa *ipa) command_endpoint = ipa->name_map[IPA_ENDPOINT_AP_COMMAND_TX]; ipa_endpoint_disable_one(command_endpoint); ipa_endpoint_teardown(ipa); - ipa_power_teardown(ipa); gsi_teardown(&ipa->gsi); } @@ -542,12 +533,9 @@ static int ipa_config(struct ipa *ipa, const struct ipa_data *data) if (ret) goto err_hardware_deconfig; - ipa->interrupt = ipa_interrupt_config(ipa); - if (IS_ERR(ipa->interrupt)) { - ret = PTR_ERR(ipa->interrupt); - ipa->interrupt = NULL; + ret = ipa_interrupt_config(ipa); + if (ret) goto err_mem_deconfig; - } ipa_uc_config(ipa); @@ -572,8 +560,7 @@ err_endpoint_deconfig: ipa_endpoint_deconfig(ipa); err_uc_deconfig: ipa_uc_deconfig(ipa); - ipa_interrupt_deconfig(ipa->interrupt); - ipa->interrupt = NULL; + ipa_interrupt_deconfig(ipa); err_mem_deconfig: ipa_mem_deconfig(ipa); err_hardware_deconfig: @@ -591,8 +578,7 @@ static void ipa_deconfig(struct ipa *ipa) ipa_modem_deconfig(ipa); ipa_endpoint_deconfig(ipa); ipa_uc_deconfig(ipa); - ipa_interrupt_deconfig(ipa->interrupt); - ipa->interrupt = NULL; + ipa_interrupt_deconfig(ipa); ipa_mem_deconfig(ipa); ipa_hardware_deconfig(ipa); } @@ -808,6 +794,7 @@ out_self: static int ipa_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct ipa_interrupt *interrupt; enum ipa_firmware_loader loader; const struct ipa_data *data; struct ipa_power *power; @@ -823,11 +810,6 @@ static int ipa_probe(struct platform_device *pdev) return -ENODEV; } - if (!ipa_version_supported(data->version)) { - dev_err(dev, "unsupported IPA version %u\n", data->version); - return -EINVAL; - } - if (!data->modem_route_count) { dev_err(dev, "modem_route_count cannot be zero\n"); return -EINVAL; @@ -839,12 +821,21 @@ static int ipa_probe(struct platform_device *pdev) if (loader == IPA_LOADER_DEFER) return -EPROBE_DEFER; - /* The clock and interconnects might not be ready when we're - * probed, so might return -EPROBE_DEFER. + /* The IPA interrupt might not be ready when we're probed, so this + * might return -EPROBE_DEFER. + */ + interrupt = ipa_interrupt_init(pdev); + if (IS_ERR(interrupt)) + return PTR_ERR(interrupt); + + /* The clock and interconnects might not be ready when we're probed, + * so this might return -EPROBE_DEFER. */ power = ipa_power_init(dev, data->power_data); - if (IS_ERR(power)) - return PTR_ERR(power); + if (IS_ERR(power)) { + ret = PTR_ERR(power); + goto err_interrupt_exit; + } /* No more EPROBE_DEFER. Allocate and initialize the IPA structure */ ipa = kzalloc(sizeof(*ipa), GFP_KERNEL); @@ -853,21 +844,26 @@ static int ipa_probe(struct platform_device *pdev) goto err_power_exit; } - ipa->pdev = pdev; + ipa->dev = dev; dev_set_drvdata(dev, ipa); + ipa->interrupt = interrupt; ipa->power = power; ipa->version = data->version; ipa->modem_route_count = data->modem_route_count; init_completion(&ipa->completion); - ret = ipa_reg_init(ipa); + ret = ipa_reg_init(ipa, pdev); if (ret) goto err_kfree_ipa; - ret = ipa_mem_init(ipa, data->mem_data); + ret = ipa_mem_init(ipa, pdev, data->mem_data); if (ret) goto err_reg_exit; + ret = ipa_cmd_init(ipa); + if (ret) + goto err_mem_exit; + ret = gsi_init(&ipa->gsi, pdev, ipa->version, data->endpoint_count, data->endpoint_data); if (ret) @@ -882,7 +878,7 @@ static int ipa_probe(struct platform_device *pdev) if (ret) goto err_endpoint_exit; - ret = ipa_smp2p_init(ipa, loader == IPA_LOADER_MODEM); + ret = ipa_smp2p_init(ipa, pdev, loader == IPA_LOADER_MODEM); if (ret) goto err_table_exit; @@ -939,17 +935,27 @@ err_kfree_ipa: kfree(ipa); err_power_exit: ipa_power_exit(power); +err_interrupt_exit: + ipa_interrupt_exit(interrupt); return ret; } static void ipa_remove(struct platform_device *pdev) { - struct ipa *ipa = dev_get_drvdata(&pdev->dev); - struct ipa_power *power = ipa->power; - struct device *dev = &pdev->dev; + struct ipa_interrupt *interrupt; + struct ipa_power *power; + struct device *dev; + struct ipa *ipa; int ret; + ipa = dev_get_drvdata(&pdev->dev); + dev = ipa->dev; + WARN_ON(dev != &pdev->dev); + + power = ipa->power; + interrupt = ipa->interrupt; + /* Prevent the modem from triggering a call to ipa_setup(). This * also ensures a modem-initiated setup that's underway completes. */ @@ -991,6 +997,7 @@ out_power_put: ipa_reg_exit(ipa); kfree(ipa); ipa_power_exit(power); + ipa_interrupt_exit(interrupt); dev_info(dev, "IPA driver removed"); } |