mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 15:11:48 -04:00
Merge tag 'LA.UM.9.14.r1-21200-LAHAINA.QSSI13.0' of https://git.codelinaro.org/clo/la/kernel/msm-5.4 into android13-5.4-lahaina
"LA.UM.9.14.r1-21200-LAHAINA.QSSI13.0" * tag 'LA.UM.9.14.r1-21200-LAHAINA.QSSI13.0' of https://git.codelinaro.org/clo/la/kernel/msm-5.4: msm: ipa: add support for PMIPv6 msm: kgsl: Use dma_buf_get() to get dma_buf structure msm: ipa3: Update MPLS DL Vlan tag array to use 16 bits soc: qcom: qsee_ipc_irq_bridge: Remove redundant cleanup wait: Fix __wait_event_hrtimeout for RT/DL tasks msm: mhi_dev: Add support for MSI disable spi: spi-msm-geni: Handle IRQ enable and disable msm: ipa: Add disable_msi flag msm: ep_pcie: Enable BME Deassert IRQ Revert "wait: Fix __wait_event_hrtimeout for RT/DL tasks" net: qrtr: Prevent wakeups using service id based filter msm: ipa: Rmnet CV2X header file changes msm: mhi-net-dev: Set MIN and MAX MTU size for Ethernet packet msm: mhi-net-dev: Don't over-write skb length mfd: qcom-spmi-pmic: Add remove API msm: ep_pcie: Add support for MSI disable cnss2: Add API to send WFC mode to WLAN FW cnss2: Add data length validation in cnss_wlfw_qdss_data_send_sync() icnss2: Add data length validation in cnss_wlfw_qdss_data_send_sync() mhi: core: Add the basic sanity to check the irq registration cnss2: Unregister host driver during PCI remove net: qrtr: haven: Add bounds check on tx path msm: ipa: Add DSCP PCP mapping info ioctl rpmsg: glink: Remove dev_set_name to avoid KASAN issue net: qrtr: haven: Add bounds check in rx path icnss2: Add data length validation in cnss_wlfw_qdss_data_send_sync() devfreq: memlat: Change number of array elements for holding core_stats cpu-topology: Change the size of allocation for cpu's raw_capacity iio: qcom-spmi-adc5: remove the remove callback cnss2: Validate maximum number of memory segments cnss2: Add data length validation in cnss_wlfw_qdss_data_send_sync() Reverts below USB and netfilter patches memshare: Free QMI handle only if its valid ANDROID: arm64: mm: perform clean & invalidation in __dma_map_area arm64: mm: Don't invalidate FROM_DEVICE buffers at start of DMA transfer msm: ep_pcie: Sending PME for device initiated D3cold exit Conflicts: arch/arm64/boot/dts/vendor/bindings/dma/moxa,moxart-dma.txt drivers/mmc/core/sd.c drivers/rpmsg/qcom_glink_native.c include/linux/rmap.h mm/rmap.c Change-Id: Ifc094d4b928fb27ebb4c344cbcf914d9697d705c
This commit is contained in:
commit
d5a4546147
42 changed files with 3951 additions and 4345 deletions
|
|
@ -1 +1 @@
|
|||
LTS_5.4.210_7e6cbbe7e59a
|
||||
LTS_5.4.226_d72fdcc7094f
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1372,6 +1372,7 @@
|
|||
kthread_stop
|
||||
kthread_unpark
|
||||
kthread_worker_fn
|
||||
ktime_add_safe
|
||||
ktime_get
|
||||
ktime_get_mono_fast_ns
|
||||
ktime_get_real_seconds
|
||||
|
|
@ -2418,6 +2419,7 @@
|
|||
strrchr
|
||||
strreplace
|
||||
strscpy
|
||||
strscpy_pad
|
||||
strsep
|
||||
strstr
|
||||
__sw_hweight32
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
|
|||
&cpu_capacity);
|
||||
if (!ret) {
|
||||
if (!raw_capacity) {
|
||||
raw_capacity = kcalloc(num_possible_cpus(),
|
||||
raw_capacity = kcalloc(cpumask_last(cpu_possible_mask),
|
||||
sizeof(*raw_capacity),
|
||||
GFP_KERNEL);
|
||||
if (!raw_capacity) {
|
||||
|
|
|
|||
|
|
@ -435,8 +435,11 @@ int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl)
|
|||
mhi_intvec_threaded_handlr,
|
||||
IRQF_ONESHOT | IRQF_NO_SUSPEND,
|
||||
"mhi", mhi_cntrl);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
MHI_CNTRL_ERR("Error in requesting threaded irq:%d, ret=%d\n",
|
||||
mhi_cntrl->irq[0], ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) {
|
||||
if (!mhi_event->request_irq)
|
||||
|
|
|
|||
|
|
@ -907,7 +907,7 @@ static int memlat_mon_probe(struct platform_device *pdev, bool is_compute)
|
|||
}
|
||||
}
|
||||
|
||||
num_cpus = cpumask_weight(&mon->cpus);
|
||||
num_cpus = (cpumask_last(&mon->cpus) - cpumask_first(&mon->cpus)) + 1;
|
||||
|
||||
hw = &mon->hw;
|
||||
hw->of_node = of_parse_phandle(dev->of_node, "qcom,target-dev", 0);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2008-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <uapi/linux/msm_ion.h>
|
||||
|
|
@ -2583,6 +2583,15 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_DMA_SHARED_BUFFER
|
||||
static int match_file(const void *p, struct file *file, unsigned int fd)
|
||||
{
|
||||
/*
|
||||
* We must return fd + 1 because iterate_fd stops searching on
|
||||
* non-zero return, but 0 is a valid fd.
|
||||
*/
|
||||
return (p == file) ? (fd + 1) : 0;
|
||||
}
|
||||
|
||||
static void _setup_cache_mode(struct kgsl_mem_entry *entry,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
|
|
@ -2619,6 +2628,8 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device,
|
|||
vma = find_vma(current->mm, hostptr);
|
||||
|
||||
if (vma && vma->vm_file) {
|
||||
int fd;
|
||||
|
||||
ret = check_vma_flags(vma, entry->memdesc.flags);
|
||||
if (ret) {
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
|
|
@ -2634,10 +2645,27 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device,
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Take a refcount because dma_buf_put() decrements the refcount */
|
||||
get_file(vma->vm_file);
|
||||
|
||||
dmabuf = vma->vm_file->private_data;
|
||||
/* Look for the fd that matches this vma file */
|
||||
fd = iterate_fd(current->files, 0, match_file, vma->vm_file);
|
||||
if (fd) {
|
||||
dmabuf = dma_buf_get(fd - 1);
|
||||
if (IS_ERR(dmabuf)) {
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
return PTR_ERR(dmabuf);
|
||||
}
|
||||
/*
|
||||
* It is possible that the fd obtained from iterate_fd
|
||||
* was closed before passing the fd to dma_buf_get().
|
||||
* Hence dmabuf returned by dma_buf_get() could be
|
||||
* different from vma->vm_file->private_data. Return
|
||||
* failure if this happens.
|
||||
*/
|
||||
if (dmabuf != vma->vm_file->private_data) {
|
||||
dma_buf_put(dmabuf);
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
return -EBADF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dmabuf) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
|
@ -1454,21 +1455,12 @@ static int adc5_probe(struct platform_device *pdev)
|
|||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
|
||||
static int adc5_exit(struct platform_device *pdev)
|
||||
{
|
||||
struct adc5_chip *adc = platform_get_drvdata(pdev);
|
||||
|
||||
mutex_destroy(&adc->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver adc5_driver = {
|
||||
.driver = {
|
||||
.name = "qcom-spmi-adc5",
|
||||
.of_match_table = adc5_match_table,
|
||||
},
|
||||
.probe = adc5_probe,
|
||||
.remove = adc5_exit,
|
||||
};
|
||||
module_platform_driver(adc5_driver);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2015, 2017-2019, The Linux Foundation.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -146,8 +147,11 @@ static int pmic_spmi_probe(struct spmi_device *sdev)
|
|||
|
||||
MODULE_DEVICE_TABLE(of, pmic_spmi_id_table);
|
||||
|
||||
static void pmic_spmi_remove(struct spmi_device *sdev) {}
|
||||
|
||||
static struct spmi_driver pmic_spmi_driver = {
|
||||
.probe = pmic_spmi_probe,
|
||||
.remove = pmic_spmi_remove,
|
||||
.driver = {
|
||||
.name = "pmic-spmi",
|
||||
.of_match_table = pmic_spmi_id_table,
|
||||
|
|
|
|||
|
|
@ -1179,6 +1179,7 @@ cont:
|
|||
card->clk_scaling_highest = mmc_sd_get_max_clock(card);
|
||||
card->clk_scaling_lowest = host->f_min;
|
||||
#endif
|
||||
|
||||
host->card = card;
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -3134,6 +3134,27 @@ cnss_is_converged_dt(struct cnss_plat_data *plat_priv)
|
|||
return of_property_read_bool(plat_priv->plat_dev->dev.of_node,
|
||||
"qcom,converged-dt");
|
||||
}
|
||||
|
||||
int cnss_set_wfc_mode(struct device *dev, struct cnss_wfc_cfg cfg)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
/* If IMS server is connected, return success without QMI send */
|
||||
if (test_bit(CNSS_IMS_CONNECTED, &plat_priv->driver_state)) {
|
||||
cnss_pr_dbg("Ignore host request as IMS server is connected");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = cnss_wlfw_send_host_wfc_call_status(plat_priv, cfg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_set_wfc_mode);
|
||||
|
||||
static int cnss_probe(struct platform_device *plat_dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#define MAX_NO_OF_MAC_ADDR 4
|
||||
#define QMI_WLFW_MAX_TIMESTAMP_LEN 32
|
||||
#define QMI_WLFW_MAX_NUM_MEM_SEG 32
|
||||
#define QMI_WLFW_MAX_BUILD_ID_LEN 128
|
||||
#define CNSS_RDDM_TIMEOUT_MS 20000
|
||||
#define RECOVERY_TIMEOUT 60000
|
||||
|
|
@ -456,10 +455,10 @@ struct cnss_plat_data {
|
|||
char fw_build_id[QMI_WLFW_MAX_BUILD_ID_LEN + 1];
|
||||
u32 otp_version;
|
||||
u32 fw_mem_seg_len;
|
||||
struct cnss_fw_mem fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG];
|
||||
struct cnss_fw_mem fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
|
||||
struct cnss_fw_mem m3_mem;
|
||||
u32 qdss_mem_seg_len;
|
||||
struct cnss_fw_mem qdss_mem[QMI_WLFW_MAX_NUM_MEM_SEG];
|
||||
struct cnss_fw_mem qdss_mem[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
|
||||
u32 *qdss_reg;
|
||||
struct cnss_pin_connect_result pin_result;
|
||||
struct dentry *root_dentry;
|
||||
|
|
|
|||
|
|
@ -3039,8 +3039,12 @@ int cnss_pci_register_driver_hdlr(struct cnss_pci_data *pci_priv,
|
|||
|
||||
int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
|
||||
struct cnss_plat_data *plat_priv;
|
||||
|
||||
if (!pci_priv)
|
||||
return -EINVAL;
|
||||
|
||||
plat_priv = pci_priv->plat_priv;
|
||||
set_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
|
||||
cnss_pci_dev_shutdown(pci_priv);
|
||||
pci_priv->driver_ops = NULL;
|
||||
|
|
@ -5739,7 +5743,9 @@ static void cnss_pci_unregister_mhi(struct cnss_pci_data *pci_priv)
|
|||
mhi_unregister_mhi_controller(mhi_ctrl);
|
||||
cnss_pci_mhi_ipc_logging_deinit(pci_priv);
|
||||
kfree(mhi_ctrl->irq);
|
||||
mhi_ctrl->irq = NULL;
|
||||
mhi_free_controller(mhi_ctrl);
|
||||
pci_priv->mhi_ctrl = NULL;
|
||||
}
|
||||
|
||||
static void cnss_pci_config_regs(struct cnss_pci_data *pci_priv)
|
||||
|
|
@ -6118,6 +6124,7 @@ static void cnss_pci_remove(struct pci_dev *pci_dev)
|
|||
struct cnss_plat_data *plat_priv =
|
||||
cnss_bus_dev_to_plat_priv(&pci_dev->dev);
|
||||
|
||||
cnss_pci_unregister_driver_hdlr(pci_priv);
|
||||
cnss_pci_free_m3_mem(pci_priv);
|
||||
cnss_pci_free_fw_mem(pci_priv);
|
||||
cnss_pci_free_qdss_mem(pci_priv);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
|
|
@ -930,7 +930,8 @@ int cnss_wlfw_qdss_data_send_sync(struct cnss_plat_data *plat_priv, char *file_n
|
|||
resp->total_size == total_size) &&
|
||||
(resp->seg_id_valid == 1 && resp->seg_id == req->seg_id) &&
|
||||
(resp->data_valid == 1 &&
|
||||
resp->data_len <= QMI_WLFW_MAX_DATA_SIZE_V01)) {
|
||||
resp->data_len <= QMI_WLFW_MAX_DATA_SIZE_V01) &&
|
||||
resp->data_len <= remaining) {
|
||||
memcpy(p_qdss_trace_data_temp,
|
||||
resp->data, resp->data_len);
|
||||
} else {
|
||||
|
|
@ -1956,6 +1957,72 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int cnss_wlfw_send_host_wfc_call_status(struct cnss_plat_data *plat_priv,
|
||||
struct cnss_wfc_cfg cfg)
|
||||
{
|
||||
struct wlfw_wfc_call_status_req_msg_v01 *req;
|
||||
struct wlfw_wfc_call_status_resp_msg_v01 *resp;
|
||||
struct qmi_txn txn;
|
||||
int ret = 0;
|
||||
|
||||
if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
|
||||
cnss_pr_err("Drop host WFC indication as FW not initialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
req = kzalloc(sizeof(*req), GFP_KERNEL);
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
|
||||
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
|
||||
if (!resp) {
|
||||
kfree(req);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
req->wfc_call_active_valid = 1;
|
||||
req->wfc_call_active = cfg.mode;
|
||||
cnss_pr_dbg("CNSS->FW: WFC_CALL_REQ: state: 0x%lx\n",
|
||||
plat_priv->driver_state);
|
||||
ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
|
||||
wlfw_wfc_call_status_resp_msg_v01_ei, resp);
|
||||
if (ret < 0) {
|
||||
cnss_pr_err("CNSS->FW: WFC_CALL_REQ: QMI Txn Init: Err %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
cnss_pr_dbg("Send WFC Mode: %d\n", cfg.mode);
|
||||
ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
|
||||
QMI_WLFW_WFC_CALL_STATUS_REQ_V01,
|
||||
WLFW_WFC_CALL_STATUS_REQ_MSG_V01_MAX_MSG_LEN,
|
||||
wlfw_wfc_call_status_req_msg_v01_ei, req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
cnss_pr_err("CNSS->FW: WFC_CALL_REQ: QMI Send Err: %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
|
||||
if (ret < 0) {
|
||||
cnss_pr_err("FW->CNSS: WFC_CALL_RSP: QMI Wait Err: %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
|
||||
cnss_pr_err("FW->CNSS: WFC_CALL_RSP: Result: %d Err: %d\n",
|
||||
resp->resp.result, resp->resp.error);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
out:
|
||||
kfree(req);
|
||||
kfree(resp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cnss_wlfw_wfc_call_status_send_sync
|
||||
(struct cnss_plat_data *plat_priv,
|
||||
const struct ims_private_service_wfc_call_status_ind_msg_v01 *ind_msg)
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ int cnss_wlfw_qdss_data_send_sync(struct cnss_plat_data *plat_priv, char *file_n
|
|||
u32 total_size);
|
||||
int wlfw_qdss_trace_send_start(struct cnss_plat_data *plat_priv);
|
||||
int wlfw_qdss_trace_send_stop(struct cnss_plat_data *plat_priv, unsigned long long option);
|
||||
int cnss_wlfw_send_host_wfc_call_status(struct cnss_plat_data *plat_priv,
|
||||
struct cnss_wfc_cfg cfg);
|
||||
#else
|
||||
#define QMI_WLFW_TIMEOUT_MS 10000
|
||||
|
||||
|
|
@ -285,6 +287,12 @@ int wlfw_qdss_trace_send_stop(struct cnss_plat_data *plat_priv, unsigned long lo
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_wlfw_send_host_wfc_call_status(struct cnss_plat_data *plat_priv,
|
||||
struct cnss_wfc_cfg cfg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_CNSS2_QMI */
|
||||
|
||||
#ifdef CONFIG_CNSS2_DEBUG
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@
|
|||
#define PCIE20_PARF_INT_ALL_STATUS 0x224
|
||||
#define PCIE20_PARF_INT_ALL_CLEAR 0x228
|
||||
#define PCIE20_PARF_INT_ALL_MASK 0x22C
|
||||
#define PCIE20_PARF_INT_ALL_2_STATUS 0x500
|
||||
#define PCIE20_PARF_INT_ALL_2_CLEAR 0x504
|
||||
#define PCIE20_PARF_INT_ALL_2_MASK 0x508
|
||||
|
||||
#define PCIE20_PARF_CLKREQ_OVERRIDE 0x2B0
|
||||
#define PCIE20_PARF_CLKREQ_IN_OVERRIDE_STS BIT(5)
|
||||
|
|
@ -94,6 +97,8 @@
|
|||
#define PCIE20_SUBSYSTEM 0x2c
|
||||
#define PCIE20_CAP_ID_NXT_PTR 0x40
|
||||
#define PCIE20_CON_STATUS 0x44
|
||||
#define PCIE20_MASK_PME_EN BIT(8)
|
||||
#define PCIE20_MASK_PME_STATUS BIT(15)
|
||||
#define PCIE20_MSI_CAP_ID_NEXT_CTRL 0x50
|
||||
#define PCIE20_MSI_LOWER 0x54
|
||||
#define PCIE20_MSI_UPPER 0x58
|
||||
|
|
@ -173,6 +178,7 @@
|
|||
#define MSI_EXIT_L1SS_WAIT_MAX_COUNT 100
|
||||
#define XMLH_LINK_UP 0x400
|
||||
#define PARF_XMLH_LINK_UP 0x40000000
|
||||
#define CFG_BUS_MASTER_EN_DEASSERT BIT(24)
|
||||
|
||||
#define MAX_PROP_SIZE 32
|
||||
#define MAX_MSG_LEN 80
|
||||
|
|
@ -360,6 +366,8 @@ struct ep_pcie_dev_t {
|
|||
bool mhi_soc_reset_en;
|
||||
bool aoss_rst_clear;
|
||||
bool avoid_reboot_in_d3hot;
|
||||
bool pme_in_wake_from_d3cold;
|
||||
bool bme_deassert_irq;
|
||||
u32 dbi_base_reg;
|
||||
u32 slv_space_reg;
|
||||
u32 phy_status_reg;
|
||||
|
|
@ -411,6 +419,8 @@ struct ep_pcie_dev_t {
|
|||
int perst_irq;
|
||||
atomic_t host_wake_pending;
|
||||
bool conf_ipa_msi_iatu;
|
||||
bool wake_from_d3cold;
|
||||
bool pme_en_d3;
|
||||
|
||||
struct ep_pcie_register_event *event_reg;
|
||||
struct work_struct handle_bme_work;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
#include "ep_pcie_com.h"
|
||||
#include <asm/dma-iommu.h>
|
||||
|
|
@ -46,6 +47,9 @@
|
|||
#define ICC_AVG_BW 500
|
||||
#define ICC_PEAK_BW 800
|
||||
#define PERST_RAW_RESET_STATUS BIT(11)
|
||||
#define PCIE_PME_COUNT 2
|
||||
#define PCIE_PME_SLEEP_DELAY_US 10000
|
||||
#define PCIE_PME_RESEND_DELAY_US 100000
|
||||
|
||||
/* debug mask sys interface */
|
||||
static int ep_pcie_debug_mask;
|
||||
|
|
@ -120,6 +124,7 @@ static const struct ep_pcie_irq_info_t ep_pcie_irq_info[EP_PCIE_MAX_IRQ] = {
|
|||
};
|
||||
|
||||
static int ep_pcie_core_wakeup_host_internal(enum ep_pcie_event event);
|
||||
static void ep_pcie_core_issue_inband_pme(void);
|
||||
|
||||
int ep_pcie_get_debug_mask(void)
|
||||
{
|
||||
|
|
@ -790,6 +795,17 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
|
|||
ep_pcie_write_mask(dev->dm_core + PCIE20_CAP_ID_NXT_PTR, 0,
|
||||
BIT(31)|BIT(30)|BIT(27));
|
||||
|
||||
if (dev->pme_in_wake_from_d3cold && dev->pme_en_d3) {
|
||||
/*
|
||||
* PME_ENABLE is cleared after d3cold state if
|
||||
* retention flops are not present in the target.
|
||||
* Set PME_ENABLE, if it is seen as set during
|
||||
* d3hot to send PME message
|
||||
*/
|
||||
ep_pcie_write_mask(dev->dm_core + PCIE20_CON_STATUS, 0, PCIE20_MASK_PME_EN);
|
||||
dev->pme_en_d3 = false;
|
||||
}
|
||||
|
||||
/* Set the Endpoint L0s Acceptable Latency to 1us (max) */
|
||||
ep_pcie_write_reg_field(dev->dm_core,
|
||||
PCIE20_DEVICE_CAPABILITIES,
|
||||
|
|
@ -858,8 +874,16 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
|
|||
ep_pcie_write_mask(dev->parf +
|
||||
PCIE20_PARF_INT_ALL_MASK, 0,
|
||||
BIT(EP_PCIE_INT_EVT_L1SUB_TIMEOUT));
|
||||
if (dev->bme_deassert_irq) {
|
||||
ep_pcie_write_reg(dev->parf, PCIE20_PARF_INT_ALL_2_MASK, 0);
|
||||
ep_pcie_write_mask(dev->parf + PCIE20_PARF_INT_ALL_2_MASK, 0,
|
||||
CFG_BUS_MASTER_EN_DEASSERT);
|
||||
EP_PCIE_INFO(dev,
|
||||
"PCIe V%d: PCIE20_PARF_INT_ALL_2_MASK:0x%x\n", dev->rev,
|
||||
readl_relaxed(dev->parf + PCIE20_PARF_INT_ALL_2_MASK));
|
||||
}
|
||||
|
||||
EP_PCIE_DBG(dev, "PCIe V%d: PCIE20_PARF_INT_ALL_MASK:0x%x\n",
|
||||
EP_PCIE_INFO(dev, "PCIe V%d: PCIE20_PARF_INT_ALL_MASK:0x%x\n",
|
||||
dev->rev,
|
||||
readl_relaxed(dev->parf + PCIE20_PARF_INT_ALL_MASK));
|
||||
}
|
||||
|
|
@ -1675,6 +1699,46 @@ static void ep_pcie_core_toggle_wake_gpio(bool is_on)
|
|||
|
||||
}
|
||||
|
||||
static void ep_pcie_core_issue_pme_for_wake_from_d3cold(void)
|
||||
{
|
||||
struct ep_pcie_dev_t *dev = &ep_pcie_dev;
|
||||
u32 pme_count = 0, pme_reg;
|
||||
bool pme_en, pme_status;
|
||||
|
||||
pme_reg = readl_relaxed(dev->dm_core + PCIE20_CON_STATUS);
|
||||
pme_en = pme_reg & PCIE20_MASK_PME_EN;
|
||||
pme_status = pme_reg & PCIE20_MASK_PME_STATUS;
|
||||
|
||||
EP_PCIE_INFO(dev, "PCIe V%d: pme_reg: 0x%x, pme_en: %d, pme_status: %d\n",
|
||||
dev->rev, pme_reg, pme_en, pme_status);
|
||||
|
||||
if (pme_en) {
|
||||
do {
|
||||
/* Sending PME for device initiated d3_cold exit */
|
||||
ep_pcie_core_issue_inband_pme();
|
||||
/*Polling for pme_status to be 0 for 100ms*/
|
||||
readx_poll_timeout(readl_relaxed, dev->dm_core + PCIE20_CON_STATUS, pme_reg,
|
||||
!(pme_reg & PCIE20_MASK_PME_STATUS), PCIE_PME_SLEEP_DELAY_US,
|
||||
PCIE_PME_RESEND_DELAY_US);
|
||||
|
||||
pme_status = pme_reg & PCIE20_MASK_PME_STATUS;
|
||||
EP_PCIE_DBG(dev, "PCIe V%d: pme_status:%d\n", dev->rev, pme_status);
|
||||
|
||||
pme_count++;
|
||||
|
||||
if (!pme_status)
|
||||
break;
|
||||
|
||||
} while (pme_count < PCIE_PME_COUNT);
|
||||
|
||||
if (pme_status && pme_count == PCIE_PME_COUNT) {
|
||||
EP_PCIE_INFO(dev,
|
||||
"PCIe V%d: Host failed to acknowledge PME for device-initiated wake\n",
|
||||
dev->rev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -1951,6 +2015,16 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
|
|||
dev->rev);
|
||||
}
|
||||
|
||||
if (dev->pme_in_wake_from_d3cold && dev->wake_from_d3cold) {
|
||||
/*
|
||||
* Sending PME after link training for device
|
||||
* initiated D3cold to D0 transition, based on
|
||||
* PCIe specification
|
||||
*/
|
||||
ep_pcie_core_issue_pme_for_wake_from_d3cold();
|
||||
dev->wake_from_d3cold = false;
|
||||
}
|
||||
|
||||
checkbme:
|
||||
/* Clear AOSS_CC_RESET_STATUS::PERST_RAW_RESET_STATUS when linking up */
|
||||
if (dev->aoss_rst_clear)
|
||||
|
|
@ -2277,6 +2351,9 @@ static irqreturn_t ep_pcie_handle_dstate_change_irq(int irq, void *data)
|
|||
dev->rev, dev->d3_counter);
|
||||
ep_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, 0, BIT(1));
|
||||
|
||||
dev->pme_en_d3 = readl_relaxed(dev->dm_core +
|
||||
PCIE20_CON_STATUS) & PCIE20_MASK_PME_EN;
|
||||
|
||||
if (dev->enumerated)
|
||||
ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_D3_HOT);
|
||||
else
|
||||
|
|
@ -2537,6 +2614,30 @@ static irqreturn_t ep_pcie_handle_clkreq_irq(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* ep_pcie_handle_bme_deassert_irq - Check the second status register of PCIe's
|
||||
* interrupts and print error log for BME deassert IRQ.
|
||||
* @dev: PCIe endpoint device structure.
|
||||
* @status2: Second status register of PCIe's interrupts.
|
||||
*/
|
||||
static void ep_pcie_handle_bme_deassert_irq(struct ep_pcie_dev_t *dev, u32 status2)
|
||||
{
|
||||
bool bme;
|
||||
u32 mask2 = readl_relaxed(dev->parf + PCIE20_PARF_INT_ALL_2_MASK);
|
||||
|
||||
ep_pcie_write_mask(dev->parf + PCIE20_PARF_INT_ALL_2_CLEAR, 0, status2);
|
||||
|
||||
EP_PCIE_DUMP(dev,
|
||||
"PCIe V%d: Global IRQ received; status2:0x%x; mask2:0x%x\n",
|
||||
dev->rev, status2, mask2);
|
||||
|
||||
if (status2 & CFG_BUS_MASTER_EN_DEASSERT) {
|
||||
bme = readl_relaxed(dev->dm_core + PCIE20_COMMAND_STATUS) & BIT(2);
|
||||
EP_PCIE_ERR(dev, "PCIe V%d: BME deassert IRQ received, BME = %d\n",
|
||||
dev->rev, bme);
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t ep_pcie_handle_global_irq(int irq, void *data)
|
||||
{
|
||||
struct ep_pcie_dev_t *dev = data;
|
||||
|
|
@ -2606,6 +2707,12 @@ static irqreturn_t ep_pcie_handle_global_irq(int irq, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
if (dev->bme_deassert_irq) {
|
||||
status = readl_relaxed(dev->parf + PCIE20_PARF_INT_ALL_2_STATUS);
|
||||
if (status)
|
||||
ep_pcie_handle_bme_deassert_irq(dev, status);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
@ -2952,7 +3059,7 @@ int ep_pcie_core_config_outbound_iatu(struct ep_pcie_iatu entries[],
|
|||
|
||||
int ep_pcie_core_get_msi_config(struct ep_pcie_msi_config *cfg)
|
||||
{
|
||||
u32 cap, lower, upper, data, ctrl_reg;
|
||||
u32 cap, lower, upper, data;
|
||||
static u32 changes;
|
||||
|
||||
if (ep_pcie_dev.link_status == EP_PCIE_LINK_DISABLED) {
|
||||
|
|
@ -2966,24 +3073,15 @@ int ep_pcie_core_get_msi_config(struct ep_pcie_msi_config *cfg)
|
|||
EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: MSI CAP:0x%x\n",
|
||||
ep_pcie_dev.rev, cap);
|
||||
|
||||
if (!(cap & BIT(16))) {
|
||||
EP_PCIE_ERR(&ep_pcie_dev,
|
||||
"PCIe V%d: MSI is not enabled yet\n",
|
||||
ep_pcie_dev.rev);
|
||||
return EP_PCIE_ERROR;
|
||||
}
|
||||
if (cap & BIT(16)) {
|
||||
lower = readl_relaxed(ep_pcie_dev.dm_core + PCIE20_MSI_LOWER);
|
||||
upper = readl_relaxed(ep_pcie_dev.dm_core + PCIE20_MSI_UPPER);
|
||||
data = readl_relaxed(ep_pcie_dev.dm_core + PCIE20_MSI_DATA);
|
||||
|
||||
lower = readl_relaxed(ep_pcie_dev.dm_core + PCIE20_MSI_LOWER);
|
||||
upper = readl_relaxed(ep_pcie_dev.dm_core + PCIE20_MSI_UPPER);
|
||||
data = readl_relaxed(ep_pcie_dev.dm_core + PCIE20_MSI_DATA);
|
||||
ctrl_reg = readl_relaxed(ep_pcie_dev.dm_core +
|
||||
PCIE20_MSI_CAP_ID_NEXT_CTRL);
|
||||
EP_PCIE_DBG(&ep_pcie_dev,
|
||||
"PCIe V%d: MSI info: lower:0x%x; upper:0x%x; data:0x%x\n",
|
||||
ep_pcie_dev.rev, lower, upper, data);
|
||||
|
||||
EP_PCIE_DBG(&ep_pcie_dev,
|
||||
"PCIe V%d: MSI info: lower:0x%x; upper:0x%x; data:0x%x\n",
|
||||
ep_pcie_dev.rev, lower, upper, data);
|
||||
|
||||
if (ctrl_reg & BIT(16)) {
|
||||
struct resource *msi =
|
||||
ep_pcie_dev.res[EP_PCIE_RES_MSI].resource;
|
||||
if (ep_pcie_dev.active_config)
|
||||
|
|
@ -3046,10 +3144,10 @@ int ep_pcie_core_get_msi_config(struct ep_pcie_msi_config *cfg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
EP_PCIE_ERR(&ep_pcie_dev,
|
||||
"PCIe V%d: Wrong MSI info found when MSI is enabled: lower:0x%x; data:0x%x\n",
|
||||
ep_pcie_dev.rev, lower, data);
|
||||
return EP_PCIE_ERROR;
|
||||
EP_PCIE_INFO(&ep_pcie_dev,
|
||||
"PCIe V%d: MSI is not enabled yet or not supported\n",
|
||||
ep_pcie_dev.rev);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int ep_pcie_core_trigger_msi(u32 idx)
|
||||
|
|
@ -3116,10 +3214,9 @@ int ep_pcie_core_trigger_msi(u32 idx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
EP_PCIE_ERR(&ep_pcie_dev,
|
||||
"PCIe V%d: MSI is not enabled yet. MSI addr:0x%x; data:0x%x; index from client:%d\n",
|
||||
ep_pcie_dev.rev, addr, data, idx);
|
||||
return EP_PCIE_ERROR;
|
||||
EP_PCIE_INFO(&ep_pcie_dev, "MSI is disabled or not supported\n",
|
||||
ep_pcie_dev.rev);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void ep_pcie_core_issue_inband_pme(void)
|
||||
|
|
@ -3147,6 +3244,13 @@ static int ep_pcie_core_wakeup_host_internal(enum ep_pcie_event event)
|
|||
if (!atomic_read(&dev->perst_deast)) {
|
||||
/*D3 cold handling*/
|
||||
ep_pcie_core_toggle_wake_gpio(true);
|
||||
if (dev->pme_in_wake_from_d3cold) {
|
||||
/*
|
||||
* Set below flag for device initiated
|
||||
* d3cold wake to send PME message
|
||||
*/
|
||||
dev->wake_from_d3cold = true;
|
||||
}
|
||||
} else if (dev->l23_ready) {
|
||||
EP_PCIE_ERR(dev,
|
||||
"PCIe V%d: request to assert WAKE# when in D3hot\n",
|
||||
|
|
@ -3423,6 +3527,18 @@ static int ep_pcie_probe(struct platform_device *pdev)
|
|||
"PCIe V%d: PME during reboot/panic (in D3hot) is %s needed\n",
|
||||
ep_pcie_dev.rev, ep_pcie_dev.avoid_reboot_in_d3hot ? "" : "not");
|
||||
|
||||
ep_pcie_dev.pme_in_wake_from_d3cold =
|
||||
of_property_read_bool((&pdev->dev)->of_node,
|
||||
"qcom,pme-in-wake-from-d3cold");
|
||||
EP_PCIE_DBG(&ep_pcie_dev,
|
||||
"PCIe V%d: PME is%s sent during wake from d3cold\n",
|
||||
ep_pcie_dev.rev, ep_pcie_dev.pme_in_wake_from_d3cold ? "" : " not");
|
||||
|
||||
ep_pcie_dev.bme_deassert_irq = of_property_read_bool((&pdev->dev)->of_node,
|
||||
"qcom,pcie-bme-deassert-irq");
|
||||
EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: BME deassert irq is%s enabled\n",
|
||||
ep_pcie_dev.rev, ep_pcie_dev.bme_deassert_irq ? "" : " not");
|
||||
|
||||
ret = of_property_read_u32((&pdev->dev)->of_node,
|
||||
"qcom,mhi-soc-reset-offset",
|
||||
&ep_pcie_dev.mhi_soc_reset_offset);
|
||||
|
|
|
|||
|
|
@ -281,7 +281,11 @@ static int mhi_dev_schedule_msi_ipa(struct mhi_dev *mhi, struct event_req *ereq)
|
|||
int rc;
|
||||
|
||||
rc = ep_pcie_get_msi_config(mhi->phandle, &cfg);
|
||||
if (rc) {
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
mhi_log(MHI_MSG_VERBOSE, "MSI is disabled\n");
|
||||
mhi_ctx->msi_disable = true;
|
||||
return 0;
|
||||
} else if (rc) {
|
||||
mhi_log(MHI_MSG_ERROR, "Error retrieving pcie msi logic\n");
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -335,6 +339,24 @@ static void mhi_dev_event_rd_offset_completion_cb(void *req)
|
|||
if (ereq->event_rd_dma)
|
||||
dma_unmap_single(&mhi_ctx->pdev->dev, ereq->event_rd_dma,
|
||||
sizeof(uint64_t), DMA_TO_DEVICE);
|
||||
|
||||
/*
|
||||
* The mhi_dev_cmd_event_msi_cb and mhi_dev_event_msi_cb APIs does
|
||||
* add back the flushed events space to the event buffer and returns
|
||||
* the event req back to the list. These are registered in the API
|
||||
* mhi_dev_schedule_msi_ipa and get invoked when MSI triggering is
|
||||
* complete.
|
||||
* In the case of MSI being disabled by the host, these callbacks will
|
||||
* not get invoked as triggering MSI is suppressed from device side.
|
||||
* Hence, invoking these callbacks as part of this API to ensure we do
|
||||
* not run out on ereq buffer space in this scenario.
|
||||
*/
|
||||
if (mhi_ctx->msi_disable) {
|
||||
if (ereq->is_cmd_cpl)
|
||||
mhi_dev_cmd_event_msi_cb(ereq);
|
||||
else
|
||||
mhi_dev_event_msi_cb(ereq);
|
||||
}
|
||||
}
|
||||
|
||||
static void mhi_dev_cmd_event_msi_cb(void *req)
|
||||
|
|
@ -415,7 +437,11 @@ static int mhi_trigger_msi_edma(struct mhi_dev_ring *ring, u32 idx)
|
|||
|
||||
if (!mhi_ctx->msi_lower) {
|
||||
rc = ep_pcie_get_msi_config(mhi_ctx->phandle, &cfg);
|
||||
if (rc) {
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
mhi_log(MHI_MSG_VERBOSE, "MSI is disabled\n");
|
||||
mhi_ctx->msi_disable = true;
|
||||
return 0;
|
||||
} else if (rc) {
|
||||
mhi_log(MHI_MSG_ERROR,
|
||||
"Error retrieving pcie msi logic\n");
|
||||
return rc;
|
||||
|
|
@ -1425,7 +1451,10 @@ static int mhi_hwc_init(struct mhi_dev *mhi)
|
|||
|
||||
/* Call IPA HW_ACC Init with MSI Address and db routing info */
|
||||
rc = ep_pcie_get_msi_config(mhi_ctx->phandle, &cfg);
|
||||
if (rc) {
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
mhi_log(MHI_MSG_VERBOSE, "MSI is disabled\n");
|
||||
mhi_ctx->msi_disable = true;
|
||||
} else if (rc) {
|
||||
mhi_log(MHI_MSG_ERROR,
|
||||
"Error retrieving pcie msi logic\n");
|
||||
return rc;
|
||||
|
|
@ -1450,6 +1479,7 @@ static int mhi_hwc_init(struct mhi_dev *mhi)
|
|||
ipa_init_params.msi.mask = ((1 << cfg.msg_num) - 1);
|
||||
ipa_init_params.first_er_idx = erdb_cfg.base;
|
||||
ipa_init_params.first_ch_idx = HW_CHANNEL_BASE;
|
||||
ipa_init_params.disable_msi = mhi_ctx->msi_disable;
|
||||
|
||||
if (mhi_ctx->config_iatu)
|
||||
ipa_init_params.mmio_addr =
|
||||
|
|
@ -1642,7 +1672,10 @@ int mhi_dev_send_event(struct mhi_dev *mhi, int evnt_ring,
|
|||
struct mhi_addr transfer_addr;
|
||||
|
||||
rc = ep_pcie_get_msi_config(mhi->phandle, &cfg);
|
||||
if (rc) {
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
mhi_log(MHI_MSG_VERBOSE, "MSI is disabled\n");
|
||||
mhi_ctx->msi_disable = true;
|
||||
} else if (rc) {
|
||||
mhi_log(MHI_MSG_ERROR, "Error retrieving pcie msi logic\n");
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -3759,16 +3792,19 @@ static int mhi_dev_recover(struct mhi_dev *mhi)
|
|||
mhi_log(MHI_MSG_VERBOSE, "mhi_state = 0x%X, reset = %d\n",
|
||||
state, mhi_reset);
|
||||
|
||||
if (mhi_ctx->msi_disable)
|
||||
goto poll_for_reset;
|
||||
|
||||
rc = mhi_dev_mmio_read(mhi, BHI_INTVEC, &bhi_intvec);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
while (bhi_intvec == 0xffffffff &&
|
||||
bhi_max_cnt < MHI_BHI_INTVEC_MAX_CNT) {
|
||||
bhi_max_cnt < MHI_BHI_INTVEC_MAX_CNT) {
|
||||
/* Wait for Host to set the bhi_intvec */
|
||||
msleep(MHI_BHI_INTVEC_WAIT_MS);
|
||||
mhi_log(MHI_MSG_VERBOSE,
|
||||
"Wait for Host to set BHI_INTVEC\n");
|
||||
"Wait for Host to set BHI_INTVEC\n");
|
||||
rc = mhi_dev_mmio_read(mhi, BHI_INTVEC, &bhi_intvec);
|
||||
if (rc) {
|
||||
mhi_log(MHI_MSG_ERROR,
|
||||
|
|
@ -3780,12 +3816,12 @@ static int mhi_dev_recover(struct mhi_dev *mhi)
|
|||
|
||||
if (bhi_max_cnt == MHI_BHI_INTVEC_MAX_CNT) {
|
||||
mhi_log(MHI_MSG_ERROR,
|
||||
"Host failed to set BHI_INTVEC\n");
|
||||
"Host failed to set BHI_INTVEC\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bhi_intvec != 0xffffffff) {
|
||||
/* Indicate the host that the device is ready */
|
||||
/* Indicate the host that device is ready */
|
||||
rc = ep_pcie_trigger_msi(mhi->phandle, bhi_intvec);
|
||||
if (rc) {
|
||||
mhi_log(MHI_MSG_ERROR, "error sending msi\n");
|
||||
|
|
@ -3793,6 +3829,7 @@ static int mhi_dev_recover(struct mhi_dev *mhi)
|
|||
}
|
||||
}
|
||||
|
||||
poll_for_reset:
|
||||
/* Poll for the host to set the reset bit */
|
||||
rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset);
|
||||
if (rc) {
|
||||
|
|
@ -4313,6 +4350,7 @@ static void mhi_dev_reinit(struct work_struct *work)
|
|||
static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
struct ep_pcie_msi_config cfg;
|
||||
int rc = 0;
|
||||
|
||||
/*
|
||||
|
|
@ -4360,6 +4398,24 @@ static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetching MSI config to read the MSI capability and setting the
|
||||
* msi_disable flag based on it.
|
||||
*/
|
||||
rc = ep_pcie_get_msi_config(mhi_ctx->phandle, &cfg);
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
mhi_log(MHI_MSG_VERBOSE, "MSI is disabled\n");
|
||||
mhi_ctx->msi_disable = true;
|
||||
} else if (!rc) {
|
||||
mhi_ctx->msi_disable = false;
|
||||
} else {
|
||||
mhi_log(MHI_MSG_ERROR,
|
||||
"Error retrieving pcie msi logic\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
mhi_log(MHI_MSG_VERBOSE, "msi_disable = %d\n", mhi_ctx->msi_disable);
|
||||
|
||||
rc = mhi_dev_recover(mhi_ctx);
|
||||
if (rc) {
|
||||
mhi_log(MHI_MSG_ERROR, "get mhi state failed\n");
|
||||
|
|
|
|||
|
|
@ -527,6 +527,7 @@ struct mhi_dev {
|
|||
|
||||
uint32_t *mmio_backup;
|
||||
struct mhi_config cfg;
|
||||
bool msi_disable;
|
||||
u32 msi_data;
|
||||
u32 msi_lower;
|
||||
spinlock_t msi_lock;
|
||||
|
|
|
|||
|
|
@ -238,14 +238,13 @@ static void mhi_dev_net_read_completion_cb(void *req)
|
|||
struct sk_buff *skb = mreq->context;
|
||||
unsigned long flags;
|
||||
|
||||
skb->len = mreq->transfer_len;
|
||||
skb_put(skb, mreq->transfer_len);
|
||||
|
||||
if (net_handle->eth_iface)
|
||||
skb->protocol = eth_type_trans(skb, net_handle->dev);
|
||||
else
|
||||
skb->protocol = mhi_dev_net_eth_type_trans(skb);
|
||||
|
||||
skb_put(skb, mreq->transfer_len);
|
||||
net_handle->dev->stats.rx_packets++;
|
||||
skb->dev = net_handle->dev;
|
||||
netif_rx(skb);
|
||||
|
|
@ -450,6 +449,8 @@ static void mhi_dev_net_ether_setup(struct net_device *dev)
|
|||
{
|
||||
dev->netdev_ops = &mhi_dev_net_ops_ip;
|
||||
ether_setup(dev);
|
||||
dev->min_mtu = ETH_MIN_MTU;
|
||||
dev->max_mtu = ETH_MAX_MTU;
|
||||
mhi_dev_net_log(MHI_INFO,
|
||||
"mhi_dev_net Ethernet setup\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -479,7 +479,7 @@ static int mhi_sm_prepare_resume(void)
|
|||
case MHI_DEV_READY_STATE:
|
||||
res = ep_pcie_get_msi_config(mhi_sm_ctx->mhi_dev->phandle,
|
||||
&cfg);
|
||||
if (res) {
|
||||
if (res && res != -EOPNOTSUPP) {
|
||||
MHI_SM_ERR("Error retrieving pcie msi logic\n");
|
||||
goto exit;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2225,7 +2225,6 @@ static int glink_slatecom_probe(struct platform_device *pdev)
|
|||
dev = glink->dev;
|
||||
dev->of_node = pdev->dev.of_node;
|
||||
dev->release = glink_slatecom_release;
|
||||
dev_set_name(dev, "%s", dev->of_node->name);
|
||||
dev_set_drvdata(dev, glink);
|
||||
|
||||
ret = of_property_read_string(dev->of_node, "label", &glink->name);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "icnss2_qmi: " fmt
|
||||
|
|
@ -1198,7 +1199,8 @@ int icnss_wlfw_qdss_data_send_sync(struct icnss_priv *priv, char *file_name,
|
|||
resp->total_size == total_size) &&
|
||||
(resp->seg_id_valid == 1 && resp->seg_id == req->seg_id) &&
|
||||
(resp->data_valid == 1 &&
|
||||
resp->data_len <= QMI_WLFW_MAX_DATA_SIZE_V01)) {
|
||||
resp->data_len <= QMI_WLFW_MAX_DATA_SIZE_V01) &&
|
||||
resp->data_len <= remaining) {
|
||||
memcpy(p_qdss_trace_data_temp,
|
||||
resp->data, resp->data_len);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
|
|
@ -779,6 +780,7 @@ static void memshare_init_worker(struct work_struct *work)
|
|||
dev_err(memsh_drv->dev,
|
||||
"memshare: Creating mem_share_svc qmi handle failed\n");
|
||||
kfree(mem_share_svc_handle);
|
||||
mem_share_svc_handle = NULL;
|
||||
destroy_workqueue(mem_share_svc_workqueue);
|
||||
return;
|
||||
}
|
||||
|
|
@ -787,8 +789,11 @@ static void memshare_init_worker(struct work_struct *work)
|
|||
if (rc < 0) {
|
||||
dev_err(memsh_drv->dev,
|
||||
"memshare: Registering mem share svc failed %d\n", rc);
|
||||
qmi_handle_release(mem_share_svc_handle);
|
||||
kfree(mem_share_svc_handle);
|
||||
if (mem_share_svc_handle) {
|
||||
qmi_handle_release(mem_share_svc_handle);
|
||||
kfree(mem_share_svc_handle);
|
||||
mem_share_svc_handle = NULL;
|
||||
}
|
||||
destroy_workqueue(mem_share_svc_workqueue);
|
||||
return;
|
||||
}
|
||||
|
|
@ -971,8 +976,11 @@ static int memshare_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
flush_workqueue(mem_share_svc_workqueue);
|
||||
qmi_handle_release(mem_share_svc_handle);
|
||||
kfree(mem_share_svc_handle);
|
||||
if (mem_share_svc_handle) {
|
||||
qmi_handle_release(mem_share_svc_handle);
|
||||
kfree(mem_share_svc_handle);
|
||||
mem_share_svc_handle = NULL;
|
||||
}
|
||||
destroy_workqueue(mem_share_svc_workqueue);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,7 +125,6 @@ static int qiib_driver_data_init(void)
|
|||
*/
|
||||
static void qiib_driver_data_deinit(void)
|
||||
{
|
||||
qiib_cleanup();
|
||||
if (!qiib_info->log_ctx)
|
||||
ipc_log_context_destroy(qiib_info->log_ctx);
|
||||
kfree(qiib_info);
|
||||
|
|
@ -433,8 +432,10 @@ static void qiib_cleanup(void)
|
|||
}
|
||||
mutex_unlock(&qiib_info->list_lock);
|
||||
|
||||
if (!IS_ERR_OR_NULL(qiib_info->classp))
|
||||
if (!IS_ERR_OR_NULL(qiib_info->classp)) {
|
||||
class_destroy(qiib_info->classp);
|
||||
qiib_info->classp = NULL;
|
||||
}
|
||||
|
||||
unregister_chrdev_region(MAJOR(qiib_info->dev_num), qiib_info->nports);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -162,6 +163,7 @@ struct spi_geni_master {
|
|||
int num_tx_eot;
|
||||
int num_rx_eot;
|
||||
int num_xfers;
|
||||
atomic_t is_irq_enable;
|
||||
void *ipc;
|
||||
bool gsi_mode; /* GSI Mode */
|
||||
bool shared_ee; /* Dual EE use case */
|
||||
|
|
@ -181,6 +183,7 @@ struct spi_geni_master {
|
|||
};
|
||||
|
||||
static void spi_slv_setup(struct spi_geni_master *mas);
|
||||
static void spi_geni_irq_enable(struct spi_geni_master *mas, bool irq_flag);
|
||||
|
||||
static ssize_t spi_slave_state_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
|
@ -2087,6 +2090,8 @@ static int spi_geni_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
atomic_set(&geni_mas->is_irq_enable, 0);
|
||||
|
||||
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
|
||||
if (ret) {
|
||||
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
|
||||
|
|
@ -2230,12 +2235,12 @@ static int spi_geni_runtime_suspend(struct device *dev)
|
|||
struct spi_master *spi = get_spi_master(dev);
|
||||
struct spi_geni_master *geni_mas = spi_master_get_devdata(spi);
|
||||
|
||||
disable_irq(geni_mas->irq);
|
||||
if (geni_mas->is_le_vm) {
|
||||
spi_geni_unlock_bus(spi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
spi_geni_irq_enable(geni_mas, false);
|
||||
GENI_SE_DBG(geni_mas->ipc, false, NULL, "%s:\n", __func__);
|
||||
/* Do not unconfigure the GPIOs for a shared_se usecase */
|
||||
if (geni_mas->shared_ee && !geni_mas->shared_se)
|
||||
|
|
@ -2295,7 +2300,7 @@ static int spi_geni_runtime_resume(struct device *dev)
|
|||
|
||||
exit_rt_resume:
|
||||
ret = se_geni_resources_on(&geni_mas->spi_rsc);
|
||||
enable_irq(geni_mas->irq);
|
||||
spi_geni_irq_enable(geni_mas, true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -2342,6 +2347,41 @@ static int spi_geni_suspend(struct device *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* spi_geni_irq_enable() - Enable or Disable irq.
|
||||
* @mas: Pointer to spi_geni_master structure.
|
||||
* @irq_flag: irq flag which indicates irq enable
|
||||
* or disable
|
||||
* irq_flag - false - irq disable
|
||||
* irq_flag - true - irq enable.
|
||||
*
|
||||
* This function is used to enable or disable irq.
|
||||
* Based on irq_flag the enabling or disabling of
|
||||
* irq will be done. Enable if irq_flag is true,
|
||||
* disable if irq_flag is false.
|
||||
* Return: None.
|
||||
*/
|
||||
static void spi_geni_irq_enable(struct spi_geni_master *mas, bool irq_flag)
|
||||
{
|
||||
if (irq_flag) {
|
||||
if (!(atomic_read(&mas->is_irq_enable))) {
|
||||
enable_irq(mas->irq);
|
||||
atomic_set(&mas->is_irq_enable, 1);
|
||||
} else {
|
||||
GENI_SE_DBG(mas->ipc, true, mas->dev,
|
||||
"%s: irq already enabled\n", __func__);
|
||||
}
|
||||
} else {
|
||||
if (atomic_read(&mas->is_irq_enable)) {
|
||||
disable_irq(mas->irq);
|
||||
atomic_set(&mas->is_irq_enable, 0);
|
||||
} else {
|
||||
GENI_SE_DBG(mas->ipc, true, mas->dev,
|
||||
"%s: irq already disabled\n", __func__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops spi_geni_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(spi_geni_runtime_suspend,
|
||||
spi_geni_runtime_resume, NULL)
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type)
|
|||
* dwc3_core_soft_reset - Issues core soft reset and PHY reset
|
||||
* @dwc: pointer to our context structure
|
||||
*/
|
||||
int dwc3_core_soft_reset(struct dwc3 *dwc)
|
||||
static int dwc3_core_soft_reset(struct dwc3 *dwc)
|
||||
{
|
||||
u32 reg;
|
||||
int retries = 1000;
|
||||
|
|
|
|||
|
|
@ -1607,8 +1607,6 @@ bool dwc3_has_imod(struct dwc3 *dwc);
|
|||
int dwc3_event_buffers_setup(struct dwc3 *dwc);
|
||||
void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
|
||||
|
||||
int dwc3_core_soft_reset(struct dwc3 *dwc);
|
||||
|
||||
#if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
|
||||
int dwc3_host_init(struct dwc3 *dwc);
|
||||
void dwc3_host_exit(struct dwc3 *dwc);
|
||||
|
|
|
|||
|
|
@ -566,15 +566,16 @@ int dwc3_drd_init(struct dwc3 *dwc)
|
|||
{
|
||||
int ret, irq;
|
||||
|
||||
if (ROLE_SWITCH &&
|
||||
device_property_read_bool(dwc->dev, "usb-role-switch"))
|
||||
return dwc3_setup_role_switch(dwc);
|
||||
|
||||
dwc->edev = dwc3_get_extcon(dwc);
|
||||
if (IS_ERR(dwc->edev))
|
||||
return PTR_ERR(dwc->edev);
|
||||
|
||||
if (dwc->edev) {
|
||||
if (ROLE_SWITCH &&
|
||||
device_property_read_bool(dwc->dev, "usb-role-switch")) {
|
||||
ret = dwc3_setup_role_switch(dwc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else if (dwc->edev) {
|
||||
dwc->edev_nb.notifier_call = dwc3_drd_notifier;
|
||||
ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
|
||||
&dwc->edev_nb);
|
||||
|
|
|
|||
|
|
@ -4545,7 +4545,7 @@ int dwc3_gadget_resume(struct dwc3 *dwc)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (!dwc->gadget_driver || !dwc->softconnect)
|
||||
if (!dwc->gadget_driver)
|
||||
return 0;
|
||||
|
||||
ret = __dwc3_gadget_start(dwc);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ struct ipa_mhi_msi_info {
|
|||
* @notify: client callback
|
||||
* @priv: client private data to be provided in client callback
|
||||
* @test_mode: flag to indicate if IPA MHI is in unit test mode
|
||||
* @disable_msi: flag to indicate if MSI is disabled.
|
||||
*/
|
||||
struct ipa_mhi_init_params {
|
||||
struct ipa_mhi_msi_info msi;
|
||||
|
|
@ -72,6 +73,7 @@ struct ipa_mhi_init_params {
|
|||
mhi_client_cb notify;
|
||||
void *priv;
|
||||
bool test_mode;
|
||||
bool disable_msi;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _IPA_USB_H_
|
||||
|
|
@ -159,6 +160,7 @@ struct ipa_usb_xdci_chan_params {
|
|||
u64 data_buff_base_addr_iova;
|
||||
struct sg_table *sgt_xfer_rings;
|
||||
struct sg_table *sgt_data_buff;
|
||||
bool is_sw_path;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -279,9 +279,9 @@ int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma);
|
|||
*/
|
||||
struct rmap_walk_control {
|
||||
void *arg;
|
||||
struct vm_area_struct *target_vma;
|
||||
bool try_lock;
|
||||
bool contended;
|
||||
struct vm_area_struct *target_vma;
|
||||
/*
|
||||
* Return false if page table scanning in rmap_walk should be stopped.
|
||||
* Otherwise, return true.
|
||||
|
|
|
|||
|
|
@ -92,6 +92,15 @@ enum cnss_bus_event_type {
|
|||
BUS_EVENT_INVALID = 0xFFFF,
|
||||
};
|
||||
|
||||
enum cnss_wfc_mode {
|
||||
CNSS_WFC_MODE_OFF,
|
||||
CNSS_WFC_MODE_ON,
|
||||
};
|
||||
|
||||
struct cnss_wfc_cfg {
|
||||
enum cnss_wfc_mode mode;
|
||||
};
|
||||
|
||||
struct cnss_hang_event {
|
||||
void *hang_event_data;
|
||||
u16 hang_event_data_len;
|
||||
|
|
@ -281,4 +290,5 @@ extern int cnss_get_mem_segment_info(enum cnss_remote_mem_type type,
|
|||
extern int cnss_send_buffer_to_afcmem(struct device *dev, char *afcdb,
|
||||
uint32_t len, uint8_t slotid);
|
||||
extern int cnss_reset_afcmem(struct device *dev, uint8_t slotid);
|
||||
extern int cnss_set_wfc_mode(struct device *dev, struct cnss_wfc_cfg cfg);
|
||||
#endif /* _NET_CNSS2_H */
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_MSM_IPA_H_
|
||||
|
|
@ -150,6 +150,7 @@
|
|||
#define IPA_IOCTL_DEL_MACSEC_MAPPING 93
|
||||
#define IPA_IOCTL_QUERY_CACHED_DRIVER_MSG 94
|
||||
#define IPA_IOCTL_SET_EXT_ROUTER_MODE 95
|
||||
#define IPA_IOCTL_ADD_DEL_DSCP_PCP_MAPPING 96
|
||||
/**
|
||||
* max size of the header to be inserted
|
||||
*/
|
||||
|
|
@ -215,6 +216,11 @@
|
|||
|
||||
#define IPA_MAX_IPPT_NUM_PORT_FLT 5
|
||||
|
||||
/**
|
||||
* Max number of DSCP entries in uc
|
||||
*/
|
||||
#define IPA_UC_MAX_DSCP_VAL 64
|
||||
|
||||
/**
|
||||
* New feature flag for CV2X config.
|
||||
*/
|
||||
|
|
@ -1522,6 +1528,9 @@ enum ipa_hdr_l2_type {
|
|||
* IPA_HDR_PROC_SET_DSCP:
|
||||
* IPA_HDR_PROC_EoGRE_HEADER_ADD: Add IPV[46] and GRE header
|
||||
* IPA_HDR_PROC_EoGRE_HEADER_REMOVE: Remove IPV[46] and GRE header
|
||||
* IPA_HDR_PROC_WWAN_TO_ETHII_EX: To update PCP value for E2E traffic.
|
||||
* IPA_HDR_PROC_GRE_HEADER_ADD, Add IPV[46] and IP-GRE header
|
||||
* IPA_HDR_PROC_GRE_HEADER_REMOVE, Remove IPV[46] and IP-GRE header
|
||||
*/
|
||||
enum ipa_hdr_proc_type {
|
||||
IPA_HDR_PROC_NONE,
|
||||
|
|
@ -1537,8 +1546,11 @@ enum ipa_hdr_proc_type {
|
|||
IPA_HDR_PROC_SET_DSCP,
|
||||
IPA_HDR_PROC_EoGRE_HEADER_ADD,
|
||||
IPA_HDR_PROC_EoGRE_HEADER_REMOVE,
|
||||
IPA_HDR_PROC_WWAN_TO_ETHII_EX,
|
||||
IPA_HDR_PROC_GRE_HEADER_ADD,
|
||||
IPA_HDR_PROC_GRE_HEADER_REMOVE
|
||||
};
|
||||
#define IPA_HDR_PROC_MAX (IPA_HDR_PROC_EoGRE_HEADER_REMOVE + 1)
|
||||
#define IPA_HDR_PROC_MAX (IPA_HDR_PROC_GRE_HEADER_REMOVE + 1)
|
||||
|
||||
/**
|
||||
* struct ipa_rt_rule - attributes of a routing rule
|
||||
|
|
@ -1739,8 +1751,8 @@ struct IpaDscpVlanPcpMap_t {
|
|||
uint8_t pad3; /* for alignment */
|
||||
uint8_t num_mpls_val_sorted; /* num of elements in mpls_val_sorted */
|
||||
uint32_t mpls_val_sorted[IPA_EoGRE_MAX_VLAN * IPA_GRE_MAX_S_VLAN];
|
||||
uint8_t vlan_c[IPA_EoGRE_MAX_VLAN * IPA_GRE_MAX_S_VLAN];
|
||||
uint8_t vlan_s[IPA_EoGRE_MAX_VLAN * IPA_GRE_MAX_S_VLAN];
|
||||
uint16_t vlan_c[IPA_EoGRE_MAX_VLAN * IPA_GRE_MAX_S_VLAN];
|
||||
uint16_t vlan_s[IPA_EoGRE_MAX_VLAN * IPA_GRE_MAX_S_VLAN];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
|
|
@ -1857,18 +1869,86 @@ struct ipa_eogre_hdr_proc_ctx_params {
|
|||
struct ipa_eogre_header_remove_procparams hdr_remove_param;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct ipa_gre_header_add_procparams -
|
||||
* @eth_hdr_retained: Specifies if Ethernet header is retained or not
|
||||
* @input_ip_version: Specifies if Input header is IPV4(0) or IPV6(1)
|
||||
* @output_ip_version: Specifies if template header's outer IP is IPV4(0) or IPV6(1)
|
||||
* @second_pass: Specifies if the data should be processed again.
|
||||
* @is_mpls: Specifies if ucp cmd is for legacy EoGRE(0) or MPLSoGRE(1)
|
||||
* @tag_remove_len: Specifies amount to be removed for the tags
|
||||
*/
|
||||
struct ipa_gre_header_add_procparams {
|
||||
uint32_t eth_hdr_retained :1;
|
||||
uint32_t input_ip_version :1;
|
||||
uint32_t output_ip_version :1;
|
||||
uint32_t second_pass :1;
|
||||
uint32_t is_mpls :1;
|
||||
uint32_t tag_remove_len :4;
|
||||
uint32_t reserved :23;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ipa_gre_header_remove_procparams -
|
||||
* @hdr_len_remove: Specifies how much (in bytes) of the header needs
|
||||
* to be removed
|
||||
* @outer_ip_version: Specifies if template header's outer IP is IPV4(0) or IPV6(1)
|
||||
* @is_mpls: Specifies if ucp cmd is for legacy EoGRE(0) or MPLSoGRE(1)
|
||||
* @tag_add_len: Specifies amount to be added for the tags
|
||||
*/
|
||||
struct ipa_gre_header_remove_procparams {
|
||||
uint32_t hdr_len_remove :8; /* 44 bytes for IPV6, 24 for IPV4 */
|
||||
uint32_t outer_ip_version :1;
|
||||
uint32_t is_mpls :1;
|
||||
uint32_t tag_add_len :4;
|
||||
uint32_t reserved :18;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ipa_gre_hdr_proc_ctx_params -
|
||||
* @hdr_add_param: parameters for header add
|
||||
* @hdr_remove_param: parameters for header remove
|
||||
*/
|
||||
struct ipa_gre_hdr_proc_ctx_params {
|
||||
struct ipa_gre_header_add_procparams hdr_add_param;
|
||||
struct ipa_gre_header_remove_procparams hdr_remove_param;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ipa_eth_II_to_eth_II_ex_procparams -
|
||||
* @input_ethhdr_negative_offset: Specifies where the ethernet hdr offset is
|
||||
* (in bytes) from the start of the input IP hdr
|
||||
* @output_ethhdr_negative_offset: Specifies where the ethernet hdr offset is
|
||||
* (in bytes) from the end of the template hdr
|
||||
* @output_dscp_pcp_update: Specifies if VLAN PCP needs to be updated based on
|
||||
* DSCP<->PCP mapping table.
|
||||
* @reserved: for future use
|
||||
*/
|
||||
struct ipa_eth_II_to_eth_II_ex_procparams {
|
||||
uint32_t input_ethhdr_negative_offset : 8;
|
||||
uint32_t output_ethhdr_negative_offset : 8;
|
||||
uint32_t reserved : 16;
|
||||
uint32_t output_dscp_pcp_update : 1;
|
||||
uint32_t reserved : 15;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ipa_wwan_to_eth_II_ex_procparams -
|
||||
* @input_ethhdr_negative_offset: Specifies where the ethernet hdr offset is
|
||||
* (in bytes) from the start of the input IP hdr
|
||||
* @output_ethhdr_negative_offset: Specifies where the ethernet hdr offset is
|
||||
* (in bytes) from the end of the template hdr
|
||||
* @output_dscp_pcp_update: Specifies if VLAN PCP needs to be updated based on
|
||||
* DSCP<->PCP mapping table.
|
||||
* @input_ethhdr_valid: Specifies whether input ethernet header is valid or not.
|
||||
* @reserved: for future use
|
||||
*/
|
||||
struct ipa_wwan_to_eth_II_ex_procparams {
|
||||
uint32_t input_ethhdr_negative_offset : 8;
|
||||
uint32_t output_ethhdr_negative_offset : 8;
|
||||
uint32_t output_dscp_pcp_update : 1;
|
||||
uint32_t input_ethhdr_valid : 1;
|
||||
uint32_t reserved : 14;
|
||||
};
|
||||
|
||||
#define L2TP_USER_SPACE_SPECIFY_DST_PIPE
|
||||
|
|
@ -1881,6 +1961,7 @@ struct ipa_eth_II_to_eth_II_ex_procparams {
|
|||
* @l2tp_params: l2tp parameters
|
||||
* @eogre_params: eogre parameters
|
||||
* @generic_params: generic proc_ctx params
|
||||
* @generic_params_v2: generic proc_ctx params for bridging
|
||||
* @proc_ctx_hdl: out parameter, handle to proc_ctx, valid when status is 0
|
||||
* @status: out parameter, status of header add operation,
|
||||
* 0 for success,
|
||||
|
|
@ -1894,6 +1975,8 @@ struct ipa_hdr_proc_ctx_add {
|
|||
struct ipa_l2tp_hdr_proc_ctx_params l2tp_params;
|
||||
struct ipa_eogre_hdr_proc_ctx_params eogre_params;
|
||||
struct ipa_eth_II_to_eth_II_ex_procparams generic_params;
|
||||
struct ipa_wwan_to_eth_II_ex_procparams generic_params_v2;
|
||||
struct ipa_gre_hdr_proc_ctx_params gre_params;
|
||||
};
|
||||
|
||||
#define IPA_L2TP_HDR_PROC_SUPPORT
|
||||
|
|
@ -3654,6 +3737,18 @@ struct ipa_ioc_ext_router_info {
|
|||
uint32_t idu_client_prefix[IPA_PREFIX_MAPPING_MAX][4];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ipa_ioc_dscp_pcp_map_info - provide dscp pcp mapping info to add/delete
|
||||
* @add: Boolean to indicate add or delete the mapping
|
||||
* @dscp_pcp_map: DSCP <6 bits> and PCP <3 bits>.
|
||||
* Only 3 bits are valid(0-7) for PCP.
|
||||
* DSCP is used as index (0-63).
|
||||
*/
|
||||
struct ipa_ioc_dscp_pcp_map_info {
|
||||
uint32_t add;
|
||||
uint8_t dscp_pcp_map[IPA_UC_MAX_DSCP_VAL];
|
||||
};
|
||||
|
||||
/**
|
||||
* actual IOCTLs supported by IPA driver
|
||||
*/
|
||||
|
|
@ -3975,6 +4070,9 @@ struct ipa_ioc_ext_router_info {
|
|||
IPA_IOCTL_SET_EXT_ROUTER_MODE, \
|
||||
struct ipa_ioc_ext_router_info)
|
||||
|
||||
#define IPA_IOC_ADD_DEL_DSCP_PCP_MAPPING _IOWR(IPA_IOC_MAGIC, \
|
||||
IPA_IOCTL_ADD_DEL_DSCP_PCP_MAPPING, \
|
||||
struct ipa_ioc_dscp_pcp_map_info)
|
||||
|
||||
/*
|
||||
* unique magic number of the Tethering bridge ioctls
|
||||
|
|
|
|||
|
|
@ -1960,6 +1960,7 @@ static void rmap_walk_file(struct page *page, struct rmap_walk_control *rwc,
|
|||
i_mmap_lock_read(mapping);
|
||||
}
|
||||
lookup:
|
||||
|
||||
if (rwc->target_vma) {
|
||||
address = vma_address(page, rwc->target_vma);
|
||||
rwc->rmap_one(page, rwc->target_vma, address, rwc->arg);
|
||||
|
|
|
|||
|
|
@ -148,6 +148,9 @@ static void haven_rx_peak(struct haven_pipe *pipe, void *data,
|
|||
if (tail >= pipe->length)
|
||||
tail -= pipe->length;
|
||||
|
||||
if (WARN_ON_ONCE(tail > pipe->length))
|
||||
return;
|
||||
|
||||
len = min_t(size_t, count, pipe->length - tail);
|
||||
if (len)
|
||||
memcpy_fromio(data, pipe->fifo + tail, len);
|
||||
|
|
@ -188,6 +191,9 @@ static size_t haven_tx_avail(struct haven_pipe *pipe)
|
|||
else
|
||||
avail -= FIFO_FULL_RESERVE;
|
||||
|
||||
if (WARN_ON_ONCE(avail > pipe->length))
|
||||
avail = 0;
|
||||
|
||||
return avail;
|
||||
}
|
||||
|
||||
|
|
@ -198,6 +204,8 @@ static void haven_tx_write(struct haven_pipe *pipe,
|
|||
u32 head;
|
||||
|
||||
head = le32_to_cpu(*pipe->head);
|
||||
if (WARN_ON_ONCE(head > pipe->length))
|
||||
return;
|
||||
|
||||
len = min_t(size_t, count, pipe->length - head);
|
||||
if (len)
|
||||
|
|
@ -604,7 +612,7 @@ static int qrtr_haven_probe(struct platform_device *pdev)
|
|||
INIT_WORK(&qdev->work, qrtr_haven_retry_work);
|
||||
|
||||
qdev->ep.xmit = qrtr_haven_send;
|
||||
ret = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NET_ID_AUTO, false);
|
||||
ret = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NET_ID_AUTO, false, NULL);
|
||||
if (ret)
|
||||
goto register_fail;
|
||||
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
|
|||
|
||||
dev_set_drvdata(&mhi_dev->dev, qdev);
|
||||
|
||||
rc = qrtr_endpoint_register(&qdev->ep, net_id, rt);
|
||||
rc = qrtr_endpoint_register(&qdev->ep, net_id, rt, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ static void qrtr_mhi_dev_state_cb(struct mhi_dev_client_cb_data *cb_data)
|
|||
return;
|
||||
}
|
||||
|
||||
rc = qrtr_endpoint_register(&qep->ep, qep->net_id, qep->rt);
|
||||
rc = qrtr_endpoint_register(&qep->ep, qep->net_id, qep->rt, NULL);
|
||||
if (rc) {
|
||||
dev_err(qep->dev, "register failed %d\n", rc);
|
||||
qrtr_mhi_dev_close_channels(qep);
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ static DEFINE_SPINLOCK(qrtr_port_lock);
|
|||
#define QRTR_BACKUP_HI_SIZE SZ_16K
|
||||
#define QRTR_BACKUP_LO_NUM 20
|
||||
#define QRTR_BACKUP_LO_SIZE SZ_1K
|
||||
|
||||
static struct sk_buff_head qrtr_backup_lo;
|
||||
static struct sk_buff_head qrtr_backup_hi;
|
||||
static struct work_struct qrtr_backup_work;
|
||||
|
|
@ -190,6 +191,8 @@ struct qrtr_node {
|
|||
|
||||
struct wakeup_source *ws;
|
||||
void *ilc;
|
||||
|
||||
u32 nonwake_svc[MAX_NON_WAKE_SVC_LEN];
|
||||
};
|
||||
|
||||
struct qrtr_tx_flow_waiter {
|
||||
|
|
@ -838,7 +841,9 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
|
|||
size_t size;
|
||||
unsigned int ver;
|
||||
size_t hdrlen;
|
||||
int errcode;
|
||||
int errcode, i;
|
||||
bool wake = true;
|
||||
int svc_id;
|
||||
|
||||
if (len == 0 || len & 3)
|
||||
return -EINVAL;
|
||||
|
|
@ -938,9 +943,22 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
|
|||
goto err;
|
||||
|
||||
/* Force wakeup for all packets except for sensors */
|
||||
if (node->nid != 9)
|
||||
if (node->nid != 9 && node->nid != 5)
|
||||
pm_wakeup_ws_event(node->ws, qrtr_wakeup_ms, true);
|
||||
|
||||
if (node->nid == 5) {
|
||||
svc_id = qrtr_get_service_id(cb->src_node, cb->src_port);
|
||||
if (svc_id > 0) {
|
||||
for (i = 0; i < MAX_NON_WAKE_SVC_LEN; i++) {
|
||||
if (svc_id == node->nonwake_svc[i]) {
|
||||
wake = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wake)
|
||||
pm_wakeup_ws_event(node->ws, qrtr_wakeup_ms, true);
|
||||
}
|
||||
qrtr_port_put(ipc);
|
||||
}
|
||||
|
||||
|
|
@ -1149,7 +1167,7 @@ static void qrtr_hello_work(struct kthread_work *work)
|
|||
* The specified endpoint must have the xmit function pointer set on call.
|
||||
*/
|
||||
int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id,
|
||||
bool rt)
|
||||
bool rt, u32 *svc_arr)
|
||||
{
|
||||
struct qrtr_node *node;
|
||||
struct sched_param param = {.sched_priority = 1};
|
||||
|
|
@ -1180,6 +1198,9 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id,
|
|||
if (rt)
|
||||
sched_setscheduler(node->task, SCHED_FIFO, ¶m);
|
||||
|
||||
if (svc_arr)
|
||||
memcpy(node->nonwake_svc, svc_arr, MAX_NON_WAKE_SVC_LEN * sizeof(int));
|
||||
|
||||
mutex_init(&node->qrtr_tx_lock);
|
||||
INIT_RADIX_TREE(&node->qrtr_tx_flow, GFP_KERNEL);
|
||||
init_waitqueue_head(&node->resume_tx);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ struct sk_buff;
|
|||
|
||||
#define QRTR_DEL_PROC_MAGIC 0xe111
|
||||
|
||||
#define MAX_NON_WAKE_SVC_LEN 5
|
||||
|
||||
/**
|
||||
* struct qrtr_endpoint - endpoint handle
|
||||
* @xmit: Callback for outgoing packets
|
||||
|
|
@ -27,7 +29,7 @@ struct qrtr_endpoint {
|
|||
};
|
||||
|
||||
int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id,
|
||||
bool rt);
|
||||
bool rt, u32 *svc_arr);
|
||||
|
||||
void qrtr_endpoint_unregister(struct qrtr_endpoint *ep);
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,8 @@ static int qcom_smd_qrtr_probe(struct rpmsg_device *rpdev)
|
|||
struct qrtr_smd_dev *qdev;
|
||||
u32 net_id;
|
||||
bool rt;
|
||||
int rc;
|
||||
int rc, size;
|
||||
u32 *svc_arr = NULL;
|
||||
pr_info("%s:Entered\n", __func__);
|
||||
|
||||
qdev = devm_kzalloc(&rpdev->dev, sizeof(*qdev), GFP_KERNEL);
|
||||
|
|
@ -81,7 +82,18 @@ static int qcom_smd_qrtr_probe(struct rpmsg_device *rpdev)
|
|||
|
||||
rt = of_property_read_bool(rpdev->dev.of_node, "qcom,low-latency");
|
||||
|
||||
rc = qrtr_endpoint_register(&qdev->ep, net_id, rt);
|
||||
size = of_property_count_u32_elems(rpdev->dev.of_node, "qcom,non-wake-svc");
|
||||
|
||||
if (size > 0) {
|
||||
if (size > MAX_NON_WAKE_SVC_LEN)
|
||||
size = MAX_NON_WAKE_SVC_LEN;
|
||||
svc_arr = kmalloc_array(size, sizeof(u32), GFP_KERNEL);
|
||||
|
||||
of_property_read_u32_array(rpdev->dev.of_node, "qcom,non-wake-svc",
|
||||
svc_arr, size);
|
||||
}
|
||||
rc = qrtr_endpoint_register(&qdev->ep, net_id, rt, svc_arr);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue