msm: ipa: initial commit of IPA driver
This is a snapshot of IPA from kernel msm-4.4 based on
commit ebc2a18351d4 ("msm: ipa: WA to get PA of sgt_tbl from wlan")
CRs-Fixed: 1077422
Change-Id: I97cf9ee9c104ac5ab5bc0577eb9413264b08a7a5
Signed-off-by: Amir Levy <alevy@codeaurora.org>
This commit is contained in:
parent
8751c8965c
commit
9659e593c8
110 changed files with 114401 additions and 0 deletions
207
Documentation/devicetree/bindings/platform/msm/ipa.txt
Normal file
207
Documentation/devicetree/bindings/platform/msm/ipa.txt
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
Qualcomm technologies inc. Internet Packet Accelerator
|
||||
|
||||
Internet Packet Accelerator (IPA) is a programmable protocol
|
||||
processor HW block. It is designed to support generic HW processing
|
||||
of UL/DL IP packets for various use cases independent of radio technology.
|
||||
|
||||
Required properties:
|
||||
|
||||
IPA node:
|
||||
|
||||
- compatible : "qcom,ipa"
|
||||
- reg: Specifies the base physical addresses and the sizes of the IPA
|
||||
registers.
|
||||
- reg-names: "ipa-base" - string to identify the IPA CORE base registers.
|
||||
"bam-base" - string to identify the IPA BAM base registers.
|
||||
"a2-bam-base" - string to identify the A2 BAM base registers.
|
||||
- interrupts: Specifies the interrupt associated with IPA.
|
||||
- interrupt-names: "ipa-irq" - string to identify the IPA core interrupt.
|
||||
"bam-irq" - string to identify the IPA BAM interrupt.
|
||||
"a2-bam-irq" - string to identify the A2 BAM interrupt.
|
||||
- qcom,ipa-hw-ver: Specifies the IPA hardware version.
|
||||
|
||||
Optional:
|
||||
|
||||
- qcom,wan-rx-ring-size: size of WAN rx ring, default is 32
|
||||
- qcom,arm-smmu: SMMU is present and ARM SMMU driver is used
|
||||
- qcom,msm-smmu: SMMU is present and QSMMU driver is used
|
||||
- qcom,smmu-s1-bypass: Boolean context flag to set SMMU to S1 bypass
|
||||
- qcom,smmu-fast-map: Boolean context flag to set SMMU to fastpath mode
|
||||
- ipa_smmu_ap: AP general purpose SMMU device
|
||||
compatible "qcom,ipa-smmu-ap-cb"
|
||||
- ipa_smmu_wlan: WDI SMMU device
|
||||
compatible "qcom,ipa-smmu-wlan-cb"
|
||||
- ipa_smmu_uc: uc SMMU device
|
||||
compatible "qcom,ipa-smmu-uc-cb"
|
||||
- qcom,smmu-disable-htw: boolean value to turn off SMMU page table caching
|
||||
- qcom,use-a2-service: determine if A2 service will be used
|
||||
- qcom,use-ipa-tethering-bridge: determine if tethering bridge will be used
|
||||
- qcom,use-ipa-bamdma-a2-bridge: determine if a2/ipa hw bridge will be used
|
||||
- qcom,ee: which EE is assigned to (non-secure) APPS from IPA-BAM POV. This
|
||||
is a number
|
||||
- qcom,ipa-hw-mode: IPA hardware mode - Normal, Virtual memory allocation,
|
||||
memory allocation over a PCIe bridge
|
||||
- qcom,msm-bus,name: String representing the client-name
|
||||
- qcom,msm-bus,num-cases: Total number of usecases
|
||||
- qcom,msm-bus,active-only: Boolean context flag for requests in active or
|
||||
dual (active & sleep) contex
|
||||
- qcom,msm-bus,num-paths: Total number of master-slave pairs
|
||||
- qcom,msm-bus,vectors-KBps: Arrays of unsigned integers representing:
|
||||
master-id, slave-id, arbitrated bandwidth
|
||||
in KBps, instantaneous bandwidth in KBps
|
||||
- qcom,ipa-bam-remote-mode: Boolean context flag to determine if ipa bam
|
||||
is in remote mode.
|
||||
- qcom,modem-cfg-emb-pipe-flt: Boolean context flag to determine if modem
|
||||
configures embedded pipe filtering rules
|
||||
- qcom,skip-uc-pipe-reset: Boolean context flag to indicate whether
|
||||
a pipe reset via the IPA uC is required
|
||||
- qcom,ipa-wdi2: Boolean context flag to indicate whether
|
||||
using wdi-2.0 or not
|
||||
- qcom,use-dma-zone: Boolean context flag to indicate whether memory
|
||||
allocations controlled by IPA driver that do not
|
||||
specify a struct device * should use GFP_DMA to
|
||||
workaround IPA HW limitations
|
||||
- qcom,use-gsi: Boolean context flag to indicate if the
|
||||
transport protocol is GSI
|
||||
- qcom,use-rg10-limitation-mitigation: Boolean context flag to activate
|
||||
the mitigation to register group 10
|
||||
AP access limitation
|
||||
- qcom,do-not-use-ch-gsi-20: Boolean context flag to activate
|
||||
software workaround for IPA limitation
|
||||
to not use GSI physical channel 20
|
||||
- qcom,tethered-flow-control: Boolean context flag to indicate whether
|
||||
apps based flow control is needed for tethered
|
||||
call.
|
||||
IPA pipe sub nodes (A2 static pipes configurations):
|
||||
|
||||
-label: two labels are supported, a2-to-ipa and ipa-to-a2 which
|
||||
supply static configuration for A2-IPA connection.
|
||||
-qcom,src-bam-physical-address: The physical address of the source BAM
|
||||
-qcom,ipa-bam-mem-type:The memory type:
|
||||
0(Pipe memory), 1(Private memory), 2(System memory)
|
||||
-qcom,src-bam-pipe-index: Source pipe index
|
||||
-qcom,dst-bam-physical-address: The physical address of the
|
||||
destination BAM
|
||||
-qcom,dst-bam-pipe-index: Destination pipe index
|
||||
-qcom,data-fifo-offset: Data fifo base offset
|
||||
-qcom,data-fifo-size: Data fifo size (bytes)
|
||||
-qcom,descriptor-fifo-offset: Descriptor fifo base offset
|
||||
-qcom,descriptor-fifo-size: Descriptor fifo size (bytes)
|
||||
|
||||
Optional properties:
|
||||
-qcom,ipa-pipe-mem: Specifies the base physical address and the
|
||||
size of the IPA pipe memory region.
|
||||
Pipe memory is a feature which may be supported by the
|
||||
target (HW platform). The Driver support using pipe
|
||||
memory instead of system memory. In case this property
|
||||
will not appear in the IPA DTS entry, the driver will
|
||||
use system memory.
|
||||
- clocks: This property shall provide a list of entries each of which
|
||||
contains a phandle to clock controller device and a macro that is
|
||||
the clock's name in hardware.This should be "clock_rpm" as clock
|
||||
controller phandle and "clk_ipa_clk" as macro for "iface_clk"
|
||||
- clock-names: This property shall contain the clock input names used
|
||||
by driver in same order as the clocks property.This should be "iface_clk"
|
||||
|
||||
IPA SMMU sub nodes
|
||||
|
||||
-compatible: "qcom,ipa-smmu-ap-cb" - represents the AP context bank.
|
||||
|
||||
-compatible: "qcom,ipa-smmu-wlan-cb" - represents IPA WLAN context bank.
|
||||
|
||||
-compatible: "qcom,ipa-smmu-uc-cb" - represents IPA uC context bank (for uC
|
||||
offload scenarios).
|
||||
- iommus : the phandle and stream IDs for the SMMU used by this root
|
||||
|
||||
- qcom,iova-mapping: specifies the start address and size of iova space.
|
||||
|
||||
IPA SMP2P sub nodes
|
||||
|
||||
-compatible: "qcom,smp2pgpio-map-ipa-1-out" - represents the out gpio from
|
||||
ipa driver to modem.
|
||||
|
||||
-compatible: "qcom,smp2pgpio-map-ipa-1-in" - represents the in gpio to
|
||||
ipa driver from modem.
|
||||
|
||||
-gpios: Binding to the gpio defined in XXX-smp2p.dtsi
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
qcom,ipa@fd4c0000 {
|
||||
compatible = "qcom,ipa";
|
||||
reg = <0xfd4c0000 0x26000>,
|
||||
<0xfd4c4000 0x14818>;
|
||||
<0xfc834000 0x7000>;
|
||||
reg-names = "ipa-base", "bam-base"; "a2-bam-base";
|
||||
interrupts = <0 252 0>,
|
||||
<0 253 0>;
|
||||
<0 29 1>;
|
||||
interrupt-names = "ipa-irq", "bam-irq"; "a2-bam-irq";
|
||||
qcom,ipa-hw-ver = <1>;
|
||||
clocks = <&clock_rpm clk_ipa_clk>;
|
||||
clock-names = "iface_clk";
|
||||
|
||||
qcom,msm-bus,name = "ipa";
|
||||
qcom,msm-bus,num-cases = <3>;
|
||||
qcom,msm-bus,num-paths = <2>;
|
||||
qcom,msm-bus,vectors-KBps =
|
||||
<90 512 0 0>, <90 585 0 0>, /* No vote */
|
||||
<90 512 100000 800000>, <90 585 100000 800000>, /* SVS */
|
||||
<90 512 100000 1200000>, <90 585 100000 1200000>; /* PERF */
|
||||
qcom,bus-vector-names = "MIN", "SVS", "PERF";
|
||||
|
||||
qcom,pipe1 {
|
||||
label = "a2-to-ipa";
|
||||
qcom,src-bam-physical-address = <0xfc834000>;
|
||||
qcom,ipa-bam-mem-type = <0>;
|
||||
qcom,src-bam-pipe-index = <1>;
|
||||
qcom,dst-bam-physical-address = <0xfd4c0000>;
|
||||
qcom,dst-bam-pipe-index = <6>;
|
||||
qcom,data-fifo-offset = <0x1000>;
|
||||
qcom,data-fifo-size = <0xd00>;
|
||||
qcom,descriptor-fifo-offset = <0x1d00>;
|
||||
qcom,descriptor-fifo-size = <0x300>;
|
||||
};
|
||||
|
||||
qcom,pipe2 {
|
||||
label = "ipa-to-a2";
|
||||
qcom,src-bam-physical-address = <0xfd4c0000>;
|
||||
qcom,ipa-bam-mem-type = <0>;
|
||||
qcom,src-bam-pipe-index = <7>;
|
||||
qcom,dst-bam-physical-address = <0xfc834000>;
|
||||
qcom,dst-bam-pipe-index = <0>;
|
||||
qcom,data-fifo-offset = <0x00>;
|
||||
qcom,data-fifo-size = <0xd00>;
|
||||
qcom,descriptor-fifo-offset = <0xd00>;
|
||||
qcom,descriptor-fifo-size = <0x300>;
|
||||
};
|
||||
|
||||
/* smp2p gpio information */
|
||||
qcom,smp2pgpio_map_ipa_1_out {
|
||||
compatible = "qcom,smp2pgpio-map-ipa-1-out";
|
||||
gpios = <&smp2pgpio_ipa_1_out 0 0>;
|
||||
};
|
||||
|
||||
qcom,smp2pgpio_map_ipa_1_in {
|
||||
compatible = "qcom,smp2pgpio-map-ipa-1-in";
|
||||
gpios = <&smp2pgpio_ipa_1_in 0 0>;
|
||||
};
|
||||
|
||||
ipa_smmu_ap: ipa_smmu_ap {
|
||||
compatible = "qcom,ipa-smmu-ap-cb";
|
||||
iommus = <&anoc2_smmu 0x30>;
|
||||
qcom,iova-mapping = <0x10000000 0x40000000>;
|
||||
};
|
||||
|
||||
ipa_smmu_wlan: ipa_smmu_wlan {
|
||||
compatible = "qcom,ipa-smmu-wlan-cb";
|
||||
iommus = <&anoc2_smmu 0x31>;
|
||||
};
|
||||
|
||||
ipa_smmu_uc: ipa_smmu_uc {
|
||||
compatible = "qcom,ipa-smmu-uc-cb";
|
||||
iommus = <&anoc2_smmu 0x32>;
|
||||
qcom,iova-mapping = <0x40000000 0x20000000>;
|
||||
};
|
||||
};
|
||||
18
Documentation/devicetree/bindings/platform/msm/rmnet_ipa.txt
Normal file
18
Documentation/devicetree/bindings/platform/msm/rmnet_ipa.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
* Qualcomm Technologies, Inc. RmNet IPA driver module
|
||||
|
||||
This module enables embedded data calls using IPA HW.
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "qcom,rmnet-ipa"
|
||||
|
||||
Optional:
|
||||
- qcom,rmnet-ipa-ssr: determine if modem SSR is supported
|
||||
- qcom,ipa-loaduC: indicate that ipa uC should be loaded
|
||||
- qcom,ipa-advertise-sg-support: determine how to respond to a query
|
||||
regarding scatter-gather capability
|
||||
|
||||
Example:
|
||||
qcom,rmnet-ipa {
|
||||
compatible = "qcom,rmnet-ipa";
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
* Qualcomm Technologies, Inc. RmNet IPA driver module
|
||||
|
||||
This module enables embedded data calls using IPA v3 HW.
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "qcom,rmnet-ipa3"
|
||||
|
||||
Optional:
|
||||
- qcom,rmnet-ipa-ssr: determine if modem SSR is supported
|
||||
- qcom,ipa-loaduC: indicate that ipa uC should be loaded
|
||||
- qcom,ipa-advertise-sg-support: determine how to respond to a query
|
||||
regarding scatter-gather capability
|
||||
|
||||
Example:
|
||||
qcom,rmnet-ipa3 {
|
||||
compatible = "qcom,rmnet-ipa3";
|
||||
}
|
||||
|
||||
|
|
@ -8,3 +8,5 @@ endif
|
|||
source "drivers/platform/goldfish/Kconfig"
|
||||
|
||||
source "drivers/platform/chrome/Kconfig"
|
||||
|
||||
source "drivers/platform/msm/Kconfig"
|
||||
|
|
|
|||
|
|
@ -7,3 +7,4 @@ obj-$(CONFIG_MIPS) += mips/
|
|||
obj-$(CONFIG_OLPC) += olpc/
|
||||
obj-$(CONFIG_GOLDFISH) += goldfish/
|
||||
obj-$(CONFIG_CHROME_PLATFORMS) += chrome/
|
||||
obj-$(CONFIG_ARCH_QCOM) += msm/
|
||||
|
|
|
|||
68
drivers/platform/msm/Kconfig
Normal file
68
drivers/platform/msm/Kconfig
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
menu "Qualcomm technologies inc. MSM specific device drivers"
|
||||
depends on ARCH_QCOM
|
||||
|
||||
config IPA
|
||||
tristate "IPA support"
|
||||
depends on SPS && NET
|
||||
help
|
||||
This driver supports the Internet Packet Accelerator (IPA) core.
|
||||
IPA is a programmable protocol processor HW block.
|
||||
It is designed to support generic HW processing of UL/DL IP packets
|
||||
for various use cases independent of radio technology.
|
||||
The driver support client connection and configuration
|
||||
for the IPA core.
|
||||
Kernel and user-space processes can call the IPA driver
|
||||
to configure IPA core.
|
||||
|
||||
config RMNET_IPA
|
||||
tristate "IPA RMNET WWAN Network Device"
|
||||
depends on IPA && MSM_QMI_INTERFACE
|
||||
help
|
||||
This WWAN Network Driver implements network stack class device.
|
||||
It supports Embedded data transfer from A7 to Q6. Configures IPA HW
|
||||
for RmNet Data Driver and also exchange of QMI messages between
|
||||
A7 and Q6 IPA-driver.
|
||||
|
||||
config GSI
|
||||
bool "GSI support"
|
||||
help
|
||||
This driver provides the transport needed to talk to the
|
||||
IPA core. It replaces the BAM transport used previously.
|
||||
|
||||
The GSI connects to a peripheral component via uniform TLV
|
||||
interface, and allows it to interface with other peripherals
|
||||
and CPUs over various types of interfaces such as MHI, xDCI,
|
||||
xHCI, GPI, WDI, Ethernet, etc.
|
||||
|
||||
config IPA3
|
||||
tristate "IPA3 support"
|
||||
depends on GSI && NET
|
||||
help
|
||||
This driver supports the Internet Packet Accelerator (IPA3) core.
|
||||
IPA is a programmable protocol processor HW block.
|
||||
It is designed to support generic HW processing of UL/DL IP packets
|
||||
for various use cases independent of radio technology.
|
||||
The driver support client connection and configuration
|
||||
for the IPA core.
|
||||
Kernel and user-space processes can call the IPA driver
|
||||
to configure IPA core.
|
||||
|
||||
config RMNET_IPA3
|
||||
tristate "IPA3 RMNET WWAN Network Device"
|
||||
depends on IPA3 && MSM_QMI_INTERFACE
|
||||
help
|
||||
This WWAN Network Driver implements network stack class device.
|
||||
It supports Embedded data transfer from A7 to Q6. Configures IPA HW
|
||||
for RmNet Data Driver and also exchange of QMI messages between
|
||||
A7 and Q6 IPA-driver.
|
||||
|
||||
config IPA_UT
|
||||
tristate "IPA Unit-Test Framework and Test Suites"
|
||||
depends on IPA3 && DEBUG_FS
|
||||
help
|
||||
This Module implements IPA in-kernel test framework.
|
||||
The framework supports defining and running tests, grouped
|
||||
into suites according to the sub-unit of the IPA being tested.
|
||||
The user interface to run and control the tests is debugfs file
|
||||
system.
|
||||
endmenu
|
||||
6
drivers/platform/msm/Makefile
Normal file
6
drivers/platform/msm/Makefile
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# Makefile for the MSM specific device drivers.
|
||||
#
|
||||
obj-$(CONFIG_GSI) += gsi/
|
||||
obj-$(CONFIG_IPA) += ipa/
|
||||
obj-$(CONFIG_IPA3) += ipa/
|
||||
5
drivers/platform/msm/ipa/Makefile
Normal file
5
drivers/platform/msm/ipa/Makefile
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
obj-$(CONFIG_IPA) += ipa_v2/ ipa_clients/ ipa_common
|
||||
obj-$(CONFIG_IPA3) += ipa_v3/ ipa_clients/ ipa_common
|
||||
obj-$(CONFIG_IPA_UT) += test/
|
||||
|
||||
ipa_common += ipa_api.o ipa_rm.o ipa_rm_dependency_graph.o ipa_rm_peers_list.o ipa_rm_resource.o ipa_rm_inactivity_timer.o
|
||||
2931
drivers/platform/msm/ipa/ipa_api.c
Normal file
2931
drivers/platform/msm/ipa/ipa_api.c
Normal file
File diff suppressed because it is too large
Load diff
400
drivers/platform/msm/ipa/ipa_api.h
Normal file
400
drivers/platform/msm/ipa/ipa_api.h
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
/* Copyright (c) 2015-2016, 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/ipa_mhi.h>
|
||||
#include <linux/ipa_uc_offload.h>
|
||||
#include "ipa_common_i.h"
|
||||
|
||||
#ifndef _IPA_API_H_
|
||||
#define _IPA_API_H_
|
||||
|
||||
struct ipa_api_controller {
|
||||
int (*ipa_connect)(const struct ipa_connect_params *in,
|
||||
struct ipa_sps_params *sps, u32 *clnt_hdl);
|
||||
|
||||
int (*ipa_disconnect)(u32 clnt_hdl);
|
||||
|
||||
int (*ipa_reset_endpoint)(u32 clnt_hdl);
|
||||
|
||||
int (*ipa_clear_endpoint_delay)(u32 clnt_hdl);
|
||||
|
||||
int (*ipa_disable_endpoint)(u32 clnt_hdl);
|
||||
|
||||
int (*ipa_cfg_ep)(u32 clnt_hdl, const struct ipa_ep_cfg *ipa_ep_cfg);
|
||||
|
||||
int (*ipa_cfg_ep_nat)(u32 clnt_hdl,
|
||||
const struct ipa_ep_cfg_nat *ipa_ep_cfg);
|
||||
|
||||
int (*ipa_cfg_ep_hdr)(u32 clnt_hdl,
|
||||
const struct ipa_ep_cfg_hdr *ipa_ep_cfg);
|
||||
|
||||
int (*ipa_cfg_ep_hdr_ext)(u32 clnt_hdl,
|
||||
const struct ipa_ep_cfg_hdr_ext *ipa_ep_cfg);
|
||||
|
||||
int (*ipa_cfg_ep_mode)(u32 clnt_hdl,
|
||||
const struct ipa_ep_cfg_mode *ipa_ep_cfg);
|
||||
|
||||
int (*ipa_cfg_ep_aggr)(u32 clnt_hdl,
|
||||
const struct ipa_ep_cfg_aggr *ipa_ep_cfg);
|
||||
|
||||
int (*ipa_cfg_ep_deaggr)(u32 clnt_hdl,
|
||||
const struct ipa_ep_cfg_deaggr *ipa_ep_cfg);
|
||||
|
||||
int (*ipa_cfg_ep_route)(u32 clnt_hdl,
|
||||
const struct ipa_ep_cfg_route *ipa_ep_cfg);
|
||||
|
||||
int (*ipa_cfg_ep_holb)(u32 clnt_hdl,
|
||||
const struct ipa_ep_cfg_holb *ipa_ep_cfg);
|
||||
|
||||
int (*ipa_cfg_ep_cfg)(u32 clnt_hdl,
|
||||
const struct ipa_ep_cfg_cfg *ipa_ep_cfg);
|
||||
|
||||
int (*ipa_cfg_ep_metadata_mask)(u32 clnt_hdl,
|
||||
const struct ipa_ep_cfg_metadata_mask *ipa_ep_cfg);
|
||||
|
||||
int (*ipa_cfg_ep_holb_by_client)(enum ipa_client_type client,
|
||||
const struct ipa_ep_cfg_holb *ipa_ep_cfg);
|
||||
|
||||
int (*ipa_cfg_ep_ctrl)(u32 clnt_hdl,
|
||||
const struct ipa_ep_cfg_ctrl *ep_ctrl);
|
||||
|
||||
int (*ipa_add_hdr)(struct ipa_ioc_add_hdr *hdrs);
|
||||
|
||||
int (*ipa_del_hdr)(struct ipa_ioc_del_hdr *hdls);
|
||||
|
||||
int (*ipa_commit_hdr)(void);
|
||||
|
||||
int (*ipa_reset_hdr)(void);
|
||||
|
||||
int (*ipa_get_hdr)(struct ipa_ioc_get_hdr *lookup);
|
||||
|
||||
int (*ipa_put_hdr)(u32 hdr_hdl);
|
||||
|
||||
int (*ipa_copy_hdr)(struct ipa_ioc_copy_hdr *copy);
|
||||
|
||||
int (*ipa_add_hdr_proc_ctx)(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs);
|
||||
|
||||
int (*ipa_del_hdr_proc_ctx)(struct ipa_ioc_del_hdr_proc_ctx *hdls);
|
||||
|
||||
int (*ipa_add_rt_rule)(struct ipa_ioc_add_rt_rule *rules);
|
||||
|
||||
int (*ipa_del_rt_rule)(struct ipa_ioc_del_rt_rule *hdls);
|
||||
|
||||
int (*ipa_commit_rt)(enum ipa_ip_type ip);
|
||||
|
||||
int (*ipa_reset_rt)(enum ipa_ip_type ip);
|
||||
|
||||
int (*ipa_get_rt_tbl)(struct ipa_ioc_get_rt_tbl *lookup);
|
||||
|
||||
int (*ipa_put_rt_tbl)(u32 rt_tbl_hdl);
|
||||
|
||||
int (*ipa_query_rt_index)(struct ipa_ioc_get_rt_tbl_indx *in);
|
||||
|
||||
int (*ipa_mdfy_rt_rule)(struct ipa_ioc_mdfy_rt_rule *rules);
|
||||
|
||||
int (*ipa_add_flt_rule)(struct ipa_ioc_add_flt_rule *rules);
|
||||
|
||||
int (*ipa_del_flt_rule)(struct ipa_ioc_del_flt_rule *hdls);
|
||||
|
||||
int (*ipa_mdfy_flt_rule)(struct ipa_ioc_mdfy_flt_rule *rules);
|
||||
|
||||
int (*ipa_commit_flt)(enum ipa_ip_type ip);
|
||||
|
||||
int (*ipa_reset_flt)(enum ipa_ip_type ip);
|
||||
|
||||
int (*allocate_nat_device)(struct ipa_ioc_nat_alloc_mem *mem);
|
||||
|
||||
int (*ipa_nat_init_cmd)(struct ipa_ioc_v4_nat_init *init);
|
||||
|
||||
int (*ipa_nat_dma_cmd)(struct ipa_ioc_nat_dma_cmd *dma);
|
||||
|
||||
int (*ipa_nat_del_cmd)(struct ipa_ioc_v4_nat_del *del);
|
||||
|
||||
int (*ipa_send_msg)(struct ipa_msg_meta *meta, void *buff,
|
||||
ipa_msg_free_fn callback);
|
||||
|
||||
int (*ipa_register_pull_msg)(struct ipa_msg_meta *meta,
|
||||
ipa_msg_pull_fn callback);
|
||||
|
||||
int (*ipa_deregister_pull_msg)(struct ipa_msg_meta *meta);
|
||||
|
||||
int (*ipa_register_intf)(const char *name,
|
||||
const struct ipa_tx_intf *tx,
|
||||
const struct ipa_rx_intf *rx);
|
||||
|
||||
int (*ipa_register_intf_ext)(const char *name,
|
||||
const struct ipa_tx_intf *tx,
|
||||
const struct ipa_rx_intf *rx,
|
||||
const struct ipa_ext_intf *ext);
|
||||
|
||||
int (*ipa_deregister_intf)(const char *name);
|
||||
|
||||
int (*ipa_set_aggr_mode)(enum ipa_aggr_mode mode);
|
||||
|
||||
int (*ipa_set_qcncm_ndp_sig)(char sig[3]);
|
||||
|
||||
int (*ipa_set_single_ndp_per_mbim)(bool enable);
|
||||
|
||||
int (*ipa_tx_dp)(enum ipa_client_type dst, struct sk_buff *skb,
|
||||
struct ipa_tx_meta *metadata);
|
||||
|
||||
int (*ipa_tx_dp_mul)(enum ipa_client_type dst,
|
||||
struct ipa_tx_data_desc *data_desc);
|
||||
|
||||
void (*ipa_free_skb)(struct ipa_rx_data *);
|
||||
|
||||
int (*ipa_setup_sys_pipe)(struct ipa_sys_connect_params *sys_in,
|
||||
u32 *clnt_hdl);
|
||||
|
||||
int (*ipa_teardown_sys_pipe)(u32 clnt_hdl);
|
||||
|
||||
int (*ipa_sys_setup)(struct ipa_sys_connect_params *sys_in,
|
||||
unsigned long *ipa_bam_hdl,
|
||||
u32 *ipa_pipe_num, u32 *clnt_hdl, bool en_status);
|
||||
|
||||
int (*ipa_sys_teardown)(u32 clnt_hdl);
|
||||
|
||||
int (*ipa_sys_update_gsi_hdls)(u32 clnt_hdl, unsigned long gsi_ch_hdl,
|
||||
unsigned long gsi_ev_hdl);
|
||||
|
||||
int (*ipa_connect_wdi_pipe)(struct ipa_wdi_in_params *in,
|
||||
struct ipa_wdi_out_params *out);
|
||||
|
||||
int (*ipa_disconnect_wdi_pipe)(u32 clnt_hdl);
|
||||
|
||||
int (*ipa_enable_wdi_pipe)(u32 clnt_hdl);
|
||||
|
||||
int (*ipa_disable_wdi_pipe)(u32 clnt_hdl);
|
||||
|
||||
int (*ipa_resume_wdi_pipe)(u32 clnt_hdl);
|
||||
|
||||
int (*ipa_suspend_wdi_pipe)(u32 clnt_hdl);
|
||||
|
||||
int (*ipa_get_wdi_stats)(struct IpaHwStatsWDIInfoData_t *stats);
|
||||
|
||||
u16 (*ipa_get_smem_restr_bytes)(void);
|
||||
|
||||
int (*ipa_uc_wdi_get_dbpa)(struct ipa_wdi_db_params *out);
|
||||
|
||||
int (*ipa_uc_reg_rdyCB)(struct ipa_wdi_uc_ready_params *param);
|
||||
|
||||
int (*ipa_uc_dereg_rdyCB)(void);
|
||||
|
||||
int (*teth_bridge_init)(struct teth_bridge_init_params *params);
|
||||
|
||||
int (*teth_bridge_disconnect)(enum ipa_client_type client);
|
||||
|
||||
int (*teth_bridge_connect)(
|
||||
struct teth_bridge_connect_params *connect_params);
|
||||
|
||||
void (*ipa_set_client)(
|
||||
int index, enum ipacm_client_enum client, bool uplink);
|
||||
|
||||
enum ipacm_client_enum (*ipa_get_client)(int pipe_idx);
|
||||
|
||||
bool (*ipa_get_client_uplink)(int pipe_idx);
|
||||
|
||||
int (*ipa_dma_init)(void);
|
||||
|
||||
int (*ipa_dma_enable)(void);
|
||||
|
||||
int (*ipa_dma_disable)(void);
|
||||
|
||||
int (*ipa_dma_sync_memcpy)(u64 dest, u64 src, int len);
|
||||
|
||||
int (*ipa_dma_async_memcpy)(u64 dest, u64 src, int len,
|
||||
void (*user_cb)(void *user1), void *user_param);
|
||||
|
||||
int (*ipa_dma_uc_memcpy)(phys_addr_t dest, phys_addr_t src, int len);
|
||||
|
||||
void (*ipa_dma_destroy)(void);
|
||||
|
||||
bool (*ipa_has_open_aggr_frame)(enum ipa_client_type client);
|
||||
|
||||
int (*ipa_generate_tag_process)(void);
|
||||
|
||||
int (*ipa_disable_sps_pipe)(enum ipa_client_type client);
|
||||
|
||||
void (*ipa_set_tag_process_before_gating)(bool val);
|
||||
|
||||
int (*ipa_mhi_init_engine)(struct ipa_mhi_init_engine *params);
|
||||
|
||||
int (*ipa_connect_mhi_pipe)(struct ipa_mhi_connect_params_internal *in,
|
||||
u32 *clnt_hdl);
|
||||
|
||||
int (*ipa_disconnect_mhi_pipe)(u32 clnt_hdl);
|
||||
|
||||
bool (*ipa_mhi_stop_gsi_channel)(enum ipa_client_type client);
|
||||
|
||||
int (*ipa_qmi_disable_force_clear)(u32 request_id);
|
||||
|
||||
int (*ipa_qmi_enable_force_clear_datapath_send)(
|
||||
struct ipa_enable_force_clear_datapath_req_msg_v01 *req);
|
||||
|
||||
int (*ipa_qmi_disable_force_clear_datapath_send)(
|
||||
struct ipa_disable_force_clear_datapath_req_msg_v01 *req);
|
||||
|
||||
bool (*ipa_mhi_sps_channel_empty)(enum ipa_client_type client);
|
||||
|
||||
int (*ipa_mhi_reset_channel_internal)(enum ipa_client_type client);
|
||||
|
||||
int (*ipa_mhi_start_channel_internal)(enum ipa_client_type client);
|
||||
|
||||
void (*ipa_get_holb)(int ep_idx, struct ipa_ep_cfg_holb *holb);
|
||||
|
||||
int (*ipa_mhi_query_ch_info)(enum ipa_client_type client,
|
||||
struct gsi_chan_info *ch_info);
|
||||
|
||||
int (*ipa_mhi_resume_channels_internal)(
|
||||
enum ipa_client_type client,
|
||||
bool LPTransitionRejected,
|
||||
bool brstmode_enabled,
|
||||
union __packed gsi_channel_scratch ch_scratch,
|
||||
u8 index);
|
||||
|
||||
int (*ipa_mhi_destroy_channel)(enum ipa_client_type client);
|
||||
|
||||
int (*ipa_uc_mhi_send_dl_ul_sync_info)
|
||||
(union IpaHwMhiDlUlSyncCmdData_t *cmd);
|
||||
|
||||
int (*ipa_uc_mhi_init)
|
||||
(void (*ready_cb)(void), void (*wakeup_request_cb)(void));
|
||||
|
||||
void (*ipa_uc_mhi_cleanup)(void);
|
||||
|
||||
int (*ipa_uc_mhi_print_stats)(char *dbg_buff, int size);
|
||||
|
||||
int (*ipa_uc_mhi_reset_channel)(int channelHandle);
|
||||
|
||||
int (*ipa_uc_mhi_suspend_channel)(int channelHandle);
|
||||
|
||||
int (*ipa_uc_mhi_stop_event_update_channel)(int channelHandle);
|
||||
|
||||
int (*ipa_uc_state_check)(void);
|
||||
|
||||
int (*ipa_write_qmap_id)(struct ipa_ioc_write_qmapid *param_in);
|
||||
|
||||
int (*ipa_add_interrupt_handler)(enum ipa_irq_type interrupt,
|
||||
ipa_irq_handler_t handler,
|
||||
bool deferred_flag,
|
||||
void *private_data);
|
||||
|
||||
int (*ipa_remove_interrupt_handler)(enum ipa_irq_type interrupt);
|
||||
|
||||
int (*ipa_restore_suspend_handler)(void);
|
||||
|
||||
void (*ipa_bam_reg_dump)(void);
|
||||
|
||||
int (*ipa_get_ep_mapping)(enum ipa_client_type client);
|
||||
|
||||
bool (*ipa_is_ready)(void);
|
||||
|
||||
void (*ipa_proxy_clk_vote)(void);
|
||||
|
||||
void (*ipa_proxy_clk_unvote)(void);
|
||||
|
||||
bool (*ipa_is_client_handle_valid)(u32 clnt_hdl);
|
||||
|
||||
enum ipa_client_type (*ipa_get_client_mapping)(int pipe_idx);
|
||||
|
||||
enum ipa_rm_resource_name (*ipa_get_rm_resource_from_ep)(int pipe_idx);
|
||||
|
||||
bool (*ipa_get_modem_cfg_emb_pipe_flt)(void);
|
||||
|
||||
enum ipa_transport_type (*ipa_get_transport_type)(void);
|
||||
|
||||
int (*ipa_ap_suspend)(struct device *dev);
|
||||
|
||||
int (*ipa_ap_resume)(struct device *dev);
|
||||
|
||||
int (*ipa_stop_gsi_channel)(u32 clnt_hdl);
|
||||
|
||||
struct iommu_domain *(*ipa_get_smmu_domain)(void);
|
||||
|
||||
int (*ipa_disable_apps_wan_cons_deaggr)(uint32_t agg_size,
|
||||
uint32_t agg_count);
|
||||
|
||||
struct device *(*ipa_get_dma_dev)(void);
|
||||
|
||||
int (*ipa_release_wdi_mapping)(u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info);
|
||||
|
||||
int (*ipa_create_wdi_mapping)(u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info);
|
||||
|
||||
struct ipa_gsi_ep_config *(*ipa_get_gsi_ep_info)(int ipa_ep_idx);
|
||||
|
||||
int (*ipa_register_ipa_ready_cb)(void (*ipa_ready_cb)(void *user_data),
|
||||
void *user_data);
|
||||
|
||||
void (*ipa_inc_client_enable_clks)(
|
||||
struct ipa_active_client_logging_info *id);
|
||||
|
||||
void (*ipa_dec_client_disable_clks)(
|
||||
struct ipa_active_client_logging_info *id);
|
||||
|
||||
int (*ipa_inc_client_enable_clks_no_block)(
|
||||
struct ipa_active_client_logging_info *id);
|
||||
|
||||
int (*ipa_suspend_resource_no_block)(
|
||||
enum ipa_rm_resource_name resource);
|
||||
|
||||
int (*ipa_resume_resource)(enum ipa_rm_resource_name name);
|
||||
|
||||
int (*ipa_suspend_resource_sync)(enum ipa_rm_resource_name resource);
|
||||
|
||||
int (*ipa_set_required_perf_profile)(
|
||||
enum ipa_voltage_level floor_voltage, u32 bandwidth_mbps);
|
||||
|
||||
void *(*ipa_get_ipc_logbuf)(void);
|
||||
|
||||
void *(*ipa_get_ipc_logbuf_low)(void);
|
||||
|
||||
int (*ipa_rx_poll)(u32 clnt_hdl, int budget);
|
||||
|
||||
void (*ipa_recycle_wan_skb)(struct sk_buff *skb);
|
||||
|
||||
int (*ipa_setup_uc_ntn_pipes)(struct ipa_ntn_conn_in_params *in,
|
||||
ipa_notify_cb notify, void *priv, u8 hdr_len,
|
||||
struct ipa_ntn_conn_out_params *);
|
||||
|
||||
int (*ipa_tear_down_uc_offload_pipes)(int ipa_ep_idx_ul,
|
||||
int ipa_ep_idx_dl);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IPA
|
||||
int ipa_plat_drv_probe(struct platform_device *pdev_p,
|
||||
struct ipa_api_controller *api_ctrl,
|
||||
const struct of_device_id *pdrv_match);
|
||||
#else
|
||||
static inline int ipa_plat_drv_probe(struct platform_device *pdev_p,
|
||||
struct ipa_api_controller *api_ctrl,
|
||||
const struct of_device_id *pdrv_match)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif /* (CONFIG_IPA) */
|
||||
|
||||
#ifdef CONFIG_IPA3
|
||||
int ipa3_plat_drv_probe(struct platform_device *pdev_p,
|
||||
struct ipa_api_controller *api_ctrl,
|
||||
const struct of_device_id *pdrv_match);
|
||||
#else
|
||||
static inline int ipa3_plat_drv_probe(struct platform_device *pdev_p,
|
||||
struct ipa_api_controller *api_ctrl,
|
||||
const struct of_device_id *pdrv_match)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif /* (CONFIG_IPA3) */
|
||||
|
||||
#endif /* _IPA_API_H_ */
|
||||
2
drivers/platform/msm/ipa/ipa_clients/Makefile
Normal file
2
drivers/platform/msm/ipa/ipa_clients/Makefile
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
obj-$(CONFIG_IPA3) += ipa_usb.o odu_bridge.o ipa_mhi_client.o ipa_uc_offload.o
|
||||
obj-$(CONFIG_IPA) += odu_bridge.o ipa_mhi_client.o ipa_uc_offload.o
|
||||
2609
drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
Normal file
2609
drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
Normal file
File diff suppressed because it is too large
Load diff
597
drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c
Normal file
597
drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c
Normal file
|
|
@ -0,0 +1,597 @@
|
|||
/* Copyright (c) 2015, 2016 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/ipa_uc_offload.h>
|
||||
#include <linux/msm_ipa.h>
|
||||
#include "../ipa_common_i.h"
|
||||
|
||||
#define IPA_NTN_DMA_POOL_ALIGNMENT 8
|
||||
#define OFFLOAD_DRV_NAME "ipa_uc_offload"
|
||||
#define IPA_UC_OFFLOAD_DBG(fmt, args...) \
|
||||
do { \
|
||||
pr_debug(OFFLOAD_DRV_NAME " %s:%d " fmt, \
|
||||
__func__, __LINE__, ## args); \
|
||||
IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
|
||||
OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
|
||||
IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
|
||||
OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
|
||||
} while (0)
|
||||
|
||||
#define IPA_UC_OFFLOAD_LOW(fmt, args...) \
|
||||
do { \
|
||||
pr_debug(OFFLOAD_DRV_NAME " %s:%d " fmt, \
|
||||
__func__, __LINE__, ## args); \
|
||||
IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
|
||||
OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
|
||||
} while (0)
|
||||
|
||||
#define IPA_UC_OFFLOAD_ERR(fmt, args...) \
|
||||
do { \
|
||||
pr_err(OFFLOAD_DRV_NAME " %s:%d " fmt, \
|
||||
__func__, __LINE__, ## args); \
|
||||
IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
|
||||
OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
|
||||
IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
|
||||
OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
|
||||
} while (0)
|
||||
|
||||
#define IPA_UC_OFFLOAD_INFO(fmt, args...) \
|
||||
do { \
|
||||
pr_info(OFFLOAD_DRV_NAME " %s:%d " fmt, \
|
||||
__func__, __LINE__, ## args); \
|
||||
IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
|
||||
OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
|
||||
IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
|
||||
OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
|
||||
} while (0)
|
||||
|
||||
enum ipa_uc_offload_state {
|
||||
IPA_UC_OFFLOAD_STATE_INVALID,
|
||||
IPA_UC_OFFLOAD_STATE_INITIALIZED,
|
||||
IPA_UC_OFFLOAD_STATE_UP,
|
||||
IPA_UC_OFFLOAD_STATE_DOWN,
|
||||
};
|
||||
|
||||
struct ipa_uc_offload_ctx {
|
||||
enum ipa_uc_offload_proto proto;
|
||||
enum ipa_uc_offload_state state;
|
||||
void *priv;
|
||||
u8 hdr_len;
|
||||
u32 partial_hdr_hdl[IPA_IP_MAX];
|
||||
char netdev_name[IPA_RESOURCE_NAME_MAX];
|
||||
ipa_notify_cb notify;
|
||||
struct completion ntn_completion;
|
||||
};
|
||||
|
||||
static struct ipa_uc_offload_ctx *ipa_uc_offload_ctx[IPA_UC_MAX_PROT_SIZE];
|
||||
|
||||
static int ipa_commit_partial_hdr(
|
||||
struct ipa_ioc_add_hdr *hdr,
|
||||
const char *netdev_name,
|
||||
struct ipa_hdr_info *hdr_info)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (hdr == NULL || hdr_info == NULL) {
|
||||
IPA_UC_OFFLOAD_ERR("Invalid input\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hdr->commit = 1;
|
||||
hdr->num_hdrs = 2;
|
||||
|
||||
snprintf(hdr->hdr[0].name, sizeof(hdr->hdr[0].name),
|
||||
"%s_ipv4", netdev_name);
|
||||
snprintf(hdr->hdr[1].name, sizeof(hdr->hdr[1].name),
|
||||
"%s_ipv6", netdev_name);
|
||||
for (i = IPA_IP_v4; i < IPA_IP_MAX; i++) {
|
||||
hdr->hdr[i].hdr_len = hdr_info[i].hdr_len;
|
||||
memcpy(hdr->hdr[i].hdr, hdr_info[i].hdr, hdr->hdr[i].hdr_len);
|
||||
hdr->hdr[i].type = hdr_info[i].hdr_type;
|
||||
hdr->hdr[i].is_partial = 1;
|
||||
hdr->hdr[i].is_eth2_ofst_valid = 1;
|
||||
hdr->hdr[i].eth2_ofst = hdr_info[i].dst_mac_addr_offset;
|
||||
}
|
||||
|
||||
if (ipa_add_hdr(hdr)) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to add partial headers\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipa_uc_offload_ntn_reg_intf(
|
||||
struct ipa_uc_offload_intf_params *inp,
|
||||
struct ipa_uc_offload_out_params *outp,
|
||||
struct ipa_uc_offload_ctx *ntn_ctx)
|
||||
{
|
||||
struct ipa_ioc_add_hdr *hdr;
|
||||
struct ipa_tx_intf tx;
|
||||
struct ipa_rx_intf rx;
|
||||
struct ipa_ioc_tx_intf_prop tx_prop[2];
|
||||
struct ipa_ioc_rx_intf_prop rx_prop[2];
|
||||
u32 len;
|
||||
int ret = 0;
|
||||
|
||||
IPA_UC_OFFLOAD_DBG("register interface for netdev %s\n",
|
||||
inp->netdev_name);
|
||||
|
||||
memcpy(ntn_ctx->netdev_name, inp->netdev_name, IPA_RESOURCE_NAME_MAX);
|
||||
ntn_ctx->hdr_len = inp->hdr_info[0].hdr_len;
|
||||
ntn_ctx->notify = inp->notify;
|
||||
ntn_ctx->priv = inp->priv;
|
||||
|
||||
/* add partial header */
|
||||
len = sizeof(struct ipa_ioc_add_hdr) + 2 * sizeof(struct ipa_hdr_add);
|
||||
hdr = kzalloc(len, GFP_KERNEL);
|
||||
if (hdr == NULL) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to alloc %d bytes\n", len);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (ipa_commit_partial_hdr(hdr, ntn_ctx->netdev_name, inp->hdr_info)) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to commit partial headers\n");
|
||||
ret = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* populate tx prop */
|
||||
tx.num_props = 2;
|
||||
tx.prop = tx_prop;
|
||||
|
||||
memset(tx_prop, 0, sizeof(tx_prop));
|
||||
tx_prop[0].ip = IPA_IP_v4;
|
||||
tx_prop[0].dst_pipe = IPA_CLIENT_ODU_TETH_CONS;
|
||||
tx_prop[0].hdr_l2_type = inp->hdr_info[0].hdr_type;
|
||||
memcpy(tx_prop[0].hdr_name, hdr->hdr[IPA_IP_v4].name,
|
||||
sizeof(tx_prop[0].hdr_name));
|
||||
|
||||
tx_prop[1].ip = IPA_IP_v6;
|
||||
tx_prop[1].dst_pipe = IPA_CLIENT_ODU_TETH_CONS;
|
||||
tx_prop[1].hdr_l2_type = inp->hdr_info[1].hdr_type;
|
||||
memcpy(tx_prop[1].hdr_name, hdr->hdr[IPA_IP_v6].name,
|
||||
sizeof(tx_prop[1].hdr_name));
|
||||
|
||||
/* populate rx prop */
|
||||
rx.num_props = 2;
|
||||
rx.prop = rx_prop;
|
||||
|
||||
memset(rx_prop, 0, sizeof(rx_prop));
|
||||
rx_prop[0].ip = IPA_IP_v4;
|
||||
rx_prop[0].src_pipe = IPA_CLIENT_ODU_PROD;
|
||||
rx_prop[0].hdr_l2_type = inp->hdr_info[0].hdr_type;
|
||||
if (inp->is_meta_data_valid) {
|
||||
rx_prop[0].attrib.attrib_mask |= IPA_FLT_META_DATA;
|
||||
rx_prop[0].attrib.meta_data = inp->meta_data;
|
||||
rx_prop[0].attrib.meta_data_mask = inp->meta_data_mask;
|
||||
}
|
||||
|
||||
rx_prop[1].ip = IPA_IP_v6;
|
||||
rx_prop[1].src_pipe = IPA_CLIENT_ODU_PROD;
|
||||
rx_prop[1].hdr_l2_type = inp->hdr_info[1].hdr_type;
|
||||
if (inp->is_meta_data_valid) {
|
||||
rx_prop[1].attrib.attrib_mask |= IPA_FLT_META_DATA;
|
||||
rx_prop[1].attrib.meta_data = inp->meta_data;
|
||||
rx_prop[1].attrib.meta_data_mask = inp->meta_data_mask;
|
||||
}
|
||||
|
||||
if (ipa_register_intf(inp->netdev_name, &tx, &rx)) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to add interface prop\n");
|
||||
memset(ntn_ctx, 0, sizeof(*ntn_ctx));
|
||||
ret = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ntn_ctx->partial_hdr_hdl[IPA_IP_v4] = hdr->hdr[IPA_IP_v4].hdr_hdl;
|
||||
ntn_ctx->partial_hdr_hdl[IPA_IP_v6] = hdr->hdr[IPA_IP_v6].hdr_hdl;
|
||||
init_completion(&ntn_ctx->ntn_completion);
|
||||
ntn_ctx->state = IPA_UC_OFFLOAD_STATE_INITIALIZED;
|
||||
|
||||
fail:
|
||||
kfree(hdr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ipa_uc_offload_reg_intf(
|
||||
struct ipa_uc_offload_intf_params *inp,
|
||||
struct ipa_uc_offload_out_params *outp)
|
||||
{
|
||||
struct ipa_uc_offload_ctx *ctx;
|
||||
int ret = 0;
|
||||
|
||||
if (inp == NULL || outp == NULL) {
|
||||
IPA_UC_OFFLOAD_ERR("invalid params in=%p out=%p\n", inp, outp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (inp->proto <= IPA_UC_INVALID ||
|
||||
inp->proto >= IPA_UC_MAX_PROT_SIZE) {
|
||||
IPA_UC_OFFLOAD_ERR("invalid proto %d\n", inp->proto);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!ipa_uc_offload_ctx[inp->proto]) {
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (ctx == NULL) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to alloc uc offload ctx\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
ipa_uc_offload_ctx[inp->proto] = ctx;
|
||||
ctx->proto = inp->proto;
|
||||
} else
|
||||
ctx = ipa_uc_offload_ctx[inp->proto];
|
||||
|
||||
if (ctx->state != IPA_UC_OFFLOAD_STATE_INVALID) {
|
||||
IPA_UC_OFFLOAD_ERR("Already Initialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ctx->proto == IPA_UC_NTN) {
|
||||
ret = ipa_uc_offload_ntn_reg_intf(inp, outp, ctx);
|
||||
if (!ret)
|
||||
outp->clnt_hndl = IPA_UC_NTN;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_uc_offload_reg_intf);
|
||||
|
||||
static int ipa_uc_ntn_cons_release(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipa_uc_ntn_cons_request(void)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ipa_uc_offload_ctx *ntn_ctx;
|
||||
|
||||
ntn_ctx = ipa_uc_offload_ctx[IPA_UC_NTN];
|
||||
if (!ntn_ctx) {
|
||||
IPA_UC_OFFLOAD_ERR("NTN is not initialized\n");
|
||||
ret = -EFAULT;
|
||||
} else if (ntn_ctx->state != IPA_UC_OFFLOAD_STATE_UP) {
|
||||
IPA_UC_OFFLOAD_ERR("Invalid State: %d\n", ntn_ctx->state);
|
||||
ret = -EFAULT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ipa_uc_offload_rm_notify(void *user_data, enum ipa_rm_event event,
|
||||
unsigned long data)
|
||||
{
|
||||
struct ipa_uc_offload_ctx *offload_ctx;
|
||||
|
||||
offload_ctx = (struct ipa_uc_offload_ctx *)user_data;
|
||||
if (!(offload_ctx && offload_ctx->proto > IPA_UC_INVALID &&
|
||||
offload_ctx->proto < IPA_UC_MAX_PROT_SIZE)) {
|
||||
IPA_UC_OFFLOAD_ERR("Invalid user data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (offload_ctx->state != IPA_UC_OFFLOAD_STATE_INITIALIZED)
|
||||
IPA_UC_OFFLOAD_ERR("Invalid State: %d\n", offload_ctx->state);
|
||||
|
||||
switch (event) {
|
||||
case IPA_RM_RESOURCE_GRANTED:
|
||||
complete_all(&offload_ctx->ntn_completion);
|
||||
break;
|
||||
|
||||
case IPA_RM_RESOURCE_RELEASED:
|
||||
break;
|
||||
|
||||
default:
|
||||
IPA_UC_OFFLOAD_ERR("Invalid RM Evt: %d", event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int ipa_uc_ntn_conn_pipes(struct ipa_ntn_conn_in_params *inp,
|
||||
struct ipa_ntn_conn_out_params *outp,
|
||||
struct ipa_uc_offload_ctx *ntn_ctx)
|
||||
{
|
||||
struct ipa_rm_create_params param;
|
||||
int result = 0;
|
||||
|
||||
if (inp->dl.ring_base_pa % IPA_NTN_DMA_POOL_ALIGNMENT ||
|
||||
inp->dl.buff_pool_base_pa % IPA_NTN_DMA_POOL_ALIGNMENT) {
|
||||
IPA_UC_OFFLOAD_ERR("alignment failure on TX\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (inp->ul.ring_base_pa % IPA_NTN_DMA_POOL_ALIGNMENT ||
|
||||
inp->ul.buff_pool_base_pa % IPA_NTN_DMA_POOL_ALIGNMENT) {
|
||||
IPA_UC_OFFLOAD_ERR("alignment failure on RX\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(¶m, 0, sizeof(param));
|
||||
param.name = IPA_RM_RESOURCE_ODU_ADAPT_PROD;
|
||||
param.reg_params.user_data = ntn_ctx;
|
||||
param.reg_params.notify_cb = ipa_uc_offload_rm_notify;
|
||||
param.floor_voltage = IPA_VOLTAGE_SVS;
|
||||
result = ipa_rm_create_resource(¶m);
|
||||
if (result) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to create ODU_ADAPT_PROD resource\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
memset(¶m, 0, sizeof(param));
|
||||
param.name = IPA_RM_RESOURCE_ODU_ADAPT_CONS;
|
||||
param.request_resource = ipa_uc_ntn_cons_request;
|
||||
param.release_resource = ipa_uc_ntn_cons_release;
|
||||
result = ipa_rm_create_resource(¶m);
|
||||
if (result) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to create ODU_ADAPT_CONS resource\n");
|
||||
goto fail_create_rm_cons;
|
||||
}
|
||||
|
||||
if (ipa_rm_add_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
|
||||
IPA_RM_RESOURCE_APPS_CONS)) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to add rm dependency\n");
|
||||
result = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ipa_setup_uc_ntn_pipes(inp, ntn_ctx->notify,
|
||||
ntn_ctx->priv, ntn_ctx->hdr_len, outp)) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to setup uc offload pipes\n");
|
||||
result = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ntn_ctx->state = IPA_UC_OFFLOAD_STATE_UP;
|
||||
result = ipa_rm_request_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
|
||||
if (result == -EINPROGRESS) {
|
||||
if (wait_for_completion_timeout(&ntn_ctx->ntn_completion,
|
||||
10*HZ) == 0) {
|
||||
IPA_UC_OFFLOAD_ERR("ODU PROD resource req time out\n");
|
||||
result = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
} else if (result != 0) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to request resource\n");
|
||||
result = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_CONS);
|
||||
fail_create_rm_cons:
|
||||
ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int ipa_uc_offload_conn_pipes(struct ipa_uc_offload_conn_in_params *inp,
|
||||
struct ipa_uc_offload_conn_out_params *outp)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ipa_uc_offload_ctx *offload_ctx;
|
||||
|
||||
if (!(inp && outp)) {
|
||||
IPA_UC_OFFLOAD_ERR("bad parm. in=%p out=%p\n", inp, outp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (inp->clnt_hndl <= IPA_UC_INVALID ||
|
||||
inp->clnt_hndl >= IPA_UC_MAX_PROT_SIZE) {
|
||||
IPA_UC_OFFLOAD_ERR("invalid client handle %d\n",
|
||||
inp->clnt_hndl);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
offload_ctx = ipa_uc_offload_ctx[inp->clnt_hndl];
|
||||
if (!offload_ctx) {
|
||||
IPA_UC_OFFLOAD_ERR("Invalid Handle\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (offload_ctx->state != IPA_UC_OFFLOAD_STATE_INITIALIZED) {
|
||||
IPA_UC_OFFLOAD_ERR("Invalid state %d\n", offload_ctx->state);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
switch (offload_ctx->proto) {
|
||||
case IPA_UC_NTN:
|
||||
ret = ipa_uc_ntn_conn_pipes(&inp->u.ntn, &outp->u.ntn,
|
||||
offload_ctx);
|
||||
break;
|
||||
|
||||
default:
|
||||
IPA_UC_OFFLOAD_ERR("Invalid Proto :%d\n", offload_ctx->proto);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_uc_offload_conn_pipes);
|
||||
|
||||
int ipa_set_perf_profile(struct ipa_perf_profile *profile)
|
||||
{
|
||||
struct ipa_rm_perf_profile rm_profile;
|
||||
enum ipa_rm_resource_name resource_name;
|
||||
|
||||
if (profile == NULL) {
|
||||
IPA_UC_OFFLOAD_ERR("Invalid input\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rm_profile.max_supported_bandwidth_mbps =
|
||||
profile->max_supported_bw_mbps;
|
||||
|
||||
if (profile->client == IPA_CLIENT_ODU_PROD) {
|
||||
resource_name = IPA_RM_RESOURCE_ODU_ADAPT_PROD;
|
||||
} else if (profile->client == IPA_CLIENT_ODU_TETH_CONS) {
|
||||
resource_name = IPA_RM_RESOURCE_ODU_ADAPT_CONS;
|
||||
} else {
|
||||
IPA_UC_OFFLOAD_ERR("not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ipa_rm_set_perf_profile(resource_name, &rm_profile)) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to setup rm perf profile\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_set_perf_profile);
|
||||
|
||||
static int ipa_uc_ntn_disconn_pipes(struct ipa_uc_offload_ctx *ntn_ctx)
|
||||
{
|
||||
int ipa_ep_idx_ul, ipa_ep_idx_dl;
|
||||
|
||||
ntn_ctx->state = IPA_UC_OFFLOAD_STATE_DOWN;
|
||||
if (ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
|
||||
IPA_RM_RESOURCE_APPS_CONS)) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to delete rm dependency\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD)) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to delete ODU_ADAPT_PROD resource\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_CONS)) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to delete ODU_ADAPT_CONS resource\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ipa_ep_idx_ul = ipa_get_ep_mapping(IPA_CLIENT_ODU_PROD);
|
||||
ipa_ep_idx_dl = ipa_get_ep_mapping(IPA_CLIENT_ODU_TETH_CONS);
|
||||
if (ipa_tear_down_uc_offload_pipes(ipa_ep_idx_ul, ipa_ep_idx_dl)) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to tear down uc offload pipes\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipa_uc_offload_disconn_pipes(u32 clnt_hdl)
|
||||
{
|
||||
struct ipa_uc_offload_ctx *offload_ctx;
|
||||
int ret = 0;
|
||||
|
||||
if (clnt_hdl <= IPA_UC_INVALID ||
|
||||
clnt_hdl >= IPA_UC_MAX_PROT_SIZE) {
|
||||
IPA_UC_OFFLOAD_ERR("Invalid client handle %d\n", clnt_hdl);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
offload_ctx = ipa_uc_offload_ctx[clnt_hdl];
|
||||
if (!offload_ctx) {
|
||||
IPA_UC_OFFLOAD_ERR("Invalid client Handle\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (offload_ctx->state != IPA_UC_OFFLOAD_STATE_UP) {
|
||||
IPA_UC_OFFLOAD_ERR("Invalid state\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (offload_ctx->proto) {
|
||||
case IPA_UC_NTN:
|
||||
ret = ipa_uc_ntn_disconn_pipes(offload_ctx);
|
||||
break;
|
||||
|
||||
default:
|
||||
IPA_UC_OFFLOAD_ERR("Invalid Proto :%d\n", clnt_hdl);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_uc_offload_disconn_pipes);
|
||||
|
||||
static int ipa_uc_ntn_cleanup(struct ipa_uc_offload_ctx *ntn_ctx)
|
||||
{
|
||||
int len, result = 0;
|
||||
struct ipa_ioc_del_hdr *hdr;
|
||||
|
||||
len = sizeof(struct ipa_ioc_del_hdr) + 2 * sizeof(struct ipa_hdr_del);
|
||||
hdr = kzalloc(len, GFP_KERNEL);
|
||||
if (hdr == NULL) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to alloc %d bytes\n", len);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hdr->commit = 1;
|
||||
hdr->num_hdls = 2;
|
||||
hdr->hdl[0].hdl = ntn_ctx->partial_hdr_hdl[0];
|
||||
hdr->hdl[1].hdl = ntn_ctx->partial_hdr_hdl[1];
|
||||
|
||||
if (ipa_del_hdr(hdr)) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to delete partial header\n");
|
||||
result = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ipa_deregister_intf(ntn_ctx->netdev_name)) {
|
||||
IPA_UC_OFFLOAD_ERR("fail to delete interface prop\n");
|
||||
result = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
kfree(hdr);
|
||||
return result;
|
||||
}
|
||||
|
||||
int ipa_uc_offload_cleanup(u32 clnt_hdl)
|
||||
{
|
||||
struct ipa_uc_offload_ctx *offload_ctx;
|
||||
int ret = 0;
|
||||
|
||||
if (clnt_hdl <= IPA_UC_INVALID ||
|
||||
clnt_hdl >= IPA_UC_MAX_PROT_SIZE) {
|
||||
IPA_UC_OFFLOAD_ERR("Invalid client handle %d\n", clnt_hdl);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
offload_ctx = ipa_uc_offload_ctx[clnt_hdl];
|
||||
if (!offload_ctx) {
|
||||
IPA_UC_OFFLOAD_ERR("Invalid client handle %d\n", clnt_hdl);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (offload_ctx->state != IPA_UC_OFFLOAD_STATE_DOWN) {
|
||||
IPA_UC_OFFLOAD_ERR("Invalid State %d\n", offload_ctx->state);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (offload_ctx->proto) {
|
||||
case IPA_UC_NTN:
|
||||
ret = ipa_uc_ntn_cleanup(offload_ctx);
|
||||
break;
|
||||
|
||||
default:
|
||||
IPA_UC_OFFLOAD_ERR("Invalid Proto :%d\n", clnt_hdl);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
kfree(offload_ctx);
|
||||
offload_ctx = NULL;
|
||||
ipa_uc_offload_ctx[clnt_hdl] = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_uc_offload_cleanup);
|
||||
2711
drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
Normal file
2711
drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
Normal file
File diff suppressed because it is too large
Load diff
1251
drivers/platform/msm/ipa/ipa_clients/odu_bridge.c
Normal file
1251
drivers/platform/msm/ipa/ipa_clients/odu_bridge.c
Normal file
File diff suppressed because it is too large
Load diff
383
drivers/platform/msm/ipa/ipa_common_i.h
Normal file
383
drivers/platform/msm/ipa/ipa_common_i.h
Normal file
|
|
@ -0,0 +1,383 @@
|
|||
/* Copyright (c) 2012-2016, 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/ipa_mhi.h>
|
||||
#include <linux/ipa_qmi_service_v01.h>
|
||||
|
||||
#ifndef _IPA_COMMON_I_H_
|
||||
#define _IPA_COMMON_I_H_
|
||||
#include <linux/ipc_logging.h>
|
||||
#include <linux/ipa.h>
|
||||
#include <linux/ipa_uc_offload.h>
|
||||
|
||||
#define __FILENAME__ \
|
||||
(strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
|
||||
#define IPA_ACTIVE_CLIENTS_PREP_EP(log_info, client) \
|
||||
log_info.file = __FILENAME__; \
|
||||
log_info.line = __LINE__; \
|
||||
log_info.type = EP; \
|
||||
log_info.id_string = ipa_clients_strings[client]
|
||||
|
||||
#define IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info) \
|
||||
log_info.file = __FILENAME__; \
|
||||
log_info.line = __LINE__; \
|
||||
log_info.type = SIMPLE; \
|
||||
log_info.id_string = __func__
|
||||
|
||||
#define IPA_ACTIVE_CLIENTS_PREP_RESOURCE(log_info, resource_name) \
|
||||
log_info.file = __FILENAME__; \
|
||||
log_info.line = __LINE__; \
|
||||
log_info.type = RESOURCE; \
|
||||
log_info.id_string = resource_name
|
||||
|
||||
#define IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, id_str) \
|
||||
log_info.file = __FILENAME__; \
|
||||
log_info.line = __LINE__; \
|
||||
log_info.type = SPECIAL; \
|
||||
log_info.id_string = id_str
|
||||
|
||||
#define IPA_ACTIVE_CLIENTS_INC_EP(client) \
|
||||
do { \
|
||||
struct ipa_active_client_logging_info log_info; \
|
||||
IPA_ACTIVE_CLIENTS_PREP_EP(log_info, client); \
|
||||
ipa_inc_client_enable_clks(&log_info); \
|
||||
} while (0)
|
||||
|
||||
#define IPA_ACTIVE_CLIENTS_DEC_EP(client) \
|
||||
do { \
|
||||
struct ipa_active_client_logging_info log_info; \
|
||||
IPA_ACTIVE_CLIENTS_PREP_EP(log_info, client); \
|
||||
ipa_dec_client_disable_clks(&log_info); \
|
||||
} while (0)
|
||||
|
||||
#define IPA_ACTIVE_CLIENTS_INC_SIMPLE() \
|
||||
do { \
|
||||
struct ipa_active_client_logging_info log_info; \
|
||||
IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info); \
|
||||
ipa_inc_client_enable_clks(&log_info); \
|
||||
} while (0)
|
||||
|
||||
#define IPA_ACTIVE_CLIENTS_DEC_SIMPLE() \
|
||||
do { \
|
||||
struct ipa_active_client_logging_info log_info; \
|
||||
IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info); \
|
||||
ipa_dec_client_disable_clks(&log_info); \
|
||||
} while (0)
|
||||
|
||||
#define IPA_ACTIVE_CLIENTS_INC_RESOURCE(resource_name) \
|
||||
do { \
|
||||
struct ipa_active_client_logging_info log_info; \
|
||||
IPA_ACTIVE_CLIENTS_PREP_RESOURCE(log_info, resource_name); \
|
||||
ipa_inc_client_enable_clks(&log_info); \
|
||||
} while (0)
|
||||
|
||||
#define IPA_ACTIVE_CLIENTS_DEC_RESOURCE(resource_name) \
|
||||
do { \
|
||||
struct ipa_active_client_logging_info log_info; \
|
||||
IPA_ACTIVE_CLIENTS_PREP_RESOURCE(log_info, resource_name); \
|
||||
ipa_dec_client_disable_clks(&log_info); \
|
||||
} while (0)
|
||||
|
||||
#define IPA_ACTIVE_CLIENTS_INC_SPECIAL(id_str) \
|
||||
do { \
|
||||
struct ipa_active_client_logging_info log_info; \
|
||||
IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, id_str); \
|
||||
ipa_inc_client_enable_clks(&log_info); \
|
||||
} while (0)
|
||||
|
||||
#define IPA_ACTIVE_CLIENTS_DEC_SPECIAL(id_str) \
|
||||
do { \
|
||||
struct ipa_active_client_logging_info log_info; \
|
||||
IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, id_str); \
|
||||
ipa_dec_client_disable_clks(&log_info); \
|
||||
} while (0)
|
||||
|
||||
#define ipa_assert_on(condition)\
|
||||
do {\
|
||||
if (unlikely(condition))\
|
||||
ipa_assert();\
|
||||
} while (0)
|
||||
|
||||
#define IPA_CLIENT_IS_PROD(x) (x >= IPA_CLIENT_PROD && x < IPA_CLIENT_CONS)
|
||||
#define IPA_CLIENT_IS_CONS(x) (x >= IPA_CLIENT_CONS && x < IPA_CLIENT_MAX)
|
||||
|
||||
#define IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC (1000)
|
||||
#define IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC (2000)
|
||||
|
||||
enum ipa_active_client_log_type {
|
||||
EP,
|
||||
SIMPLE,
|
||||
RESOURCE,
|
||||
SPECIAL,
|
||||
INVALID
|
||||
};
|
||||
|
||||
struct ipa_active_client_logging_info {
|
||||
const char *id_string;
|
||||
char *file;
|
||||
int line;
|
||||
enum ipa_active_client_log_type type;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ipa_mem_buffer - IPA memory buffer
|
||||
* @base: base
|
||||
* @phys_base: physical base address
|
||||
* @size: size of memory buffer
|
||||
*/
|
||||
struct ipa_mem_buffer {
|
||||
void *base;
|
||||
dma_addr_t phys_base;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
#define IPA_MHI_GSI_ER_START 10
|
||||
#define IPA_MHI_GSI_ER_END 16
|
||||
|
||||
/**
|
||||
* enum ipa3_mhi_burst_mode - MHI channel burst mode state
|
||||
*
|
||||
* Values are according to MHI specification
|
||||
* @IPA_MHI_BURST_MODE_DEFAULT: burst mode enabled for HW channels,
|
||||
* disabled for SW channels
|
||||
* @IPA_MHI_BURST_MODE_RESERVED:
|
||||
* @IPA_MHI_BURST_MODE_DISABLE: Burst mode is disabled for this channel
|
||||
* @IPA_MHI_BURST_MODE_ENABLE: Burst mode is enabled for this channel
|
||||
*
|
||||
*/
|
||||
enum ipa3_mhi_burst_mode {
|
||||
IPA_MHI_BURST_MODE_DEFAULT,
|
||||
IPA_MHI_BURST_MODE_RESERVED,
|
||||
IPA_MHI_BURST_MODE_DISABLE,
|
||||
IPA_MHI_BURST_MODE_ENABLE,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ipa_hw_mhi_channel_states - MHI channel state machine
|
||||
*
|
||||
* Values are according to MHI specification
|
||||
* @IPA_HW_MHI_CHANNEL_STATE_DISABLE: Channel is disabled and not processed by
|
||||
* the host or device.
|
||||
* @IPA_HW_MHI_CHANNEL_STATE_ENABLE: A channel is enabled after being
|
||||
* initialized and configured by host, including its channel context and
|
||||
* associated transfer ring. While this state, the channel is not active
|
||||
* and the device does not process transfer.
|
||||
* @IPA_HW_MHI_CHANNEL_STATE_RUN: The device processes transfers and doorbell
|
||||
* for channels.
|
||||
* @IPA_HW_MHI_CHANNEL_STATE_SUSPEND: Used to halt operations on the channel.
|
||||
* The device does not process transfers for the channel in this state.
|
||||
* This state is typically used to synchronize the transition to low power
|
||||
* modes.
|
||||
* @IPA_HW_MHI_CHANNEL_STATE_STOP: Used to halt operations on the channel.
|
||||
* The device does not process transfers for the channel in this state.
|
||||
* @IPA_HW_MHI_CHANNEL_STATE_ERROR: The device detected an error in an element
|
||||
* from the transfer ring associated with the channel.
|
||||
* @IPA_HW_MHI_CHANNEL_STATE_INVALID: Invalid state. Shall not be in use in
|
||||
* operational scenario.
|
||||
*/
|
||||
enum ipa_hw_mhi_channel_states {
|
||||
IPA_HW_MHI_CHANNEL_STATE_DISABLE = 0,
|
||||
IPA_HW_MHI_CHANNEL_STATE_ENABLE = 1,
|
||||
IPA_HW_MHI_CHANNEL_STATE_RUN = 2,
|
||||
IPA_HW_MHI_CHANNEL_STATE_SUSPEND = 3,
|
||||
IPA_HW_MHI_CHANNEL_STATE_STOP = 4,
|
||||
IPA_HW_MHI_CHANNEL_STATE_ERROR = 5,
|
||||
IPA_HW_MHI_CHANNEL_STATE_INVALID = 0xFF
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure holding the parameters for IPA_CPU_2_HW_CMD_MHI_DL_UL_SYNC_INFO
|
||||
* command. Parameters are sent as 32b immediate parameters.
|
||||
* @isDlUlSyncEnabled: Flag to indicate if DL UL Syncronization is enabled
|
||||
* @UlAccmVal: UL Timer Accumulation value (Period after which device will poll
|
||||
* for UL data)
|
||||
* @ulMsiEventThreshold: Threshold at which HW fires MSI to host for UL events
|
||||
* @dlMsiEventThreshold: Threshold at which HW fires MSI to host for DL events
|
||||
*/
|
||||
union IpaHwMhiDlUlSyncCmdData_t {
|
||||
struct IpaHwMhiDlUlSyncCmdParams_t {
|
||||
u32 isDlUlSyncEnabled:8;
|
||||
u32 UlAccmVal:8;
|
||||
u32 ulMsiEventThreshold:8;
|
||||
u32 dlMsiEventThreshold:8;
|
||||
} params;
|
||||
u32 raw32b;
|
||||
};
|
||||
|
||||
struct ipa_mhi_ch_ctx {
|
||||
u8 chstate;/*0-7*/
|
||||
u8 brstmode:2;/*8-9*/
|
||||
u8 pollcfg:6;/*10-15*/
|
||||
u16 rsvd;/*16-31*/
|
||||
u32 chtype;
|
||||
u32 erindex;
|
||||
u64 rbase;
|
||||
u64 rlen;
|
||||
u64 rp;
|
||||
u64 wp;
|
||||
} __packed;
|
||||
|
||||
struct ipa_mhi_ev_ctx {
|
||||
u32 intmodc:16;
|
||||
u32 intmodt:16;
|
||||
u32 ertype;
|
||||
u32 msivec;
|
||||
u64 rbase;
|
||||
u64 rlen;
|
||||
u64 rp;
|
||||
u64 wp;
|
||||
} __packed;
|
||||
|
||||
struct ipa_mhi_init_uc_engine {
|
||||
struct ipa_mhi_msi_info *msi;
|
||||
u32 mmio_addr;
|
||||
u32 host_ctrl_addr;
|
||||
u32 host_data_addr;
|
||||
u32 first_ch_idx;
|
||||
u32 first_er_idx;
|
||||
union IpaHwMhiDlUlSyncCmdData_t *ipa_cached_dl_ul_sync_info;
|
||||
};
|
||||
|
||||
struct ipa_mhi_init_gsi_engine {
|
||||
u32 first_ch_idx;
|
||||
};
|
||||
|
||||
struct ipa_mhi_init_engine {
|
||||
struct ipa_mhi_init_uc_engine uC;
|
||||
struct ipa_mhi_init_gsi_engine gsi;
|
||||
};
|
||||
|
||||
struct start_gsi_channel {
|
||||
enum ipa_hw_mhi_channel_states state;
|
||||
struct ipa_mhi_msi_info *msi;
|
||||
struct ipa_mhi_ev_ctx *ev_ctx_host;
|
||||
u64 event_context_addr;
|
||||
struct ipa_mhi_ch_ctx *ch_ctx_host;
|
||||
u64 channel_context_addr;
|
||||
void (*ch_err_cb)(struct gsi_chan_err_notify *notify);
|
||||
void (*ev_err_cb)(struct gsi_evt_err_notify *notify);
|
||||
void *channel;
|
||||
bool assert_bit40;
|
||||
struct gsi_mhi_channel_scratch *mhi;
|
||||
unsigned long *cached_gsi_evt_ring_hdl;
|
||||
uint8_t evchid;
|
||||
};
|
||||
|
||||
struct start_uc_channel {
|
||||
enum ipa_hw_mhi_channel_states state;
|
||||
u8 index;
|
||||
u8 id;
|
||||
};
|
||||
|
||||
struct start_mhi_channel {
|
||||
struct start_uc_channel uC;
|
||||
struct start_gsi_channel gsi;
|
||||
};
|
||||
|
||||
struct ipa_mhi_connect_params_internal {
|
||||
struct ipa_sys_connect_params *sys;
|
||||
u8 channel_id;
|
||||
struct start_mhi_channel start;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ipa_hdr_offset_entry - IPA header offset entry
|
||||
* @link: entry's link in global header offset entries list
|
||||
* @offset: the offset
|
||||
* @bin: bin
|
||||
*/
|
||||
struct ipa_hdr_offset_entry {
|
||||
struct list_head link;
|
||||
u32 offset;
|
||||
u32 bin;
|
||||
};
|
||||
|
||||
extern const char *ipa_clients_strings[];
|
||||
|
||||
#define IPA_IPC_LOGGING(buf, fmt, args...) \
|
||||
do { \
|
||||
if (buf) \
|
||||
ipc_log_string((buf), fmt, __func__, __LINE__, \
|
||||
## args); \
|
||||
} while (0)
|
||||
|
||||
void ipa_inc_client_enable_clks(struct ipa_active_client_logging_info *id);
|
||||
void ipa_dec_client_disable_clks(struct ipa_active_client_logging_info *id);
|
||||
int ipa_inc_client_enable_clks_no_block(
|
||||
struct ipa_active_client_logging_info *id);
|
||||
int ipa_suspend_resource_no_block(enum ipa_rm_resource_name resource);
|
||||
int ipa_resume_resource(enum ipa_rm_resource_name name);
|
||||
int ipa_suspend_resource_sync(enum ipa_rm_resource_name resource);
|
||||
int ipa_set_required_perf_profile(enum ipa_voltage_level floor_voltage,
|
||||
u32 bandwidth_mbps);
|
||||
void *ipa_get_ipc_logbuf(void);
|
||||
void *ipa_get_ipc_logbuf_low(void);
|
||||
void ipa_assert(void);
|
||||
|
||||
/* MHI */
|
||||
int ipa_mhi_init_engine(struct ipa_mhi_init_engine *params);
|
||||
int ipa_connect_mhi_pipe(struct ipa_mhi_connect_params_internal *in,
|
||||
u32 *clnt_hdl);
|
||||
int ipa_disconnect_mhi_pipe(u32 clnt_hdl);
|
||||
bool ipa_mhi_stop_gsi_channel(enum ipa_client_type client);
|
||||
int ipa_qmi_enable_force_clear_datapath_send(
|
||||
struct ipa_enable_force_clear_datapath_req_msg_v01 *req);
|
||||
int ipa_qmi_disable_force_clear_datapath_send(
|
||||
struct ipa_disable_force_clear_datapath_req_msg_v01 *req);
|
||||
int ipa_generate_tag_process(void);
|
||||
int ipa_disable_sps_pipe(enum ipa_client_type client);
|
||||
int ipa_mhi_reset_channel_internal(enum ipa_client_type client);
|
||||
int ipa_mhi_start_channel_internal(enum ipa_client_type client);
|
||||
bool ipa_mhi_sps_channel_empty(enum ipa_client_type client);
|
||||
int ipa_mhi_resume_channels_internal(enum ipa_client_type client,
|
||||
bool LPTransitionRejected, bool brstmode_enabled,
|
||||
union __packed gsi_channel_scratch ch_scratch, u8 index);
|
||||
int ipa_mhi_handle_ipa_config_req(struct ipa_config_req_msg_v01 *config_req);
|
||||
int ipa_mhi_query_ch_info(enum ipa_client_type client,
|
||||
struct gsi_chan_info *ch_info);
|
||||
int ipa_mhi_destroy_channel(enum ipa_client_type client);
|
||||
int ipa_mhi_is_using_dma(bool *flag);
|
||||
const char *ipa_mhi_get_state_str(int state);
|
||||
|
||||
/* MHI uC */
|
||||
int ipa_uc_mhi_send_dl_ul_sync_info(union IpaHwMhiDlUlSyncCmdData_t *cmd);
|
||||
int ipa_uc_mhi_init
|
||||
(void (*ready_cb)(void), void (*wakeup_request_cb)(void));
|
||||
void ipa_uc_mhi_cleanup(void);
|
||||
int ipa_uc_mhi_reset_channel(int channelHandle);
|
||||
int ipa_uc_mhi_suspend_channel(int channelHandle);
|
||||
int ipa_uc_mhi_stop_event_update_channel(int channelHandle);
|
||||
int ipa_uc_mhi_print_stats(char *dbg_buff, int size);
|
||||
|
||||
/* uC */
|
||||
int ipa_uc_state_check(void);
|
||||
|
||||
/* general */
|
||||
void ipa_get_holb(int ep_idx, struct ipa_ep_cfg_holb *holb);
|
||||
void ipa_set_tag_process_before_gating(bool val);
|
||||
bool ipa_has_open_aggr_frame(enum ipa_client_type client);
|
||||
int ipa_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
|
||||
ipa_notify_cb notify, void *priv, u8 hdr_len,
|
||||
struct ipa_ntn_conn_out_params *outp);
|
||||
|
||||
int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl);
|
||||
|
||||
u8 *ipa_write_64(u64 w, u8 *dest);
|
||||
u8 *ipa_write_32(u32 w, u8 *dest);
|
||||
u8 *ipa_write_16(u16 hw, u8 *dest);
|
||||
u8 *ipa_write_8(u8 b, u8 *dest);
|
||||
u8 *ipa_pad_to_64(u8 *dest);
|
||||
u8 *ipa_pad_to_32(u8 *dest);
|
||||
const char *ipa_get_version_string(enum ipa_hw_type ver);
|
||||
|
||||
#endif /* _IPA_COMMON_I_H_ */
|
||||
1194
drivers/platform/msm/ipa/ipa_rm.c
Normal file
1194
drivers/platform/msm/ipa/ipa_rm.c
Normal file
File diff suppressed because it is too large
Load diff
251
drivers/platform/msm/ipa/ipa_rm_dependency_graph.c
Normal file
251
drivers/platform/msm/ipa/ipa_rm_dependency_graph.c
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
/* Copyright (c) 2013-2016, 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/slab.h>
|
||||
#include "ipa_rm_dependency_graph.h"
|
||||
#include "ipa_rm_i.h"
|
||||
|
||||
static int ipa_rm_dep_get_index(enum ipa_rm_resource_name resource_name)
|
||||
{
|
||||
int resource_index = IPA_RM_INDEX_INVALID;
|
||||
|
||||
if (IPA_RM_RESORCE_IS_PROD(resource_name))
|
||||
resource_index = ipa_rm_prod_index(resource_name);
|
||||
else if (IPA_RM_RESORCE_IS_CONS(resource_name))
|
||||
resource_index = ipa_rm_cons_index(resource_name);
|
||||
|
||||
return resource_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa_rm_dep_graph_create() - creates graph
|
||||
* @dep_graph: [out] created dependency graph
|
||||
*
|
||||
* Returns: dependency graph on success, NULL on failure
|
||||
*/
|
||||
int ipa_rm_dep_graph_create(struct ipa_rm_dep_graph **dep_graph)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
*dep_graph = kzalloc(sizeof(**dep_graph), GFP_KERNEL);
|
||||
if (!*dep_graph) {
|
||||
IPA_RM_ERR("no mem\n");
|
||||
result = -ENOMEM;
|
||||
goto bail;
|
||||
}
|
||||
bail:
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa_rm_dep_graph_delete() - destroyes the graph
|
||||
* @graph: [in] dependency graph
|
||||
*
|
||||
* Frees all resources.
|
||||
*/
|
||||
void ipa_rm_dep_graph_delete(struct ipa_rm_dep_graph *graph)
|
||||
{
|
||||
int resource_index;
|
||||
|
||||
if (!graph) {
|
||||
IPA_RM_ERR("invalid params\n");
|
||||
return;
|
||||
}
|
||||
for (resource_index = 0;
|
||||
resource_index < IPA_RM_RESOURCE_MAX;
|
||||
resource_index++)
|
||||
kfree(graph->resource_table[resource_index]);
|
||||
memset(graph->resource_table, 0, sizeof(graph->resource_table));
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa_rm_dep_graph_get_resource() - provides a resource by name
|
||||
* @graph: [in] dependency graph
|
||||
* @name: [in] name of the resource
|
||||
* @resource: [out] resource in case of success
|
||||
*
|
||||
* Returns: 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_rm_dep_graph_get_resource(
|
||||
struct ipa_rm_dep_graph *graph,
|
||||
enum ipa_rm_resource_name resource_name,
|
||||
struct ipa_rm_resource **resource)
|
||||
{
|
||||
int result;
|
||||
int resource_index;
|
||||
|
||||
if (!graph) {
|
||||
result = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
resource_index = ipa_rm_dep_get_index(resource_name);
|
||||
if (resource_index == IPA_RM_INDEX_INVALID) {
|
||||
result = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
*resource = graph->resource_table[resource_index];
|
||||
if (!*resource) {
|
||||
result = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
result = 0;
|
||||
bail:
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa_rm_dep_graph_add() - adds resource to graph
|
||||
* @graph: [in] dependency graph
|
||||
* @resource: [in] resource to add
|
||||
*
|
||||
* Returns: 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_rm_dep_graph_add(struct ipa_rm_dep_graph *graph,
|
||||
struct ipa_rm_resource *resource)
|
||||
{
|
||||
int result = 0;
|
||||
int resource_index;
|
||||
|
||||
if (!graph || !resource) {
|
||||
result = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
resource_index = ipa_rm_dep_get_index(resource->name);
|
||||
if (resource_index == IPA_RM_INDEX_INVALID) {
|
||||
result = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
graph->resource_table[resource_index] = resource;
|
||||
bail:
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa_rm_dep_graph_remove() - removes resource from graph
|
||||
* @graph: [in] dependency graph
|
||||
* @resource: [in] resource to add
|
||||
*
|
||||
* Returns: 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_rm_dep_graph_remove(struct ipa_rm_dep_graph *graph,
|
||||
enum ipa_rm_resource_name resource_name)
|
||||
{
|
||||
if (!graph)
|
||||
return -EINVAL;
|
||||
graph->resource_table[resource_name] = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa_rm_dep_graph_add_dependency() - adds dependency between
|
||||
* two nodes in graph
|
||||
* @graph: [in] dependency graph
|
||||
* @resource_name: [in] resource to add
|
||||
* @depends_on_name: [in] resource to add
|
||||
* @userspace_dep: [in] operation requested by userspace ?
|
||||
*
|
||||
* Returns: 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_rm_dep_graph_add_dependency(struct ipa_rm_dep_graph *graph,
|
||||
enum ipa_rm_resource_name resource_name,
|
||||
enum ipa_rm_resource_name depends_on_name,
|
||||
bool userspace_dep)
|
||||
{
|
||||
struct ipa_rm_resource *dependent = NULL;
|
||||
struct ipa_rm_resource *dependency = NULL;
|
||||
int result;
|
||||
|
||||
if (!graph ||
|
||||
!IPA_RM_RESORCE_IS_PROD(resource_name) ||
|
||||
!IPA_RM_RESORCE_IS_CONS(depends_on_name)) {
|
||||
IPA_RM_ERR("invalid params\n");
|
||||
result = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
if (ipa_rm_dep_graph_get_resource(graph,
|
||||
resource_name,
|
||||
&dependent)) {
|
||||
IPA_RM_ERR("%s does not exist\n",
|
||||
ipa_rm_resource_str(resource_name));
|
||||
result = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
if (ipa_rm_dep_graph_get_resource(graph,
|
||||
depends_on_name,
|
||||
&dependency)) {
|
||||
IPA_RM_ERR("%s does not exist\n",
|
||||
ipa_rm_resource_str(depends_on_name));
|
||||
result = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
result = ipa_rm_resource_add_dependency(dependent, dependency,
|
||||
userspace_dep);
|
||||
bail:
|
||||
IPA_RM_DBG("EXIT with %d\n", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa_rm_dep_graph_delete_dependency() - deleted dependency between
|
||||
* two nodes in graph
|
||||
* @graph: [in] dependency graph
|
||||
* @resource_name: [in] resource to delete
|
||||
* @depends_on_name: [in] resource to delete
|
||||
* @userspace_dep: [in] operation requested by userspace ?
|
||||
*
|
||||
* Returns: 0 on success, negative on failure
|
||||
*
|
||||
*/
|
||||
int ipa_rm_dep_graph_delete_dependency(struct ipa_rm_dep_graph *graph,
|
||||
enum ipa_rm_resource_name resource_name,
|
||||
enum ipa_rm_resource_name depends_on_name,
|
||||
bool userspace_dep)
|
||||
{
|
||||
struct ipa_rm_resource *dependent = NULL;
|
||||
struct ipa_rm_resource *dependency = NULL;
|
||||
int result;
|
||||
|
||||
if (!graph ||
|
||||
!IPA_RM_RESORCE_IS_PROD(resource_name) ||
|
||||
!IPA_RM_RESORCE_IS_CONS(depends_on_name)) {
|
||||
IPA_RM_ERR("invalid params\n");
|
||||
result = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (ipa_rm_dep_graph_get_resource(graph,
|
||||
resource_name,
|
||||
&dependent)) {
|
||||
IPA_RM_ERR("%s does not exist\n",
|
||||
ipa_rm_resource_str(resource_name));
|
||||
result = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (ipa_rm_dep_graph_get_resource(graph,
|
||||
depends_on_name,
|
||||
&dependency)) {
|
||||
IPA_RM_ERR("%s does not exist\n",
|
||||
ipa_rm_resource_str(depends_on_name));
|
||||
result = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
result = ipa_rm_resource_delete_dependency(dependent, dependency,
|
||||
userspace_dep);
|
||||
bail:
|
||||
IPA_RM_DBG("EXIT with %d\n", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
49
drivers/platform/msm/ipa/ipa_rm_dependency_graph.h
Normal file
49
drivers/platform/msm/ipa/ipa_rm_dependency_graph.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/* Copyright (c) 2013-2016, 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 _IPA_RM_DEPENDENCY_GRAPH_H_
|
||||
#define _IPA_RM_DEPENDENCY_GRAPH_H_
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/ipa.h>
|
||||
#include "ipa_rm_resource.h"
|
||||
|
||||
struct ipa_rm_dep_graph {
|
||||
struct ipa_rm_resource *resource_table[IPA_RM_RESOURCE_MAX];
|
||||
};
|
||||
|
||||
int ipa_rm_dep_graph_get_resource(
|
||||
struct ipa_rm_dep_graph *graph,
|
||||
enum ipa_rm_resource_name name,
|
||||
struct ipa_rm_resource **resource);
|
||||
|
||||
int ipa_rm_dep_graph_create(struct ipa_rm_dep_graph **dep_graph);
|
||||
|
||||
void ipa_rm_dep_graph_delete(struct ipa_rm_dep_graph *graph);
|
||||
|
||||
int ipa_rm_dep_graph_add(struct ipa_rm_dep_graph *graph,
|
||||
struct ipa_rm_resource *resource);
|
||||
|
||||
int ipa_rm_dep_graph_remove(struct ipa_rm_dep_graph *graph,
|
||||
enum ipa_rm_resource_name resource_name);
|
||||
|
||||
int ipa_rm_dep_graph_add_dependency(struct ipa_rm_dep_graph *graph,
|
||||
enum ipa_rm_resource_name resource_name,
|
||||
enum ipa_rm_resource_name depends_on_name,
|
||||
bool userspsace_dep);
|
||||
|
||||
int ipa_rm_dep_graph_delete_dependency(struct ipa_rm_dep_graph *graph,
|
||||
enum ipa_rm_resource_name resource_name,
|
||||
enum ipa_rm_resource_name depends_on_name,
|
||||
bool userspsace_dep);
|
||||
|
||||
#endif /* _IPA_RM_DEPENDENCY_GRAPH_H_ */
|
||||
157
drivers/platform/msm/ipa/ipa_rm_i.h
Normal file
157
drivers/platform/msm/ipa/ipa_rm_i.h
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/* Copyright (c) 2013-2016, 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 _IPA_RM_I_H_
|
||||
#define _IPA_RM_I_H_
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/ipa.h>
|
||||
#include "ipa_rm_resource.h"
|
||||
#include "ipa_common_i.h"
|
||||
|
||||
#define IPA_RM_DRV_NAME "ipa_rm"
|
||||
|
||||
#define IPA_RM_DBG_LOW(fmt, args...) \
|
||||
do { \
|
||||
pr_debug(IPA_RM_DRV_NAME " %s:%d " fmt, __func__, __LINE__, \
|
||||
## args); \
|
||||
IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
|
||||
IPA_RM_DRV_NAME " %s:%d " fmt, ## args); \
|
||||
} while (0)
|
||||
#define IPA_RM_DBG(fmt, args...) \
|
||||
do { \
|
||||
pr_debug(IPA_RM_DRV_NAME " %s:%d " fmt, __func__, __LINE__, \
|
||||
## args); \
|
||||
IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
|
||||
IPA_RM_DRV_NAME " %s:%d " fmt, ## args); \
|
||||
IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
|
||||
IPA_RM_DRV_NAME " %s:%d " fmt, ## args); \
|
||||
} while (0)
|
||||
|
||||
#define IPA_RM_ERR(fmt, args...) \
|
||||
do { \
|
||||
pr_err(IPA_RM_DRV_NAME " %s:%d " fmt, __func__, __LINE__, \
|
||||
## args); \
|
||||
IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
|
||||
IPA_RM_DRV_NAME " %s:%d " fmt, ## args); \
|
||||
IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
|
||||
IPA_RM_DRV_NAME " %s:%d " fmt, ## args); \
|
||||
} while (0)
|
||||
|
||||
#define IPA_RM_RESOURCE_CONS_MAX \
|
||||
(IPA_RM_RESOURCE_MAX - IPA_RM_RESOURCE_PROD_MAX)
|
||||
#define IPA_RM_RESORCE_IS_PROD(x) \
|
||||
(x >= IPA_RM_RESOURCE_PROD && x < IPA_RM_RESOURCE_PROD_MAX)
|
||||
#define IPA_RM_RESORCE_IS_CONS(x) \
|
||||
(x >= IPA_RM_RESOURCE_PROD_MAX && x < IPA_RM_RESOURCE_MAX)
|
||||
#define IPA_RM_INDEX_INVALID (-1)
|
||||
#define IPA_RM_RELEASE_DELAY_IN_MSEC 1000
|
||||
|
||||
int ipa_rm_prod_index(enum ipa_rm_resource_name resource_name);
|
||||
int ipa_rm_cons_index(enum ipa_rm_resource_name resource_name);
|
||||
|
||||
/**
|
||||
* struct ipa_rm_delayed_release_work_type - IPA RM delayed resource release
|
||||
* work type
|
||||
* @delayed_work: work struct
|
||||
* @ipa_rm_resource_name: name of the resource on which this work should be done
|
||||
* @needed_bw: bandwidth required for resource in Mbps
|
||||
* @dec_usage_count: decrease usage count on release ?
|
||||
*/
|
||||
struct ipa_rm_delayed_release_work_type {
|
||||
struct delayed_work work;
|
||||
enum ipa_rm_resource_name resource_name;
|
||||
u32 needed_bw;
|
||||
bool dec_usage_count;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ipa_rm_wq_cmd - workqueue commands
|
||||
*/
|
||||
enum ipa_rm_wq_cmd {
|
||||
IPA_RM_WQ_NOTIFY_PROD,
|
||||
IPA_RM_WQ_NOTIFY_CONS,
|
||||
IPA_RM_WQ_RESOURCE_CB
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ipa_rm_wq_work_type - IPA RM worqueue specific
|
||||
* work type
|
||||
* @work: work struct
|
||||
* @wq_cmd: command that should be processed in workqueue context
|
||||
* @resource_name: name of the resource on which this work
|
||||
* should be done
|
||||
* @dep_graph: data structure to search for resource if exists
|
||||
* @event: event to notify
|
||||
* @notify_registered_only: notify only clients registered by
|
||||
* ipa_rm_register()
|
||||
*/
|
||||
struct ipa_rm_wq_work_type {
|
||||
struct work_struct work;
|
||||
enum ipa_rm_wq_cmd wq_cmd;
|
||||
enum ipa_rm_resource_name resource_name;
|
||||
enum ipa_rm_event event;
|
||||
bool notify_registered_only;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ipa_rm_wq_suspend_resume_work_type - IPA RM worqueue resume or
|
||||
* suspend work type
|
||||
* @work: work struct
|
||||
* @resource_name: name of the resource on which this work
|
||||
* should be done
|
||||
* @prev_state:
|
||||
* @needed_bw:
|
||||
*/
|
||||
struct ipa_rm_wq_suspend_resume_work_type {
|
||||
struct work_struct work;
|
||||
enum ipa_rm_resource_name resource_name;
|
||||
enum ipa_rm_resource_state prev_state;
|
||||
u32 needed_bw;
|
||||
|
||||
};
|
||||
|
||||
int ipa_rm_wq_send_cmd(enum ipa_rm_wq_cmd wq_cmd,
|
||||
enum ipa_rm_resource_name resource_name,
|
||||
enum ipa_rm_event event,
|
||||
bool notify_registered_only);
|
||||
|
||||
int ipa_rm_wq_send_resume_cmd(enum ipa_rm_resource_name resource_name,
|
||||
enum ipa_rm_resource_state prev_state,
|
||||
u32 needed_bw);
|
||||
|
||||
int ipa_rm_wq_send_suspend_cmd(enum ipa_rm_resource_name resource_name,
|
||||
enum ipa_rm_resource_state prev_state,
|
||||
u32 needed_bw);
|
||||
|
||||
int ipa_rm_initialize(void);
|
||||
|
||||
int ipa_rm_stat(char *buf, int size);
|
||||
|
||||
const char *ipa_rm_resource_str(enum ipa_rm_resource_name resource_name);
|
||||
|
||||
void ipa_rm_perf_profile_change(enum ipa_rm_resource_name resource_name);
|
||||
|
||||
int ipa_rm_request_resource_with_timer(enum ipa_rm_resource_name resource_name);
|
||||
|
||||
void delayed_release_work_func(struct work_struct *work);
|
||||
|
||||
int ipa_rm_add_dependency_from_ioctl(enum ipa_rm_resource_name resource_name,
|
||||
enum ipa_rm_resource_name depends_on_name);
|
||||
|
||||
int ipa_rm_delete_dependency_from_ioctl(enum ipa_rm_resource_name resource_name,
|
||||
enum ipa_rm_resource_name depends_on_name);
|
||||
|
||||
void ipa_rm_exit(void);
|
||||
|
||||
#endif /* _IPA_RM_I_H_ */
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue