aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/net/ipa/ipa_clock.c (follow)
AgeCommit message (Collapse)AuthorFilesLines
2021-08-22net: ipa: rename "ipa_clock.c"Alex Elder1-473/+0
Finally, rename "ipa_clock.c" to be "ipa_power.c" and "ipa_clock.h" to be "ipa_power.h". Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-22net: ipa: rename ipa_clock_* symbolsAlex Elder1-75/+73
Rename a number of functions to clarify that there is no longer a notion of an "IPA clock," but rather that the functions are more generally related to IPA power management. ipa_clock_enable() -> ipa_power_enable() ipa_clock_disable() -> ipa_power_disable() ipa_clock_rate() -> ipa_core_clock_rate() ipa_clock_init() -> ipa_power_init() ipa_clock_exit() -> ipa_power_exit() Rename the ipa_clock structure to be ipa_power. Rename all variables and fields using that structure type "power" rather than "clock". Rename the ipa_clock_data structure to be ipa_power_data, and more broadly, just substitute "power" for "clock" in places that previously represented things related to the "IPA clock". Update comments throughout. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-22net: ipa: use autosuspendAlex Elder1-8/+7
Use runtime power management autosuspend. Up until this point, we only suspended the IPA hardware for system suspend; now we'll suspend it aggressively using runtime power management, setting the initial autosuspend delay to half a second of inactivity. Replace pm_runtime_put() calls with pm_runtime_put_autosuspend(), call pm_runtime_mark_last_busy() before each of those. In places where we're shutting things down, or decrementing power references for errors, use pm_runtime_put_noidle() instead. Finally, remove ipa_runtime_idle(), so the ->runtime_suspend callback will occur if idle. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-20net: ipa: kill ipa_clock_get()Alex Elder1-17/+0
The only remaining user of the ipa_clock_{get,put}() interface is ipa_isr_thread(). Replace calls to ipa_clock_get() there calling pm_runtime_get_sync() instead. And call pm_runtime_put() there rather than ipa_clock_put(). Warn if we ever get an error. With that, we can get rid of ipa_clock_get() and ipa_clock_put(). Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-20net: ipa: fix TX queue raceAlex Elder1-0/+71
Jakub Kicinski pointed out a race condition in ipa_start_xmit() in a recently-accepted series of patches: https://lore.kernel.org/netdev/20210812195035.2816276-1-elder@linaro.org/ We are stopping the modem TX queue in that function if the power state is not active. We restart the TX queue again once hardware resume is complete. TX path Power Management ------- ---------------- pm_runtime_get(); no power Start resume Stop TX queue ... pm_runtime_put() Resume complete return NETDEV_TX_BUSY Start TX queue pm_runtime_get() Power present, transmit pm_runtime_put() (auto-suspend) The issue is that the power management (resume) activity and the network transmit activity can occur concurrently, and there's a chance the queue will be stopped *after* it has been started again. TX path Power Management ------- ---------------- Resume underway pm_runtime_get(); no power ... Resume complete Start TX queue Stop TX queue <-- No more transmits after this pm_runtime_put() return NETDEV_TX_BUSY We address this using a STARTED flag to indicate when the TX queue has been started from the resume path, and a spinlock to make the flag and queue updates happen atomically. TX path Power Management ------- ---------------- Resume underway pm_runtime_get(); no power Resume complete start TX queue \ If STARTED flag is *not* set: > atomic Stop TX queue set STARTED flag / pm_runtime_put() return NETDEV_TX_BUSY A second flag is used to address a different race that involves another path requesting power. TX path Other path Power Management ------- ---------- ---------------- pm_runtime_get_sync() Resume Start TX queue \ atomic Set STARTED flag / (do its thing) pm_runtime_put() (auto-suspend) pm_runtime_get() Mark delayed resume STARTED *is* set, so do *not* stop TX queue <-- Queue should be stopped here pm_runtime_put() return NETDEV_TX_BUSY Suspend done, resume Resume complete pm_runtime_get() Stop TX queue (STARTED is *not* set) Start TX queue \ atomic pm_runtime_put() Set STARTED flag / return NETDEV_TX_BUSY So a STOPPED flag is set in the transmit path when it has stopped the TX queue, and this pair of operations is also protected by the spinlock. The resume path only restarts the TX queue if the STOPPED flag is set. This case isn't a major problem, but it avoids the "non-trivial amount of useless work" done by the networking stack when NETDEV_TX_BUSY is returned. Fixes: 6b51f802d652b ("net: ipa: ensure hardware has power in ipa_start_xmit()") Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-14net: ipa: distinguish system from runtime suspendAlex Elder1-7/+31
Add a new flag that is set when the hardware is suspended due to a system suspend operation, distingishing it from runtime suspend. Use it in the SUSPEND IPA interrupt handler to determine whether to trigger a system resume because of the event. Define new suspend and resume power management callback functions to set and clear the new flag, respectively. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-14net: ipa: enable wakeup in ipa_power_setup()Alex Elder1-1/+10
Move the call to enable the IPA interrupt as a wakeup interrupt into ipa_power_setup(), disable it in ipa_power_teardown(). Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-11net: ipa: kill ipa_clock_get_additional()Alex Elder1-9/+0
Now that ipa_clock_get_additional() is a trivial wrapper around pm_runtime_get_if_active(), just open-code it in its only caller and delete the function. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-11net: ipa: kill IPA clock reference countAlex Elder1-71/+6
The runtime power management core code maintains a usage count. This count mirrors the IPA clock reference count, and there's no need to maintain both. So get rid of the IPA clock reference count and just rely on the runtime PM usage count to determine when the hardware should be suspended or resumed. Use pm_runtime_get_if_active() in ipa_clock_get_additional(). We care whether power is active, regardless of whether it's in use, so pass true for its ign_usage_count argument. The IPA clock mutex is just used to make enabling/disabling the clock and updating the reference count occur atomically. Without the reference count, there's no need for the mutex, so get rid of that too. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-11net: ipa: use runtime PM coreAlex Elder1-37/+38
Use the runtime power management core to cause hardware suspend and resume to occur. Enable it in ipa_clock_init() (without autosuspend), and disable it in ipa_clock_exit(). Use ipa_runtime_suspend() as the ->runtime_suspend power operation, and arrange for it to be called by having ipa_clock_get() call pm_runtime_get_sync() when the first clock reference is taken. Similarly, use ipa_runtime_resume() as the ->runtime_resume power operation, and pm_runtime_put() when the last IPA clock reference is dropped. Introduce ipa_runtime_idle() as the ->runtime_idle power operation, and have it return a non-zero value; this way suspend will never occur except when forced. Use pm_runtime_force_suspend() and pm_runtime_force_resume() as the system suspend and resume callbacks, and remove ipa_suspend() and ipa_resume(). Store a pointer to the device structure passed to ipa_clock_init(), so it can be used by ipa_clock_exit() to disable runtime power management. For now we preserve IPA clock reference counting. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-11net: ipa: resume in ipa_clock_get()Alex Elder1-26/+37
Introduce ipa_runtime_suspend() and ipa_runtime_resume(), which encapsulate the activities necessary for suspending and resuming the IPA hardware. Call these functions from ipa_clock_get() and ipa_clock_put() when the first reference is taken or last one is dropped. When the very first clock reference is taken (for ipa_config()), setup isn't complete yet, so (as before) only the core clock gets enabled. When the last clock reference is dropped (after ipa_deconfig()), ipa_teardown() will have made the setup_complete flag false, so there too, the core clock will be stopped without affecting GSI or the endpoints. Otherwise these new functions will perform the desired suspend and resume actions once setup is complete. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-11net: ipa: disable clock in suspendAlex Elder1-8/+3
Disable the IPA clock rather than dropping a reference to it in the system suspend callback. This forces the suspend to occur without affecting existing references. Similarly, enable the clock rather than taking a reference in ipa_resume(), forcing a resume without changing the reference count. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-11net: ipa: have ipa_clock_get() return a valueAlex Elder1-16/+28
We currently assume no errors occur when enabling or disabling the IPA core clock and interconnects. And although this commit exposes errors that could occur, we generally assume this won't happen in practice. This commit changes ipa_clock_get() and ipa_clock_put() so each returns a value. The values returned are meant to mimic what the runtime power management functions return, so we can set up error handling here before we make the switch. Have ipa_clock_get() increment the reference count even if it returns an error, to match the behavior of pm_runtime_get(). More details follow. When taking a reference in ipa_clock_get(), return 0 for the first reference, 1 for subsequent references, or a negative error code if an error occurs. Note that if ipa_clock_get() returns an error, we must not touch hardware; in some cases such errors now cause entire blocks of code to be skipped. When dropping a reference in ipa_clock_put(), we return 0 or an error code. The error would come from ipa_clock_disable(), which now returns what ipa_interconnect_disable() returns (either 0 or a negative error code). For now, callers ignore the return value; if an error occurs, a message will have already been logged, and little more can actually be done to improve the situation. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-05net: ipa: move IPA flags fieldAlex Elder1-2/+14
The ipa->flags field is only ever used in "ipa_clock.c", related to suspend/resume activity. Move the definition of the ipa_flag enumerated type to "ipa_clock.c". And move the flags field from the ipa structure and to the ipa_clock structure. Rename the type and its values to include "power" or "POWER" in the name. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-05net: ipa: move ipa_suspend_handler()Alex Elder1-0/+34
Move ipa_suspend_handler() into "ipa_clock.c" from "ipa_main.c", to group with the reset of the suspend/resume code. This IPA interrupt is triggered if an IPA RX endpoint is suspended but has a packet to be delivered. Introduce ipa_power_setup() and ipa_power_teardown() to add and remove the handler for the IPA SUSPEND interrupt at the same place as before, while allowing the handler to remain private. The "power" naming convention will be adopted elsewhere in this file as well (soon). Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-05net: ipa: move IPA power operations to ipa_clock.cAlex Elder1-0/+62
Move ipa_suspend() and ipa_resume(), as well as the definition of the ipa_pm_ops structure into "ipa_clock.c". Make ipa_pm_ops public and declare it as extern in "ipa_clock.h". This is part of centralizing IPA power management functionality into "ipa_clock.c" (the file will eventually get a name change). Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-08-05net: ipa: improve IPA clock error messagesAlex Elder1-17/+22
Rearrange messages reported when errors occur in the IPA clock code, so that the specific interconnect is identified when an error occurs enabling or disabling it, or the core clock is indicated when an error occurs enabling it. Have ipa_interconnect_disable() return zero or the negative error value returned by the first interconnect that produced an error when disabled. For now, the callers ignore the returned value. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-12net: ipa: use dev_err_probe() in ipa_clock.cAlex Elder1-4/+5
When initializing the IPA core clock and interconnects, it's possible we'll get an EPROBE_DEFER error. This isn't really an error, it's just means we need to be re-probed later. Use dev_err_probe() to report the error rather than dev_err(). This avoids polluting the log with these "error" messages. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-01-18net: ipa: allow arbitrary number of interconnectsAlex Elder1-66/+51
Currently we assume that the IPA hardware has exactly three interconnects. But that won't be guaranteed for all platforms, so allow any number of interconnects to be specified in the configuration data. For each platform, define an array of interconnect data entries (still associated with the IPA clock structure), and record the number of entries initialized in that array. Loop over all entries in this array when initializing, enabling, disabling, or tearing down the set of interconnects. With this change we no longer need the ipa_interconnect_id enumerated type, so get rid of it. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2021-01-18net: ipa: clean up interconnect initializationAlex Elder1-36/+47
Pass an the address of an IPA interconnect structure and its configuration data to ipa_interconnect_init_one() and have that function initialize all the structure's fields. Change the function to simply return an error code. Introduce ipa_interconnect_exit_one() to encapsulate the cleanup of an IPA interconnect structure. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2021-01-18net: ipa: add interconnect name to configuration dataAlex Elder1-3/+3
Add the name to the configuration data for each interconnect. Use this information rather than a constant string during initialization. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2021-01-18net: ipa: store average and peak interconnect bandwidthAlex Elder1-36/+52
Add fields in the ipa_interconnect structure to hold the average and peak bandwidth values for the interconnect. Pass the configuring data for interconnects to ipa_interconnect_init() so these values can be recorded, and use them when enabling the interconnects. There's no longer any need to keep a copy of the interconnect data after initialization. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2021-01-18net: ipa: introduce an IPA interconnect structureAlex Elder1-25/+34
Rather than having separate pointers for the memory, imem, and config interconnect paths, maintain an array of ipa_interconnect structures each of which contains a pointer to a path. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2021-01-18net: ipa: don't return an error from ipa_interconnect_disable()Alex Elder1-20/+11
If disabling interconnects fails there's not a lot we can do. The only two callers of ipa_interconnect_disable() ignore the return value, so just give the function a void return type. Print an error message if disabling any of the interconnects is not successful. Return (and print) only the first error seen. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2021-01-18net: ipa: rename interconnect settingsAlex Elder1-10/+10
Use "bandwidth" rather than "rate" in describing the average and peak values to use for IPA interconnects. They should have been named that way to begin with. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-12-23net: ipa: fix interconnect enable bugAlex Elder1-2/+2
When the core clock rate and interconnect bandwidth specifications were moved into configuration data, a copy/paste bug was introduced, causing the memory interconnect bandwidth to be set three times rather than enabling the three different interconnects. Fix this bug. Fixes: 91d02f9551501 ("net: ipa: use config data for clocking") Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Georgi Djakov <georgi.djakov@linaro.org> Link: https://lore.kernel.org/r/20201222151613.5730-1-elder@linaro.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-11-20net: ipa: use config data for clockingAlex Elder1-20/+20
Stop assuming a fixed IPA core clock rate and interconnect bandwidths. Use the configuration data defined for these things instead. Get rid of the previously-used constants. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-11-20net: ipa: define clock and interconnect dataAlex Elder1-1/+6
Define a new type of configuration data, used to initialize the IPA core clock and interconnects. This is the first of three patches, and defines the data types and interface but doesn't yet use them. Switch the return value if there is no matching configuration data to ENODEV instead of ENOTSUPP (to avoid using the nonstandard errno). Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-09-18net: ipa: manage endpoints separate from clockAlex Elder1-10/+4
Currently, when (before) the last IPA clock reference is dropped, all endpoints are suspended. And whenever the first IPA clock reference is taken, all endpoints are resumed (or started). In most cases there's no need to start endpoints when the clock starts. So move the calls to ipa_endpoint_suspend() and ipa_endpoint_resume() out of ipa_clock_put() and ipa_clock_get(), respectiely. Instead, only suspend endpoints when handling a system suspend, and only resume endpoints when handling a system resume. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2020-09-18net: ipa: use refcount_t for IPA clock reference countAlex Elder1-7/+7
Take advantage of the checking provided by refcount_t, rather than using a plain atomic to represent the IPA clock reference count. Note that we need to *set* the value to 1 in ipa_clock_get() rather than incrementing it from 0 (because doing that is considered an error for a refcount_t). Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2020-07-13net: ipa: fix kerneldoc commentsAlex Elder1-1/+1
This commit affects comments (and in one case, whitespace) only. Throughout the IPA code, return statements are documented using "@Return:", whereas they should use "Return:" instead. Fix these mistakes. In function definitions, some parameters are missing their comment to describe them. And in structure definitions, some fields are missing their comment to describe them. Add these missing descriptions. Some arguments changed name and type along the way, but their descriptions were not updated (an endpoint pointer is now used in many places that previously used an endpoint ID). Fix these incorrect parameter descriptions. In the description for the ipa_clock structure, one field had a semicolon instead of a colon in its description. Fix this. Add a missing function description for ipa_gsi_endpoint_data_empty(). All of these issues were identified when building with "W=1". Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2020-07-03net: ipa: introduce ipa_clock_rate()Alex Elder1-0/+6
Create a new function that returns the current rate of the IPA core clock. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2020-05-25drivers: ipa: print dev_err info accuratelyWang Wenhu1-2/+2
Print certain name string instead of hard-coded "memory" for dev_err output, which would be more accurate and helpful for debugging. Signed-off-by: Wang Wenhu <wenhu.wang@vivo.com> Cc: Alex Elder <elder@kernel.org> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2020-03-08soc: qcom: ipa: clocking, interrupts, and memoryAlex Elder1-0/+313
This patch incorporates three source files (and their headers). They're grouped into one patch mainly for the purpose of making the number and size of patches in this series somewhat reasonable. - "ipa_clock.c" and "ipa_clock.h" implement clocking for the IPA device. The IPA has a single core clock managed by the common clock framework. In addition, the IPA has three buses whose bandwidth is managed by the Linux interconnect framework. At this time the core clock and all three buses are either on or off; we don't yet do any more fine-grained management than that. The core clock and interconnects are enabled and disabled as a unit, using a unified clock-like abstraction, ipa_clock_get()/ipa_clock_put(). - "ipa_interrupt.c" and "ipa_interrupt.h" implement IPA interrupts. There are two hardware IRQs used by the IPA driver (the other is the GSI interrupt, described in a separate patch). Several types of interrupt are handled by the IPA IRQ handler; these are not part of data/fast path. - The IPA has a region of local memory that is accessible by the AP (and modem). Within that region are areas with certain defined purposes. "ipa_mem.c" and "ipa_mem.h" define those regions, and implement their initialization. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>