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:
Michael Bestas 2023-03-19 17:05:30 +02:00
commit d5a4546147
No known key found for this signature in database
GPG key ID: CC95044519BE6669
42 changed files with 3951 additions and 4345 deletions

View file

@ -1 +1 @@
LTS_5.4.210_7e6cbbe7e59a
LTS_5.4.226_d72fdcc7094f

View file

@ -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

View file

@ -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) {

View file

@ -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)

View file

@ -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);

View file

@ -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(&current->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(&current->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(&current->mm->mmap_sem);
return -EBADF;
}
}
}
if (!dmabuf) {

View file

@ -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);

View file

@ -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,

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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");

View file

@ -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;

View file

@ -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");
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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 {

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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)

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;
};
/**

View file

@ -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;
};
/**

View file

@ -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.

View file

@ -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 */

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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, &param);
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);

View file

@ -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);

View file

@ -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;