Skip to content

Commit

Permalink
Merge branch 'ipa-autosuspend'
Browse files Browse the repository at this point in the history
Alex Elder says:

====================
net: ipa: enable automatic suspend

At long last, the first patch in this series enables automatic
suspend managed by the power management core.  The remaining two
just rename things to be "power" oriented rather than "clock"
oriented.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 22, 2021
2 parents 4af14db + 2775cbc commit 8634348
Show file tree
Hide file tree
Showing 19 changed files with 217 additions and 204 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ipa/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
obj-$(CONFIG_QCOM_IPA) += ipa.o

ipa-y := ipa_main.o ipa_clock.o ipa_reg.o ipa_mem.o \
ipa-y := ipa_main.o ipa_power.o ipa_reg.o ipa_mem.o \
ipa_table.o ipa_interrupt.o gsi.o gsi_trans.o \
ipa_gsi.o ipa_smp2p.o ipa_uc.o \
ipa_endpoint.o ipa_cmd.o ipa_modem.o \
Expand Down
20 changes: 10 additions & 10 deletions drivers/net/ipa/ipa.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct icc_path;
struct net_device;
struct platform_device;

struct ipa_clock;
struct ipa_power;
struct ipa_smp2p;
struct ipa_interrupt;

Expand All @@ -36,11 +36,11 @@ struct ipa_interrupt;
* @nb: Notifier block used for remoteproc SSR
* @notifier: Remoteproc SSR notifier
* @smp2p: SMP2P information
* @clock: IPA clocking information
* @power: IPA power information
* @table_addr: DMA address of filter/route table content
* @table_virt: Virtual address of filter/route table content
* @interrupt: IPA Interrupt information
* @uc_clocked: true if clock is active by proxy for microcontroller
* @uc_powered: true if power is active by proxy for microcontroller
* @uc_loaded: true after microcontroller has reported it's ready
* @reg_addr: DMA address used for IPA register access
* @reg_virt: Virtual address used for IPA register access
Expand Down Expand Up @@ -78,13 +78,13 @@ struct ipa {
struct notifier_block nb;
void *notifier;
struct ipa_smp2p *smp2p;
struct ipa_clock *clock;
struct ipa_power *power;

dma_addr_t table_addr;
__le64 *table_virt;

struct ipa_interrupt *interrupt;
bool uc_clocked;
bool uc_powered;
bool uc_loaded;

dma_addr_t reg_addr;
Expand Down Expand Up @@ -134,11 +134,11 @@ struct ipa {
*
* Activities performed at the init stage can be done without requiring
* any access to IPA hardware. Activities performed at the config stage
* require the IPA clock to be running, because they involve access
* to IPA registers. The setup stage is performed only after the GSI
* hardware is ready (more on this below). The setup stage allows
* the AP to perform more complex initialization by issuing "immediate
* commands" using a special interface to the IPA.
* require IPA power, because they involve access to IPA registers.
* The setup stage is performed only after the GSI hardware is ready
* (more on this below). The setup stage allows the AP to perform
* more complex initialization by issuing "immediate commands" using
* a special interface to the IPA.
*
* This function, @ipa_setup(), starts the setup stage.
*
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ipa/ipa_data-v3.1.c
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ static const struct ipa_interconnect_data ipa_interconnect_data[] = {
};

/* Clock and interconnect configuration data for an SoC having IPA v3.1 */
static const struct ipa_clock_data ipa_clock_data = {
static const struct ipa_power_data ipa_power_data = {
.core_clock_rate = 16 * 1000 * 1000, /* Hz */
.interconnect_count = ARRAY_SIZE(ipa_interconnect_data),
.interconnect_data = ipa_interconnect_data,
Expand All @@ -529,5 +529,5 @@ const struct ipa_data ipa_data_v3_1 = {
.endpoint_data = ipa_gsi_endpoint_data,
.resource_data = &ipa_resource_data,
.mem_data = &ipa_mem_data,
.clock_data = &ipa_clock_data,
.power_data = &ipa_power_data,
};
4 changes: 2 additions & 2 deletions drivers/net/ipa/ipa_data-v3.5.1.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ static const struct ipa_interconnect_data ipa_interconnect_data[] = {
};

/* Clock and interconnect configuration data for an SoC having IPA v3.5.1 */
static const struct ipa_clock_data ipa_clock_data = {
static const struct ipa_power_data ipa_power_data = {
.core_clock_rate = 75 * 1000 * 1000, /* Hz */
.interconnect_count = ARRAY_SIZE(ipa_interconnect_data),
.interconnect_data = ipa_interconnect_data,
Expand All @@ -414,5 +414,5 @@ const struct ipa_data ipa_data_v3_5_1 = {
.endpoint_data = ipa_gsi_endpoint_data,
.resource_data = &ipa_resource_data,
.mem_data = &ipa_mem_data,
.clock_data = &ipa_clock_data,
.power_data = &ipa_power_data,
};
4 changes: 2 additions & 2 deletions drivers/net/ipa/ipa_data-v4.11.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ static const struct ipa_interconnect_data ipa_interconnect_data[] = {
};

/* Clock and interconnect configuration data for an SoC having IPA v4.11 */
static const struct ipa_clock_data ipa_clock_data = {
static const struct ipa_power_data ipa_power_data = {
.core_clock_rate = 60 * 1000 * 1000, /* Hz */
.interconnect_count = ARRAY_SIZE(ipa_interconnect_data),
.interconnect_data = ipa_interconnect_data,
Expand All @@ -397,5 +397,5 @@ const struct ipa_data ipa_data_v4_11 = {
.endpoint_data = ipa_gsi_endpoint_data,
.resource_data = &ipa_resource_data,
.mem_data = &ipa_mem_data,
.clock_data = &ipa_clock_data,
.power_data = &ipa_power_data,
};
4 changes: 2 additions & 2 deletions drivers/net/ipa/ipa_data-v4.2.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ static const struct ipa_interconnect_data ipa_interconnect_data[] = {
};

/* Clock and interconnect configuration data for an SoC having IPA v4.2 */
static const struct ipa_clock_data ipa_clock_data = {
static const struct ipa_power_data ipa_power_data = {
.core_clock_rate = 100 * 1000 * 1000, /* Hz */
.interconnect_count = ARRAY_SIZE(ipa_interconnect_data),
.interconnect_data = ipa_interconnect_data,
Expand All @@ -376,5 +376,5 @@ const struct ipa_data ipa_data_v4_2 = {
.endpoint_data = ipa_gsi_endpoint_data,
.resource_data = &ipa_resource_data,
.mem_data = &ipa_mem_data,
.clock_data = &ipa_clock_data,
.power_data = &ipa_power_data,
};
4 changes: 2 additions & 2 deletions drivers/net/ipa/ipa_data-v4.5.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ static const struct ipa_interconnect_data ipa_interconnect_data[] = {
};

/* Clock and interconnect configuration data for an SoC having IPA v4.5 */
static const struct ipa_clock_data ipa_clock_data = {
static const struct ipa_power_data ipa_power_data = {
.core_clock_rate = 150 * 1000 * 1000, /* Hz (150? 60?) */
.interconnect_count = ARRAY_SIZE(ipa_interconnect_data),
.interconnect_data = ipa_interconnect_data,
Expand All @@ -458,5 +458,5 @@ const struct ipa_data ipa_data_v4_5 = {
.endpoint_data = ipa_gsi_endpoint_data,
.resource_data = &ipa_resource_data,
.mem_data = &ipa_mem_data,
.clock_data = &ipa_clock_data,
.power_data = &ipa_power_data,
};
4 changes: 2 additions & 2 deletions drivers/net/ipa/ipa_data-v4.9.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ static const struct ipa_interconnect_data ipa_interconnect_data[] = {
};

/* Clock and interconnect configuration data for an SoC having IPA v4.9 */
static const struct ipa_clock_data ipa_clock_data = {
static const struct ipa_power_data ipa_power_data = {
.core_clock_rate = 60 * 1000 * 1000, /* Hz */
.interconnect_count = ARRAY_SIZE(ipa_interconnect_data),
.interconnect_data = ipa_interconnect_data,
Expand All @@ -447,5 +447,5 @@ const struct ipa_data ipa_data_v4_9 = {
.endpoint_data = ipa_gsi_endpoint_data,
.resource_data = &ipa_resource_data,
.mem_data = &ipa_mem_data,
.clock_data = &ipa_clock_data,
.power_data = &ipa_power_data,
};
10 changes: 5 additions & 5 deletions drivers/net/ipa/ipa_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
* IPA and GSI resources to use for a given platform. This data is supplied
* via the Device Tree match table, associated with a particular compatible
* string. The data defines information about how resources, endpoints and
* channels, memory, clocking and so on are allocated and used for the
* channels, memory, power and so on are allocated and used for the
* platform.
*
* Resources are data structures used internally by the IPA hardware. The
Expand Down Expand Up @@ -265,12 +265,12 @@ struct ipa_interconnect_data {
};

/**
* struct ipa_clock_data - description of IPA clock and interconnect rates
* struct ipa_power_data - description of IPA power configuration data
* @core_clock_rate: Core clock rate (Hz)
* @interconnect_count: Number of entries in the interconnect_data array
* @interconnect_data: IPA interconnect configuration data
*/
struct ipa_clock_data {
struct ipa_power_data {
u32 core_clock_rate;
u32 interconnect_count; /* # entries in interconnect_data[] */
const struct ipa_interconnect_data *interconnect_data;
Expand All @@ -286,7 +286,7 @@ struct ipa_clock_data {
* @endpoint_data: IPA endpoint/GSI channel data
* @resource_data: IPA resource configuration data
* @mem_data: IPA memory region data
* @clock_data: IPA clock and interconnect data
* @power_data: IPA power data
*/
struct ipa_data {
enum ipa_version version;
Expand All @@ -297,7 +297,7 @@ struct ipa_data {
const struct ipa_gsi_endpoint_data *endpoint_data;
const struct ipa_resource_data *resource_data;
const struct ipa_mem_data *mem_data;
const struct ipa_clock_data *clock_data;
const struct ipa_power_data *power_data;
};

extern const struct ipa_data ipa_data_v3_1;
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ipa/ipa_endpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include "ipa_modem.h"
#include "ipa_table.h"
#include "ipa_gsi.h"
#include "ipa_clock.h"
#include "ipa_power.h"

#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)

Expand Down Expand Up @@ -810,7 +810,7 @@ static u32 hol_block_timer_val(struct ipa *ipa, u32 microseconds)
return hol_block_timer_qtime_val(ipa, microseconds);

/* Use 64 bit arithmetic to avoid overflow... */
rate = ipa_clock_rate(ipa);
rate = ipa_core_clock_rate(ipa);
ticks = DIV_ROUND_CLOSEST(microseconds * rate, 128 * USEC_PER_SEC);
/* ...but we still need to fit into a 32-bit register */
WARN_ON(ticks > U32_MAX);
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ipa/ipa_interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ static irqreturn_t ipa_isr_thread(int irq, void *dev_id)
iowrite32(pending, ipa->reg_virt + offset);
}
out_power_put:
(void)pm_runtime_put(dev);
pm_runtime_mark_last_busy(dev);
(void)pm_runtime_put_autosuspend(dev);

return IRQ_HANDLED;
}
Expand Down
45 changes: 23 additions & 22 deletions drivers/net/ipa/ipa_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include <linux/soc/qcom/mdt_loader.h>

#include "ipa.h"
#include "ipa_clock.h"
#include "ipa_power.h"
#include "ipa_data.h"
#include "ipa_endpoint.h"
#include "ipa_resource.h"
Expand Down Expand Up @@ -326,8 +326,8 @@ static void ipa_idle_indication_cfg(struct ipa *ipa,
* @ipa: IPA pointer
*
* Configures when the IPA signals it is idle to the global clock
* controller, which can respond by scalling down the clock to
* save power.
* controller, which can respond by scaling down the clock to save
* power.
*/
static void ipa_hardware_dcd_config(struct ipa *ipa)
{
Expand Down Expand Up @@ -417,7 +417,7 @@ static void ipa_hardware_deconfig(struct ipa *ipa)
* @ipa: IPA pointer
* @data: IPA configuration data
*
* Perform initialization requiring IPA clock to be enabled.
* Perform initialization requiring IPA power to be enabled.
*/
static int ipa_config(struct ipa *ipa, const struct ipa_data *data)
{
Expand Down Expand Up @@ -647,7 +647,7 @@ static bool ipa_version_valid(enum ipa_version version)
* in several stages:
* - The "init" stage involves activities that can be initialized without
* access to the IPA hardware.
* - The "config" stage requires the IPA clock to be active so IPA registers
* - The "config" stage requires IPA power to be active so IPA registers
* can be accessed, but does not require the use of IPA immediate commands.
* - The "setup" stage uses IPA immediate commands, and so requires the GSI
* layer to be initialized.
Expand All @@ -663,14 +663,14 @@ static int ipa_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct ipa_data *data;
struct ipa_clock *clock;
struct ipa_power *power;
bool modem_init;
struct ipa *ipa;
int ret;

ipa_validate_build();

/* Get configuration data early; needed for clock initialization */
/* Get configuration data early; needed for power initialization */
data = of_device_get_match_data(dev);
if (!data) {
dev_err(dev, "matched hardware not supported\n");
Expand All @@ -691,20 +691,20 @@ static int ipa_probe(struct platform_device *pdev)
/* The clock and interconnects might not be ready when we're
* probed, so might return -EPROBE_DEFER.
*/
clock = ipa_clock_init(dev, data->clock_data);
if (IS_ERR(clock))
return PTR_ERR(clock);
power = ipa_power_init(dev, data->power_data);
if (IS_ERR(power))
return PTR_ERR(power);

/* No more EPROBE_DEFER. Allocate and initialize the IPA structure */
ipa = kzalloc(sizeof(*ipa), GFP_KERNEL);
if (!ipa) {
ret = -ENOMEM;
goto err_clock_exit;
goto err_power_exit;
}

ipa->pdev = pdev;
dev_set_drvdata(dev, ipa);
ipa->clock = clock;
ipa->power = power;
ipa->version = data->version;
init_completion(&ipa->completion);

Expand Down Expand Up @@ -737,7 +737,7 @@ static int ipa_probe(struct platform_device *pdev)
if (ret)
goto err_table_exit;

/* The clock needs to be active for config and setup */
/* Power needs to be active for config and setup */
ret = pm_runtime_get_sync(dev);
if (WARN_ON(ret < 0))
goto err_power_put;
Expand Down Expand Up @@ -766,14 +766,15 @@ static int ipa_probe(struct platform_device *pdev)
if (ret)
goto err_deconfig;
done:
(void)pm_runtime_put(dev);
pm_runtime_mark_last_busy(dev);
(void)pm_runtime_put_autosuspend(dev);

return 0;

err_deconfig:
ipa_deconfig(ipa);
err_power_put:
(void)pm_runtime_put(dev);
pm_runtime_put_noidle(dev);
ipa_modem_exit(ipa);
err_table_exit:
ipa_table_exit(ipa);
Expand All @@ -787,19 +788,20 @@ static int ipa_probe(struct platform_device *pdev)
ipa_reg_exit(ipa);
err_kfree_ipa:
kfree(ipa);
err_clock_exit:
ipa_clock_exit(clock);
err_power_exit:
ipa_power_exit(power);

return ret;
}

static int ipa_remove(struct platform_device *pdev)
{
struct ipa *ipa = dev_get_drvdata(&pdev->dev);
struct ipa_clock *clock = ipa->clock;
struct ipa_power *power = ipa->power;
struct device *dev = &pdev->dev;
int ret;

ret = pm_runtime_get_sync(&pdev->dev);
ret = pm_runtime_get_sync(dev);
if (WARN_ON(ret < 0))
goto out_power_put;

Expand All @@ -818,16 +820,15 @@ static int ipa_remove(struct platform_device *pdev)

ipa_deconfig(ipa);
out_power_put:
(void)pm_runtime_put(&pdev->dev);

pm_runtime_put_noidle(dev);
ipa_modem_exit(ipa);
ipa_table_exit(ipa);
ipa_endpoint_exit(ipa);
gsi_exit(&ipa->gsi);
ipa_mem_exit(ipa);
ipa_reg_exit(ipa);
kfree(ipa);
ipa_clock_exit(clock);
ipa_power_exit(power);

return 0;
}
Expand Down
Loading

0 comments on commit 8634348

Please sign in to comment.