diff options
author | David S. Miller <davem@davemloft.net> | 2021-06-13 23:49:39 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-06-13 23:49:39 +0300 |
commit | a212d9f33ed0b8399bd9829a779c4024068742a2 (patch) | |
tree | d5c840d5e5b3b958ba13bdd7544c4cf80cf53e88 /drivers/net/wwan/iosm/iosm_ipc_pcie.h | |
parent | ffbbc5e5c7174dc4732f78b9577a19621079c879 (diff) | |
parent | f7af616c632ee2ac3af0876fe33bf9e0232e665a (diff) | |
download | linux-a212d9f33ed0b8399bd9829a779c4024068742a2.tar.xz |
Merge branch 'iosm-driver'
M Chetan Kumar says:
====================
net: iosm: PCIe Driver for Intel M.2 Modem
The IOSM (IPC over Shared Memory) driver is a PCIe host driver implemented
for linux or chrome platform for data exchange over PCIe interface between
Host platform & Intel M.2 Modem. The driver exposes interface conforming to
the MBIM protocol. Any front end application ( eg: Modem Manager) could
easily manage the MBIM interface to enable data communication towards WWAN.
Intel M.2 modem uses 2 BAR regions. The first region is dedicated to Doorbell
register for IRQs and the second region is used as scratchpad area for book
keeping modem execution stage details along with host system shared memory
region context details. The upper edge of the driver exposes the control and
data channels for user space application interaction. At lower edge these data
and control channels are associated to pipes. The pipes are lowest level
interfaces used over PCIe as a logical channel for message exchange. A single
channel maps to UL and DL pipe and are initialized on device open.
On UL path, driver copies application sent data to SKBs associate it with
transfer descriptor and puts it on to ring buffer for DMA transfer. Once
information has been updated in shared memory region, host gives a Doorbell
to modem to perform DMA and modem uses MSI to communicate back to host.
For receiving data in DL path, SKBs are pre-allocated during pipe open and
transfer descriptors are given to modem for DMA transfer.
The driver exposes two types of ports, namely "wwan0mbim0", a char device node
which is used for MBIM control operation and "wwan0-x",(x = 0,1,2..7) network
interfaces for IP data communication.
1) MBIM Control Interface:
This node exposes an interface between modem and application using char device
exposed by "IOSM" driver to establish and manage the MBIM data communication
with PCIe based Intel M.2 Modems.
2) MBIM Data Interface:
The IOSM driver exposes IP link interface "wwan0-x" of type "wwan" for IP traffic.
Iproute network utility is used for creating "wwan0-x" network interface and for
associating it with MBIM IP session. The Driver supports upto 8 IP sessions for
simultaneous IP communication.
This applies on top of WWAN core rtnetlink series posted here:
https://lore.kernel.org/netdev/1623486057-13075-1-git-send-email-loic.poulain@linaro.org/
Also driver has been compiled and tested on top of netdev net-next tree.
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wwan/iosm/iosm_ipc_pcie.h')
-rw-r--r-- | drivers/net/wwan/iosm/iosm_ipc_pcie.h | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/drivers/net/wwan/iosm/iosm_ipc_pcie.h b/drivers/net/wwan/iosm/iosm_ipc_pcie.h new file mode 100644 index 000000000000..7d1f0cd7364c --- /dev/null +++ b/drivers/net/wwan/iosm/iosm_ipc_pcie.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (C) 2020-21 Intel Corporation. + */ + +#ifndef IOSM_IPC_PCIE_H +#define IOSM_IPC_PCIE_H + +#include <linux/device.h> +#include <linux/pci.h> +#include <linux/skbuff.h> + +#include "iosm_ipc_irq.h" + +/* Device ID */ +#define INTEL_CP_DEVICE_7560_ID 0x7560 + +/* Define for BAR area usage */ +#define IPC_DOORBELL_BAR0 0 +#define IPC_SCRATCHPAD_BAR2 2 + +/* Defines for DOORBELL registers information */ +#define IPC_DOORBELL_CH_OFFSET BIT(5) +#define IPC_WRITE_PTR_REG_0 BIT(4) +#define IPC_CAPTURE_PTR_REG_0 BIT(3) + +/* Number of MSI used for IPC */ +#define IPC_MSI_VECTORS 1 + +/* Total number of Maximum IPC IRQ vectors used for IPC */ +#define IPC_IRQ_VECTORS IPC_MSI_VECTORS + +/** + * enum ipc_pcie_sleep_state - Enum type to different sleep state transitions + * @IPC_PCIE_D0L12: Put the sleep state in D0L12 + * @IPC_PCIE_D3L2: Put the sleep state in D3L2 + */ +enum ipc_pcie_sleep_state { + IPC_PCIE_D0L12, + IPC_PCIE_D3L2, +}; + +/** + * struct iosm_pcie - IPC_PCIE struct. + * @pci: Address of the device description + * @dev: Pointer to generic device structure + * @ipc_regs: Remapped CP doorbell address of the irq register + * set, to fire the doorbell irq. + * @scratchpad: Remapped CP scratchpad address, to send the + * configuration. tuple and the IPC descriptors + * to CP in the ROM phase. The config tuple + * information are saved on the MSI scratchpad. + * @imem: Pointer to imem data struct + * @ipc_regs_bar_nr: BAR number to be used for IPC doorbell + * @scratchpad_bar_nr: BAR number to be used for Scratchpad + * @nvec: number of requested irq vectors + * @doorbell_reg_offset: doorbell_reg_offset + * @doorbell_write: doorbell write register + * @doorbell_capture: doorbell capture resgister + * @suspend: S2IDLE sleep/active + * @d3l2_support: Read WWAN RTD3 BIOS setting for D3L2 support + */ +struct iosm_pcie { + struct pci_dev *pci; + struct device *dev; + void __iomem *ipc_regs; + void __iomem *scratchpad; + struct iosm_imem *imem; + int ipc_regs_bar_nr; + int scratchpad_bar_nr; + int nvec; + u32 doorbell_reg_offset; + u32 doorbell_write; + u32 doorbell_capture; + unsigned long suspend; + enum ipc_pcie_sleep_state d3l2_support; +}; + +/** + * struct ipc_skb_cb - Struct definition of the socket buffer which is mapped to + * the cb field of sbk + * @mapping: Store physical or IOVA mapped address of skb virtual add. + * @direction: DMA direction + * @len: Length of the DMA mapped region + * @op_type: Expected values are defined about enum ipc_ul_usr_op. + */ +struct ipc_skb_cb { + dma_addr_t mapping; + int direction; + int len; + u8 op_type; +}; + +/** + * enum ipc_ul_usr_op - Control operation to execute the right action on + * the user interface. + * @UL_USR_OP_BLOCKED: The uplink app was blocked until CP confirms that the + * uplink buffer was consumed triggered by the IRQ. + * @UL_MUX_OP_ADB: In MUX mode the UL ADB shall be addedd to the free list. + * @UL_DEFAULT: SKB in non muxing mode + */ +enum ipc_ul_usr_op { + UL_USR_OP_BLOCKED, + UL_MUX_OP_ADB, + UL_DEFAULT, +}; + +/** + * ipc_pcie_addr_map - Maps the kernel's virtual address to either IOVA + * address space or Physical address space, the mapping is + * stored in the skb's cb. + * @ipc_pcie: Pointer to struct iosm_pcie + * @data: Skb mem containing data + * @size: Data size + * @mapping: Dma mapping address + * @direction: Data direction + * + * Returns: 0 on success and failure value on error + */ +int ipc_pcie_addr_map(struct iosm_pcie *ipc_pcie, unsigned char *data, + size_t size, dma_addr_t *mapping, int direction); + +/** + * ipc_pcie_addr_unmap - Unmaps the skb memory region from IOVA address space + * @ipc_pcie: Pointer to struct iosm_pcie + * @size: Data size + * @mapping: Dma mapping address + * @direction: Data direction + */ +void ipc_pcie_addr_unmap(struct iosm_pcie *ipc_pcie, size_t size, + dma_addr_t mapping, int direction); + +/** + * ipc_pcie_alloc_skb - Allocate an uplink SKB for the given size. + * @ipc_pcie: Pointer to struct iosm_pcie + * @size: Size of the SKB required. + * @flags: Allocation flags + * @mapping: Copies either mapped IOVA add. or converted Phy address + * @direction: DMA data direction + * @headroom: Header data offset + * + * Returns: Pointer to ipc_skb on Success, NULL on failure. + */ +struct sk_buff *ipc_pcie_alloc_skb(struct iosm_pcie *ipc_pcie, size_t size, + gfp_t flags, dma_addr_t *mapping, + int direction, size_t headroom); + +/** + * ipc_pcie_alloc_local_skb - Allocate a local SKB for the given size. + * @ipc_pcie: Pointer to struct iosm_pcie + * @flags: Allocation flags + * @size: Size of the SKB required. + * + * Returns: Pointer to ipc_skb on Success, NULL on failure. + */ +struct sk_buff *ipc_pcie_alloc_local_skb(struct iosm_pcie *ipc_pcie, + gfp_t flags, size_t size); + +/** + * ipc_pcie_kfree_skb - Free skb allocated by ipc_pcie_alloc_*_skb(). + * @ipc_pcie: Pointer to struct iosm_pcie + * @skb: Pointer to the skb + */ +void ipc_pcie_kfree_skb(struct iosm_pcie *ipc_pcie, struct sk_buff *skb); + +/** + * ipc_pcie_check_data_link_active - Check Data Link Layer Active + * @ipc_pcie: Pointer to struct iosm_pcie + * + * Returns: true if active, otherwise false + */ +bool ipc_pcie_check_data_link_active(struct iosm_pcie *ipc_pcie); + +/** + * ipc_pcie_suspend - Callback invoked by pm_runtime_suspend. It decrements + * the device's usage count then, carry out a suspend, + * either synchronous or asynchronous. + * @ipc_pcie: Pointer to struct iosm_pcie + * + * Returns: 0 on success and failure value on error + */ +int ipc_pcie_suspend(struct iosm_pcie *ipc_pcie); + +/** + * ipc_pcie_resume - Callback invoked by pm_runtime_resume. It increments + * the device's usage count then, carry out a resume, + * either synchronous or asynchronous. + * @ipc_pcie: Pointer to struct iosm_pcie + * + * Returns: 0 on success and failure value on error + */ +int ipc_pcie_resume(struct iosm_pcie *ipc_pcie); + +/** + * ipc_pcie_check_aspm_enabled - Check if ASPM L1 is already enabled + * @ipc_pcie: Pointer to struct iosm_pcie + * @parent: True if checking ASPM L1 for parent else false + * + * Returns: true if ASPM is already enabled else false + */ +bool ipc_pcie_check_aspm_enabled(struct iosm_pcie *ipc_pcie, + bool parent); +/** + * ipc_pcie_config_aspm - Configure ASPM L1 + * @ipc_pcie: Pointer to struct iosm_pcie + */ +void ipc_pcie_config_aspm(struct iosm_pcie *ipc_pcie); + +#endif |