30 Commits

Author SHA1 Message Date
Alex Elder
fc4cecf706 net: ipa: generalize register offset functions
Rename ipa_reg_offset() to be reg_offset() and move its definition
to "reg.h".  Rename ipa_reg_n_offset() to be reg_n_offset() also.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-02-10 08:06:32 +00:00
Alex Elder
81772e444d net: ipa: start generalizing "ipa_reg"
IPA register definitions have evolved with each new version.  The
changes required to support more than 32 endpoints in IPA v5.0 made
it best to define a unified mechanism for defining registers and
their fields.

GSI register definitions, meanwhile, have remained fairly stable.
And even as the total number of IPA endpoints goes beyond 32, the
number of GSI channels on a given EE that underly endpoints still
remains 32 or less.

Despite that, GSI v3.0 (which is used with IPA v5.0) extends the
number of channels (and events) it supports to be about 256, and as
a result, many GSI register definitions must change significantly.
To address this, we'll use the same "ipa_reg" mechanism to define
the GSI registers.

As a first step in generalizing the "ipa_reg" to also support GSI
registers, isolate the definitions of the "ipa_reg" and "ipa_regs"
structure types (and some supporting macros) into a new header file,
and remove the "ipa_" and "IPA_" from symbol names.

Separate the IPA register ID validity checking from the generic
check that a register ID is in range.  Aside from that, this is
intended to have no functional effect on the code.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-02-10 08:06:32 +00:00
Caleb Connolly
df54fde451 net: ipa: use dev PM wakeirq handling
Replace the enable_irq_wake() call with one to dev_pm_set_wake_irq()
instead. This will let the dev PM framework automatically manage the
the wakeup capability of the ipa IRQ and ensure that userspace requests
to enable/disable wakeup for the IPA via sysfs are respected.

Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
Reviewed-by: Alex Elder <elder@linaro.org>
Link: https://lore.kernel.org/r/20230127202758.2913612-1-caleb.connolly@linaro.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2023-01-31 15:24:38 +01:00
Jakub Kicinski
b3c588cd55 Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
drivers/net/ipa/ipa_interrupt.c
drivers/net/ipa/ipa_interrupt.h
  9ec9b2a30853 ("net: ipa: disable ipa interrupt during suspend")
  8e461e1f092b ("net: ipa: introduce ipa_interrupt_enable()")
  d50ed3558719 ("net: ipa: enable IPA interrupt handlers separate from registration")
https://lore.kernel.org/all/20230119114125.5182c7ab@canb.auug.org.au/
https://lore.kernel.org/all/79e46152-8043-a512-79d9-c3b905462774@tessares.net/

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-01-20 12:28:23 -08:00
Caleb Connolly
9ec9b2a308 net: ipa: disable ipa interrupt during suspend
The IPA interrupt can fire when pm_runtime is disabled due to it racing
with the PM suspend/resume code. This causes a splat in the interrupt
handler when it tries to call pm_runtime_get().

Explicitly disable the interrupt in our ->suspend callback, and
re-enable it in ->resume to avoid this. If there is an interrupt pending
it will be handled after resuming. The interrupt is a wake_irq, as a
result even when disabled if it fires it will cause the system to wake
from suspend as well as cancel any suspend transition that may be in
progress. If there is an interrupt pending, the ipa_isr_thread handler
will be called after resuming.

Fixes: 1aac309d3207 ("net: ipa: use autosuspend")
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
Reviewed-by: Alex Elder <elder@linaro.org>
Link: https://lore.kernel.org/r/20230115175925.465918-1-caleb.connolly@linaro.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-01-17 19:04:13 -08:00
Alex Elder
bfb798545d net: ipa: don't maintain IPA interrupt handler array
We can call the two IPA interrupt handler functions directly;
there's no need to maintain the array of handler function pointers
any more.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-01-05 22:03:14 -08:00
Alex Elder
8d8d3f1a3e net: ipa: kill ipa_interrupt_add()
The dynamic assignment of IPA interrupt handlers isn't needed; we
only handle three IPA interrupt types, and their handler functions
are now assigned directly.  We can get rid of ipa_interrupt_add()
and ipa_interrupt_remove() now, because they serve no purpose.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-01-05 22:03:14 -08:00
Alex Elder
482ae3a993 net: ipa: register IPA interrupt handlers directly
Declare the microcontroller IPA interrupt handler publicly, and
assign it directly in ipa_interrupt_config().  Make the SUSPEND IPA
interrupt handler public, and rename it ipa_power_suspend_handler().
Assign it directly in ipa_interrupt_config() as well.

This makes it unnecessary to do this in ipa_interrupt_add().  Make
similar changes for removing IPA interrupt handlers.

The next two patches will finish the cleanup, removing the
add/remove functions and the handler array entirely.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-01-05 22:03:14 -08:00
Alex Elder
d50ed35587 net: ipa: enable IPA interrupt handlers separate from registration
Expose ipa_interrupt_enable() and have functions that register
IPA interrupt handlers enable them directly, rather than having the
registration process do that.  Do the same for disabling IPA
interrupt handlers.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-01-05 22:03:14 -08:00
Alex Elder
8e461e1f09 net: ipa: introduce ipa_interrupt_enable()
Create new function ipa_interrupt_enable() to encapsulate enabling
one of the IPA interrupt types.  Introduce ipa_interrupt_disable()
to reverse that operation.  Add a helper function to factor out the
common register update used by both.

Use these in ipa_interrupt_add() and ipa_interrupt_remove().

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-01-05 22:03:13 -08:00
Alex Elder
d9d71a89f2 net: ipa: use proper endpoint mask for suspend
It is now possible for a system to have more than 32 endpoints.  As
a result, registers related to endpoint suspend are parameterized,
with 32 endpoints represented in one more registers.

In ipa_interrupt_suspend_control(), the IPA_SUSPEND_EN register
offset is determined properly, but the bit mask used still assumes
the number of enpoints won't exceed 32.  This is a bug.  Fix it.

Fixes: f298ba785e2d ("net: ipa: add a parameter to suspend registers")
Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-01-01 12:01:14 +00:00
Alex Elder
88de767240 net: ipa: use a bitmap for available endpoints
Similar to the previous patch, replace the 32-bit unsigned used to
track endpoints supported by hardware with a Linux bitmap, to allow
an arbitrary number of endpoints to be represented.

Move ipa_endpoint_deconfig() above ipa_endpoint_config() and use
it in the error path of the latter function.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-11-04 10:16:53 +00:00
Alex Elder
f298ba785e net: ipa: add a parameter to suspend registers
The SUSPEND_INFO, SUSPEND_EN, SUSPEND_CLR registers represent
endpoint IDs in a bit mask.  When more than 32 endpoints are
supported, these registers will be replicated as needed to represent
the number of supported endpoints.  Update the definitions of these
registers to have a stride of 4 bytes, and update the code that
operates them to select the proper offset and bit.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-11-04 10:16:53 +00:00
Alex Elder
a4388da51a net: ipa: update copyrights
Some source files state copyright dates that are earlier than the
last modification of the file.  Change the copyright year to 2022 in
all such cases.

Signed-off-by: Alex Elder <elder@linaro.org>
Link: https://lore.kernel.org/r/20220930224549.3503434-1-elder@linaro.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-10-03 16:49:20 -07:00
Alex Elder
6a244b75cf net: ipa: introduce ipa_reg()
Create a new function that returns a register descriptor given its
ID.  Change ipa_reg_offset() and ipa_reg_n_offset() so they take a
register descriptor argument rather than an IPA pointer and register
ID.  Have them accept null pointers (and return an invalid 0 offset),
to avoid the need for excessive error checking.  (A warning is issued
whenever ipa_reg() returns 0).

Call ipa_reg() or ipa_reg_n() to look up information about the
register before calls to ipa_reg_offset() and ipa_reg_n_offset().
Delay looking up offsets until they're needed to read or write
registers.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-09-27 18:42:50 -07:00
Alex Elder
6bfb753850 net: ipa: use IPA register IDs to determine offsets
Expose two inline functions that return the offset for a register
whose ID is provided; one of them takes an additional argument
that's used for registers that are parameterized.  These both use
a common helper function __ipa_reg_offset(), which just uses the
offset symbols already defined.

Replace all references to the offset macros defined for IPA
registers with calls to ipa_reg_offset() or ipa_reg_n_offset().

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-09-27 18:42:49 -07:00
Jakub Kicinski
1172aa6e4a net: ipa: don't proceed to out-of-bound write
GCC 12 seems upset that we check ipa_irq against array bound
but then proceed, anyway:

drivers/net/ipa/ipa_interrupt.c: In function ‘ipa_interrupt_add’:
drivers/net/ipa/ipa_interrupt.c:196:27: warning: array subscript 30 is above array bounds of ‘void (*[30])(struct ipa *, enum ipa_irq_id)’ [-Warray-bounds]
  196 |         interrupt->handler[ipa_irq] = handler;
      |         ~~~~~~~~~~~~~~~~~~^~~~~~~~~
drivers/net/ipa/ipa_interrupt.c:42:27: note: while referencing ‘handler’
   42 |         ipa_irq_handler_t handler[IPA_IRQ_COUNT];
      |                           ^~~~~~~

Reviewed-by: Alex Elder <elder@linaro.org>
Link: https://lore.kernel.org/r/20220519004417.2109886-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-05-19 18:44:51 -07:00
Alex Elder
1aac309d32 net: ipa: use autosuspend
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-22 09:44:17 +01:00
Alex Elder
c3f115aa5e net: ipa: kill ipa_clock_get()
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-20 14:45:47 +01:00
Alex Elder
7ebd168c3b net: ipa: have ipa_clock_get() return a value
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-11 13:31:55 +01:00
Alex Elder
176086d870 net: ipa: kill ipa_interrupt_process_all()
Now that ipa_isr_thread() is a simple wrapper that gets a clock
reference around ipa_interrupt_process_all(), get rid of the
called function and just open-code it in ipa_isr_thread().

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-07-27 21:02:06 +01:00
Alex Elder
fe6a327979 net: ipa: get rid of some unneeded IPA interrupt code
The pending IPA interrupts are checked by ipa_isr_thread(), and
interrupts are processed only if an enabled interrupt has a
condition pending.  But ipa_interrupt_process_all() now makes the
same check, so the one in ipa_isr_thread() can just be skipped.

Also in ipa_isr_thread(), any interrupt conditions pending which are
not enabled are cleared.  Here too, ipa_interrupt_process_all() now
clears such excess interrupt conditions, so ipa_isr_thread() doesn't
have to.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-07-27 21:02:06 +01:00
Alex Elder
e70e410f8e net: ipa: clear disabled IPA interrupt conditions
We ignore any IPA interrupt that has no handler.  If any interrupt
conditions without a handler exist when an IPA interrupt occurs,
clear those conditions.  Add a debug message to report which ones
are being cleared.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-07-27 21:02:06 +01:00
Alex Elder
937a0da432 net: ipa: make IPA interrupt handler threaded only
When the IPA interrupt handler runs, the IPA core clock must already
be operational, and the interconnect providing access by the AP to
IPA config space must be enabled too.

Currently we ensure this by taking a top-level "stay awake" IPA
clock reference, but that will soon go away.  In preparation for
that, move all handling for the IPA IRQ into the thread function.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-07-27 21:02:06 +01:00
Alex Elder
1118a14710 net: ipa: set up IPA interrupts earlier
Initialization of the IPA driver has several phases:
   - "init" phase can be done without any access to IPA hardware
   - "config" phase requires the IPA hardware to be clocked
   - "setup" phase requires the GSI layer to be functional

Currently, initialization for the IPA interrupt handling code occurs
in the setup phase.  It requires access to the IPA hardware but does
not need GSI, so it can be moved to the config phase instead.

Call the interrupt configuration function early in ipa_config()
rather than from ipa_setup().  Rename ipa_interrupt_setup() to be
ipa_interrupt_config(), and ipa_interrupt_teardown() to be
ipa_interupt_deconfig(), so their names properly indicate when
they get called.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-07-26 23:09:18 +01:00
Alex Elder
5bc5588466 net: ipa: use WARN_ON() rather than assertions
I've added commented assertions to record certain properties that
can be assumed to hold in certain places in the IPA code.  Convert
these into real WARN_ON() calls so the assertions are actually
checked, using the standard WARN_ON() mechanism.

Where errors can be returned, return an error if a warning is
triggered.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-07-26 22:38:11 +01:00
Alex Elder
e666aa978a net: ipa: support IPA interrupt addresses for IPA v4.7
Starting with IPA v4.7, registers related to IPA interrupts are
located at a fixed offset 0x1000 above than the addresses used for
earlier versions.  Define and use functions to provide the offset to
use for these registers based on IPA version.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-03-25 17:22:30 -07:00
Alex Elder
f3ae1616c5 net: ipa: fix two inconsistent IPA register names
Rename two suspend IRQ registers so they follow the IPA_REG_IRQ_xxx
naming convention used elsewhere.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-11-18 15:53:48 -08:00
Alex Elder
d1b5126af0 net: ipa: enable wakeup on IPA interrupt
Now that we handle wakeup interrupts properly, arrange for the IPA
interrupt to be treated as a wakeup interrupt.

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-18 17:47:07 -07:00
Alex Elder
ba764c4dad soc: qcom: ipa: clocking, interrupts, and memory
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>
2020-03-08 22:07:09 -07:00