mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 12:25:00 -04:00
Merge 02194073f2 on remote branch
Change-Id: Ife68585f7979d8a9db574c95d5c1db7c765e1967
This commit is contained in:
commit
07b7842e81
19 changed files with 375 additions and 216 deletions
1
arch/arm/configs/vendor/sdxlemur.config
vendored
1
arch/arm/configs/vendor/sdxlemur.config
vendored
|
|
@ -347,6 +347,7 @@ CONFIG_SERIAL_MSM=y
|
|||
CONFIG_QCOM_EUD=y
|
||||
CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE=y
|
||||
CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE_DEFAULT=y
|
||||
CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE_NODUMP=y
|
||||
CONFIG_POWER_RESET_QCOM_REBOOT_REASON=y
|
||||
CONFIG_POWER_RESET_MSM=y
|
||||
CONFIG_QCOM_MINIDUMP=y
|
||||
|
|
|
|||
|
|
@ -207,6 +207,25 @@ void qcom_scm_set_download_mode(enum qcom_download_mode mode,
|
|||
}
|
||||
EXPORT_SYMBOL(qcom_scm_set_download_mode);
|
||||
|
||||
int qcom_scm_get_download_mode(unsigned int *mode, phys_addr_t tcsr_boot_misc)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct device *dev = __scm ? __scm->dev : NULL;
|
||||
|
||||
if (tcsr_boot_misc || (__scm && __scm->dload_mode_addr)) {
|
||||
ret = qcom_scm_io_readl(tcsr_boot_misc ? : __scm->dload_mode_addr, mode);
|
||||
} else {
|
||||
dev_err(dev,
|
||||
"No available mechanism for getting download mode\n");
|
||||
}
|
||||
|
||||
if (ret)
|
||||
dev_err(dev, "failed to get download mode: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_scm_get_download_mode);
|
||||
|
||||
int qcom_scm_config_cpu_errata(void)
|
||||
{
|
||||
return __qcom_scm_config_cpu_errata(__scm->dev);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
|
|
@ -601,8 +602,6 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev,
|
|||
if (drawctxt != NULL && kgsl_context_detached(&drawctxt->base))
|
||||
return -ENOENT;
|
||||
|
||||
trace_adreno_drawctxt_switch(rb, drawctxt);
|
||||
|
||||
/* Get a refcount to the new instance */
|
||||
if (drawctxt) {
|
||||
if (!_kgsl_context_get(&drawctxt->base))
|
||||
|
|
@ -616,7 +615,7 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev,
|
|||
|
||||
ret = adreno_iommu_set_pt_ctx(rb, new_pt, drawctxt);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err;
|
||||
|
||||
if (rb->drawctxt_active) {
|
||||
/* Wait for the timestamp to expire */
|
||||
|
|
@ -626,7 +625,12 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev,
|
|||
kgsl_context_put(&rb->drawctxt_active->base);
|
||||
}
|
||||
}
|
||||
trace_adreno_drawctxt_switch(rb, drawctxt);
|
||||
|
||||
rb->drawctxt_active = drawctxt;
|
||||
return 0;
|
||||
err:
|
||||
if (drawctxt)
|
||||
kgsl_context_put(&drawctxt->base);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022,2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
|
@ -353,63 +353,6 @@ static unsigned int __add_curr_ctxt_cmds(struct adreno_ringbuffer *rb,
|
|||
return cmds - cmds_orig;
|
||||
}
|
||||
|
||||
/**
|
||||
* _set_ctxt_gpu() - Add commands to set the current context in memstore
|
||||
* @rb: The ringbuffer in which commands to set memstore are added
|
||||
* @drawctxt: The context whose id is being set in memstore
|
||||
*/
|
||||
static int _set_ctxt_gpu(struct adreno_ringbuffer *rb,
|
||||
struct adreno_context *drawctxt)
|
||||
{
|
||||
unsigned int link[15], *cmds;
|
||||
int result;
|
||||
|
||||
cmds = &link[0];
|
||||
cmds += __add_curr_ctxt_cmds(rb, cmds, drawctxt);
|
||||
result = adreno_ringbuffer_issue_internal_cmds(rb, 0, link,
|
||||
(unsigned int)(cmds - link));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* _set_pagetable_gpu() - Use GPU to switch the pagetable
|
||||
* @rb: The rb in which commands to switch pagetable are to be
|
||||
* submitted
|
||||
* @new_pt: The pagetable to switch to
|
||||
*/
|
||||
static int _set_pagetable_gpu(struct adreno_ringbuffer *rb,
|
||||
struct kgsl_pagetable *new_pt)
|
||||
{
|
||||
struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb);
|
||||
unsigned int *link = NULL, count;
|
||||
int result;
|
||||
|
||||
link = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (link == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* If we are in a fault the MMU will be reset soon */
|
||||
if (test_bit(ADRENO_DEVICE_FAULT, &adreno_dev->priv)) {
|
||||
kfree(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
count = adreno_iommu_set_pt_generate_cmds(rb, link, new_pt);
|
||||
|
||||
WARN(count > (PAGE_SIZE / sizeof(unsigned int)),
|
||||
"Temp command buffer overflow\n");
|
||||
|
||||
/*
|
||||
* This returns the per context timestamp but we need to
|
||||
* use the global timestamp for iommu clock disablement
|
||||
*/
|
||||
result = adreno_ringbuffer_issue_internal_cmds(rb,
|
||||
KGSL_CMD_FLAGS_PMODE, link, count);
|
||||
|
||||
kfree(link);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* adreno_iommu_init() - Adreno iommu init
|
||||
* @adreno_dev: Adreno device
|
||||
|
|
@ -443,7 +386,6 @@ void adreno_iommu_init(struct adreno_device *adreno_dev)
|
|||
|
||||
/**
|
||||
* adreno_iommu_set_pt_ctx() - Change the pagetable of the current RB
|
||||
* @device: Pointer to device to which the rb belongs
|
||||
* @rb: The RB pointer on which pagetable is to be changed
|
||||
* @new_pt: The new pt the device will change to
|
||||
* @drawctxt: The context whose pagetable the ringbuffer is switching to,
|
||||
|
|
@ -458,21 +400,34 @@ int adreno_iommu_set_pt_ctx(struct adreno_ringbuffer *rb,
|
|||
struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb);
|
||||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||
struct kgsl_pagetable *cur_pt = device->mmu.defaultpagetable;
|
||||
unsigned int *cmds = NULL, count = 0;
|
||||
int result = 0;
|
||||
|
||||
cmds = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (cmds == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Switch the page table if a MMU is attached */
|
||||
if (kgsl_mmu_get_mmutype(device) != KGSL_MMU_TYPE_NONE) {
|
||||
if (rb->drawctxt_active)
|
||||
cur_pt = rb->drawctxt_active->base.proc_priv->pagetable;
|
||||
|
||||
/* Pagetable switch */
|
||||
/* Add commands for pagetable switch */
|
||||
if (new_pt != cur_pt)
|
||||
result = _set_pagetable_gpu(rb, new_pt);
|
||||
count += adreno_iommu_set_pt_generate_cmds(rb, cmds, new_pt);
|
||||
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Context switch */
|
||||
return _set_ctxt_gpu(rb, drawctxt);
|
||||
/* Add commands to set the current context in memstore */
|
||||
count += __add_curr_ctxt_cmds(rb, cmds + count, drawctxt);
|
||||
|
||||
WARN(count > (PAGE_SIZE / sizeof(unsigned int)),
|
||||
"Temp command buffer overflow\n");
|
||||
|
||||
result = adreno_ringbuffer_issue_internal_cmds(rb, KGSL_CMD_FLAGS_PMODE,
|
||||
cmds, count);
|
||||
|
||||
kfree(cmds);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2334,6 +2334,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s);
|
|||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s);
|
||||
|
||||
/*
|
||||
* QPS615 PCIe-PCI bridge devices cause AER timeout errors on the upstream
|
||||
* PCIe root port when L0s is enabled in CPE platform with SDX65.
|
||||
* Disable L0s for both QPS615 and SDX65 when QPS615 switch is
|
||||
* present.
|
||||
*/
|
||||
static void quirk_disable_aspm_qps615_l0s(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dev *p;
|
||||
|
||||
pci_disable_link_state(dev, PCIE_LINK_STATE_L0S);
|
||||
p = pci_get_device(PCI_VENDOR_ID_QCOM, 0x0308, NULL);
|
||||
pci_disable_link_state(p, PCIE_LINK_STATE_L0S);
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TOSHIBA, 0x0623, quirk_disable_aspm_qps615_l0s);
|
||||
|
||||
static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
|
||||
{
|
||||
pci_info(dev, "Disabling ASPM L0s/L1\n");
|
||||
|
|
|
|||
|
|
@ -132,6 +132,16 @@ config POWER_RESET_QCOM_DOWNLOAD_MODE_DEFAULT
|
|||
|
||||
Say Y here to enable "download mode" by default.
|
||||
|
||||
config POWER_RESET_QCOM_DOWNLOAD_MODE_NODUMP
|
||||
bool "MSM download mode as nodump"
|
||||
depends on POWER_RESET_QCOM_DOWNLOAD_MODE
|
||||
help
|
||||
Support MSM boards to be able to set nodump as download mode,
|
||||
when unexpected warm-restart is called, so that device will
|
||||
not go into ramdump path.
|
||||
|
||||
Say N if not sure.
|
||||
|
||||
config POWER_RESET_QCOM_PON
|
||||
tristate "Qualcomm power-on driver"
|
||||
depends on ARCH_QCOM
|
||||
|
|
|
|||
|
|
@ -203,6 +203,11 @@ static ssize_t dload_mode_show(struct kobject *kobj,
|
|||
case QCOM_DOWNLOAD_BOTHDUMP:
|
||||
mode = "both";
|
||||
break;
|
||||
#ifdef CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE_NODUMP
|
||||
case QCOM_DOWNLOAD_NODUMP:
|
||||
mode = "nodump";
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
mode = "unknown";
|
||||
break;
|
||||
|
|
@ -214,6 +219,17 @@ static ssize_t dload_mode_store(struct kobject *kobj,
|
|||
const char *buf, size_t count)
|
||||
{
|
||||
enum qcom_download_mode mode;
|
||||
#ifdef CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE_NODUMP
|
||||
int temp;
|
||||
|
||||
dump_mode = qcom_scm_get_download_mode(&temp, 0) ? dump_mode : temp;
|
||||
|
||||
if (dump_mode == QCOM_DOWNLOAD_NODUMP) {
|
||||
pr_err("%s: Current dump mode already set: nodump\n", __func__);
|
||||
pr_err("%s: Changing dump mode now is not allowed, reboot the device\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sysfs_streq(buf, "full"))
|
||||
mode = QCOM_DOWNLOAD_FULLDUMP;
|
||||
|
|
@ -221,9 +237,19 @@ static ssize_t dload_mode_store(struct kobject *kobj,
|
|||
mode = QCOM_DOWNLOAD_MINIDUMP;
|
||||
else if (sysfs_streq(buf, "both"))
|
||||
mode = QCOM_DOWNLOAD_BOTHDUMP;
|
||||
#ifdef CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE_NODUMP
|
||||
else if (sysfs_streq(buf, "nodump")) {
|
||||
mode = QCOM_DOWNLOAD_NODUMP;
|
||||
qcom_scm_disable_sdi();
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
pr_err("Invalid dump mode request...\n");
|
||||
#ifdef CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE_NODUMP
|
||||
pr_err("Supported dumps: 'full', 'mini', 'both' or 'nodump'\n");
|
||||
#else
|
||||
pr_err("Supported dumps: 'full', 'mini', or 'both'\n");
|
||||
#endif
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, Linaro Ltd
|
||||
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/idr.h>
|
||||
|
|
@ -354,6 +355,38 @@ static void qcom_glink_channel_release(struct kref *ref)
|
|||
kfree(channel);
|
||||
}
|
||||
|
||||
static struct glink_channel *qcom_glink_channel_ref_get(
|
||||
struct qcom_glink *glink,
|
||||
bool remote_channel, int cid)
|
||||
{
|
||||
struct glink_channel *channel = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
if (!glink)
|
||||
return NULL;
|
||||
|
||||
spin_lock_irqsave(&glink->idr_lock, flags);
|
||||
if (remote_channel)
|
||||
channel = idr_find(&glink->rcids, cid);
|
||||
else
|
||||
channel = idr_find(&glink->lcids, cid);
|
||||
|
||||
if (channel)
|
||||
kref_get(&channel->refcount);
|
||||
|
||||
spin_unlock_irqrestore(&glink->idr_lock, flags);
|
||||
return channel;
|
||||
}
|
||||
|
||||
static void qcom_glink_channel_ref_put(struct glink_channel *channel)
|
||||
{
|
||||
|
||||
if (!channel)
|
||||
return;
|
||||
|
||||
kref_put(&channel->refcount, qcom_glink_channel_release);
|
||||
}
|
||||
|
||||
static size_t qcom_glink_rx_avail(struct qcom_glink *glink)
|
||||
{
|
||||
return glink->rx_pipe->avail(glink->rx_pipe);
|
||||
|
|
@ -505,11 +538,8 @@ static void qcom_glink_handle_intent_req_ack(struct qcom_glink *glink,
|
|||
unsigned int cid, bool granted)
|
||||
{
|
||||
struct glink_channel *channel;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&glink->idr_lock, flags);
|
||||
channel = idr_find(&glink->rcids, cid);
|
||||
spin_unlock_irqrestore(&glink->idr_lock, flags);
|
||||
channel = qcom_glink_channel_ref_get(glink, true, cid);
|
||||
if (!channel) {
|
||||
dev_err(glink->dev, "unable to find channel\n");
|
||||
return;
|
||||
|
|
@ -519,6 +549,7 @@ static void qcom_glink_handle_intent_req_ack(struct qcom_glink *glink,
|
|||
atomic_inc(&channel->intent_req_acked);
|
||||
wake_up(&channel->intent_req_ack);
|
||||
CH_INFO(channel, "\n");
|
||||
qcom_glink_channel_ref_put(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -867,9 +898,7 @@ static void qcom_glink_handle_rx_done(struct qcom_glink *glink,
|
|||
struct glink_channel *channel;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&glink->idr_lock, flags);
|
||||
channel = idr_find(&glink->rcids, cid);
|
||||
spin_unlock_irqrestore(&glink->idr_lock, flags);
|
||||
channel = qcom_glink_channel_ref_get(glink, true, cid);
|
||||
if (!channel) {
|
||||
dev_err(glink->dev, "invalid channel id received\n");
|
||||
return;
|
||||
|
|
@ -881,6 +910,7 @@ static void qcom_glink_handle_rx_done(struct qcom_glink *glink,
|
|||
if (!intent) {
|
||||
spin_unlock_irqrestore(&channel->intent_lock, flags);
|
||||
dev_err(glink->dev, "invalid intent id received\n");
|
||||
qcom_glink_channel_ref_put(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -892,6 +922,7 @@ static void qcom_glink_handle_rx_done(struct qcom_glink *glink,
|
|||
kfree(intent);
|
||||
}
|
||||
spin_unlock_irqrestore(&channel->intent_lock, flags);
|
||||
qcom_glink_channel_ref_put(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -914,9 +945,7 @@ static void qcom_glink_handle_intent_req(struct qcom_glink *glink,
|
|||
unsigned long flags;
|
||||
int iid;
|
||||
|
||||
spin_lock_irqsave(&glink->idr_lock, flags);
|
||||
channel = idr_find(&glink->rcids, cid);
|
||||
spin_unlock_irqrestore(&glink->idr_lock, flags);
|
||||
channel = qcom_glink_channel_ref_get(glink, true, cid);
|
||||
|
||||
if (!channel) {
|
||||
pr_err("%s channel not found for cid %d\n", __func__, cid);
|
||||
|
|
@ -933,6 +962,7 @@ static void qcom_glink_handle_intent_req(struct qcom_glink *glink,
|
|||
spin_unlock_irqrestore(&channel->intent_lock, flags);
|
||||
if (intent) {
|
||||
qcom_glink_send_intent_req_ack(glink, channel, !!intent);
|
||||
qcom_glink_channel_ref_put(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -942,6 +972,7 @@ static void qcom_glink_handle_intent_req(struct qcom_glink *glink,
|
|||
qcom_glink_advertise_intent(glink, channel, intent);
|
||||
|
||||
qcom_glink_send_intent_req_ack(glink, channel, !!intent);
|
||||
qcom_glink_channel_ref_put(channel);
|
||||
}
|
||||
|
||||
static int qcom_glink_rx_defer(struct qcom_glink *glink, size_t extra)
|
||||
|
|
@ -976,7 +1007,7 @@ static int qcom_glink_rx_defer(struct qcom_glink *glink, size_t extra)
|
|||
static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
|
||||
{
|
||||
struct glink_core_rx_intent *intent;
|
||||
struct glink_channel *channel;
|
||||
struct glink_channel *channel = NULL;
|
||||
struct {
|
||||
struct glink_msg msg;
|
||||
__le32 chunk_size;
|
||||
|
|
@ -1004,9 +1035,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
|
|||
}
|
||||
|
||||
rcid = le16_to_cpu(hdr.msg.param1);
|
||||
spin_lock_irqsave(&glink->idr_lock, flags);
|
||||
channel = idr_find(&glink->rcids, rcid);
|
||||
spin_unlock_irqrestore(&glink->idr_lock, flags);
|
||||
channel = qcom_glink_channel_ref_get(glink, true, rcid);
|
||||
if (!channel) {
|
||||
dev_dbg(glink->dev, "Data on non-existing channel\n");
|
||||
|
||||
|
|
@ -1019,13 +1048,16 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
|
|||
/* Might have an ongoing, fragmented, message to append */
|
||||
if (!channel->buf) {
|
||||
intent = kzalloc(sizeof(*intent), GFP_ATOMIC);
|
||||
if (!intent)
|
||||
if (!intent) {
|
||||
qcom_glink_channel_ref_put(channel);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
intent->data = kmalloc(chunk_size + left_size,
|
||||
GFP_ATOMIC);
|
||||
if (!intent->data) {
|
||||
kfree(intent);
|
||||
qcom_glink_channel_ref_put(channel);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
@ -1092,7 +1124,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
|
|||
|
||||
advance_rx:
|
||||
qcom_glink_rx_advance(glink, ALIGN(sizeof(hdr) + chunk_size, 8));
|
||||
|
||||
qcom_glink_channel_ref_put(channel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1123,9 +1155,7 @@ static void qcom_glink_handle_intent(struct qcom_glink *glink,
|
|||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&glink->idr_lock, flags);
|
||||
channel = idr_find(&glink->rcids, cid);
|
||||
spin_unlock_irqrestore(&glink->idr_lock, flags);
|
||||
channel = qcom_glink_channel_ref_get(glink, true, cid);
|
||||
if (!channel) {
|
||||
dev_err(glink->dev, "intents for non-existing channel\n");
|
||||
qcom_glink_rx_advance(glink, ALIGN(msglen, 8));
|
||||
|
|
@ -1133,8 +1163,10 @@ static void qcom_glink_handle_intent(struct qcom_glink *glink,
|
|||
}
|
||||
|
||||
msg = kmalloc(msglen, GFP_ATOMIC);
|
||||
if (!msg)
|
||||
if (!msg) {
|
||||
qcom_glink_channel_ref_put(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
qcom_glink_rx_peak(glink, msg, 0, msglen);
|
||||
|
||||
|
|
@ -1163,15 +1195,14 @@ static void qcom_glink_handle_intent(struct qcom_glink *glink,
|
|||
|
||||
kfree(msg);
|
||||
qcom_glink_rx_advance(glink, ALIGN(msglen, 8));
|
||||
qcom_glink_channel_ref_put(channel);
|
||||
}
|
||||
|
||||
static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)
|
||||
{
|
||||
struct glink_channel *channel;
|
||||
|
||||
spin_lock(&glink->idr_lock);
|
||||
channel = idr_find(&glink->lcids, lcid);
|
||||
spin_unlock(&glink->idr_lock);
|
||||
channel = qcom_glink_channel_ref_get(glink, false, lcid);
|
||||
if (!channel) {
|
||||
dev_err(glink->dev, "Invalid open ack packet\n");
|
||||
return -EINVAL;
|
||||
|
|
@ -1179,7 +1210,7 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)
|
|||
|
||||
CH_INFO(channel, "\n");
|
||||
complete_all(&channel->open_ack);
|
||||
|
||||
qcom_glink_channel_ref_put(channel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1220,12 +1251,9 @@ static int qcom_glink_handle_signals(struct qcom_glink *glink,
|
|||
unsigned int rcid, unsigned int signals)
|
||||
{
|
||||
struct glink_channel *channel;
|
||||
unsigned long flags;
|
||||
u32 old;
|
||||
|
||||
spin_lock_irqsave(&glink->idr_lock, flags);
|
||||
channel = idr_find(&glink->rcids, rcid);
|
||||
spin_unlock_irqrestore(&glink->idr_lock, flags);
|
||||
channel = qcom_glink_channel_ref_get(glink, true, rcid);
|
||||
if (!channel) {
|
||||
dev_err(glink->dev, "signal for non-existing channel\n");
|
||||
return -EINVAL;
|
||||
|
|
@ -1252,6 +1280,7 @@ static int qcom_glink_handle_signals(struct qcom_glink *glink,
|
|||
old, channel->rsigs);
|
||||
}
|
||||
|
||||
qcom_glink_channel_ref_put(channel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -92,10 +92,16 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len)
|
|||
size_t ehdr_size;
|
||||
void *data;
|
||||
|
||||
if (fw->size < sizeof(struct elf32_hdr)) {
|
||||
dev_err(dev, "Image is too small\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
ehdr = (struct elf32_hdr *)fw->data;
|
||||
phdrs = (struct elf32_phdr *)(ehdr + 1);
|
||||
|
||||
if (ehdr->e_phnum < 2 || ehdr->e_phnum > PN_XNUM)
|
||||
if (ehdr->e_phnum < 2 || ehdr->e_phoff > fw->size ||
|
||||
(sizeof(phdrs) * ehdr->e_phnum > fw->size - ehdr->e_phoff))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (phdrs[0].p_type == PT_LOAD)
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state)
|
|||
* Wait until device controller is ready. Only applies to 1.94a and
|
||||
* later RTL.
|
||||
*/
|
||||
if (dwc->revision >= DWC3_REVISION_194A) {
|
||||
if (dwc3_is_usb3(dwc) && dwc->revision >= DWC3_REVISION_194A) {
|
||||
while (--retries) {
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
|
||||
if (reg & DWC3_DSTS_DCNRD)
|
||||
|
|
@ -124,7 +124,7 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state)
|
|||
* The following code is racy when called from dwc3_gadget_wakeup,
|
||||
* and is not needed, at least on newer versions
|
||||
*/
|
||||
if (dwc->revision >= DWC3_REVISION_194A)
|
||||
if (dwc3_is_usb3(dwc) && dwc->revision >= DWC3_REVISION_194A)
|
||||
return 0;
|
||||
|
||||
/* wait for a change in DSTS */
|
||||
|
|
@ -2116,13 +2116,10 @@ static int dwc3_gadget_remote_wakeup(struct dwc3 *dwc)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* Recent versions do this automatically */
|
||||
if (dwc->revision < DWC3_REVISION_194A) {
|
||||
/* write zeroes to Link Change Request */
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
||||
reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
|
||||
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
|
||||
}
|
||||
/* write zeroes to Link Change Request */
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
||||
reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
|
||||
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
|
||||
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
enable_irq(dwc->irq);
|
||||
|
|
|
|||
|
|
@ -732,13 +732,26 @@ static int usb_cser_notify(struct f_cdev *port, u8 type, u16 value,
|
|||
static int port_notify_serial_state(struct cserial *cser)
|
||||
{
|
||||
struct f_cdev *port = cser_to_port(cser);
|
||||
int status;
|
||||
int status, ret;
|
||||
unsigned long flags;
|
||||
struct usb_composite_dev *cdev = port->port_usb.func.config->cdev;
|
||||
struct usb_function *func = &cser->func;
|
||||
struct usb_gadget *gadget;
|
||||
|
||||
if (port->is_suspended) {
|
||||
gadget = cser->func.config->cdev->gadget;
|
||||
port->pending_state_notify = true;
|
||||
pr_debug("%s: port is suspended\n", __func__);
|
||||
if (usb_cser_get_remote_wakeup_capable(func, gadget)) {
|
||||
if (gadget->speed >= USB_SPEED_SUPER && port->func_is_suspended) {
|
||||
ret = usb_func_wakeup(func);
|
||||
port->func_wakeup_pending = (ret == -EAGAIN) ? true : false;
|
||||
} else {
|
||||
ret = usb_gadget_wakeup(gadget);
|
||||
}
|
||||
} else {
|
||||
pr_debug("%s remote-wakeup not capable\n", __func__);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -619,6 +619,7 @@ static void xhci_port_set_test_mode(struct xhci_hcd *xhci,
|
|||
static int xhci_enter_test_mode(struct xhci_hcd *xhci,
|
||||
u16 test_mode, u16 wIndex, unsigned long *flags)
|
||||
{
|
||||
struct usb_hcd *usb3_hcd = xhci_get_usb3_hcd(xhci);
|
||||
int i, retval;
|
||||
|
||||
/* Disable all Device Slots */
|
||||
|
|
@ -639,7 +640,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci,
|
|||
xhci_dbg(xhci, "Disable all port (PP = 0)\n");
|
||||
/* Power off USB3 ports*/
|
||||
for (i = 0; i < xhci->usb3_rhub.num_ports; i++)
|
||||
xhci_set_port_power(xhci, xhci->shared_hcd, i, false, flags);
|
||||
xhci_set_port_power(xhci, usb3_hcd, i, false, flags);
|
||||
/* Power off USB2 ports*/
|
||||
for (i = 0; i < xhci->usb2_rhub.num_ports; i++)
|
||||
xhci_set_port_power(xhci, xhci->main_hcd, i, false, flags);
|
||||
|
|
@ -1743,7 +1744,8 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
|
|||
status = 1;
|
||||
}
|
||||
if (!status && !reset_change) {
|
||||
xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
|
||||
xhci_dbg(xhci, "%s: stopping usb%d port polling\n",
|
||||
__func__, hcd->self.busnum);
|
||||
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
|
|
@ -1775,7 +1777,8 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
|
|||
if (bus_state->resuming_ports || /* USB2 */
|
||||
bus_state->port_remote_wakeup) { /* USB3 */
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
xhci_dbg(xhci, "suspend failed because a port is resuming\n");
|
||||
xhci_dbg(xhci, "usb%d bus suspend to fail because a port is resuming\n",
|
||||
hcd->self.busnum);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1086,7 +1086,7 @@ static u32 xhci_find_real_port_number(struct xhci_hcd *xhci,
|
|||
struct usb_hcd *hcd;
|
||||
|
||||
if (udev->speed >= USB_SPEED_SUPER)
|
||||
hcd = xhci->shared_hcd;
|
||||
hcd = xhci_get_usb3_hcd(xhci);
|
||||
else
|
||||
hcd = xhci->main_hcd;
|
||||
|
||||
|
|
@ -2494,10 +2494,11 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
|
|||
xhci->usb2_rhub.num_ports = USB_MAXCHILDREN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note we could have all USB 3.0 ports, or all USB 2.0 ports.
|
||||
* Not sure how the USB core will handle a hub with no ports...
|
||||
*/
|
||||
if (!xhci->usb2_rhub.num_ports)
|
||||
xhci_info(xhci, "USB2 root hub has no ports\n");
|
||||
|
||||
if (!xhci->usb3_rhub.num_ports)
|
||||
xhci_info(xhci, "USB3 root hub has no ports\n");
|
||||
|
||||
xhci_create_rhub_port_array(xhci, &xhci->usb2_rhub, flags);
|
||||
xhci_create_rhub_port_array(xhci, &xhci->usb3_rhub, flags);
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
|
|||
struct device *sysdev, *tmpdev;
|
||||
struct xhci_hcd *xhci;
|
||||
struct resource *res;
|
||||
struct usb_hcd *hcd;
|
||||
struct usb_hcd *hcd, *usb3_hcd;
|
||||
int ret;
|
||||
int irq;
|
||||
struct xhci_plat_priv *priv = NULL;
|
||||
|
|
@ -246,6 +246,8 @@ static int xhci_plat_probe(struct platform_device *pdev)
|
|||
|
||||
xhci = hcd_to_xhci(hcd);
|
||||
|
||||
xhci->allow_single_roothub = 1;
|
||||
|
||||
/*
|
||||
* Not all platforms have clks so it is not an error if the
|
||||
* clock do not exist.
|
||||
|
|
@ -291,12 +293,6 @@ static int xhci_plat_probe(struct platform_device *pdev)
|
|||
device_init_wakeup(hcd->self.controller, 1);
|
||||
|
||||
xhci->main_hcd = hcd;
|
||||
xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev,
|
||||
dev_name(&pdev->dev), hcd);
|
||||
if (!xhci->shared_hcd) {
|
||||
ret = -ENOMEM;
|
||||
goto disable_clk;
|
||||
}
|
||||
|
||||
/* imod_interval is the interrupt moderation value in nanoseconds. */
|
||||
xhci->imod_interval = 40000;
|
||||
|
|
@ -321,16 +317,15 @@ static int xhci_plat_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(hcd->usb_phy)) {
|
||||
ret = PTR_ERR(hcd->usb_phy);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
goto put_usb3_hcd;
|
||||
goto disable_clk;
|
||||
hcd->usb_phy = NULL;
|
||||
} else {
|
||||
ret = usb_phy_init(hcd->usb_phy);
|
||||
if (ret)
|
||||
goto put_usb3_hcd;
|
||||
goto disable_clk;
|
||||
}
|
||||
|
||||
hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node);
|
||||
xhci->shared_hcd->tpl_support = hcd->tpl_support;
|
||||
|
||||
if (priv) {
|
||||
ret = xhci_priv_plat_setup(hcd);
|
||||
|
|
@ -345,16 +340,31 @@ static int xhci_plat_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto disable_usb_phy;
|
||||
|
||||
if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
|
||||
xhci->shared_hcd->can_do_streams = 1;
|
||||
if (!xhci_has_one_roothub(xhci)) {
|
||||
xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev,
|
||||
dev_name(&pdev->dev), hcd);
|
||||
if (!xhci->shared_hcd) {
|
||||
ret = -ENOMEM;
|
||||
goto dealloc_usb2_hcd;
|
||||
}
|
||||
|
||||
ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
|
||||
if (ret)
|
||||
goto dealloc_usb2_hcd;
|
||||
xhci->shared_hcd->tpl_support = hcd->tpl_support;
|
||||
}
|
||||
|
||||
usb3_hcd = xhci_get_usb3_hcd(xhci);
|
||||
if (usb3_hcd && HCC_MAX_PSA(xhci->hcc_params) >= 4)
|
||||
usb3_hcd->can_do_streams = 1;
|
||||
|
||||
if (xhci->shared_hcd) {
|
||||
ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
|
||||
if (ret)
|
||||
goto put_usb3_hcd;
|
||||
}
|
||||
|
||||
device_enable_async_suspend(&pdev->dev);
|
||||
if (device_may_wakeup(sysdev)) {
|
||||
device_wakeup_enable(&xhci->shared_hcd->self.root_hub->dev);
|
||||
if (xhci->shared_hcd)
|
||||
device_wakeup_enable(&xhci->shared_hcd->self.root_hub->dev);
|
||||
device_wakeup_enable(&hcd->self.root_hub->dev);
|
||||
}
|
||||
|
||||
|
|
@ -364,15 +374,15 @@ static int xhci_plat_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
|
||||
put_usb3_hcd:
|
||||
usb_put_hcd(xhci->shared_hcd);
|
||||
|
||||
dealloc_usb2_hcd:
|
||||
usb_remove_hcd(hcd);
|
||||
|
||||
disable_usb_phy:
|
||||
usb_phy_shutdown(hcd->usb_phy);
|
||||
|
||||
put_usb3_hcd:
|
||||
usb_put_hcd(xhci->shared_hcd);
|
||||
|
||||
disable_clk:
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
|
@ -398,12 +408,17 @@ static int xhci_plat_remove(struct platform_device *dev)
|
|||
pm_runtime_get_sync(&dev->dev);
|
||||
xhci->xhc_state |= XHCI_STATE_REMOVING;
|
||||
|
||||
usb_remove_hcd(shared_hcd);
|
||||
if (shared_hcd)
|
||||
usb_remove_hcd(shared_hcd);
|
||||
|
||||
usb_phy_shutdown(hcd->usb_phy);
|
||||
|
||||
usb_remove_hcd(hcd);
|
||||
xhci->shared_hcd = NULL;
|
||||
usb_put_hcd(shared_hcd);
|
||||
|
||||
if (shared_hcd) {
|
||||
xhci->shared_hcd = NULL;
|
||||
usb_put_hcd(shared_hcd);
|
||||
}
|
||||
|
||||
clk_disable_unprepare(clk);
|
||||
clk_disable_unprepare(reg_clk);
|
||||
|
|
|
|||
|
|
@ -1808,7 +1808,8 @@ cleanup:
|
|||
* bits are still set. When an event occurs, switch over to
|
||||
* polling to avoid losing status changes.
|
||||
*/
|
||||
xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
|
||||
xhci_dbg(xhci, "%s: starting usb%d port polling.\n",
|
||||
__func__, hcd->self.busnum);
|
||||
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|
||||
spin_unlock(&xhci->lock);
|
||||
/* Pass this up to the core */
|
||||
|
|
|
|||
|
|
@ -520,6 +520,10 @@ static void compliance_mode_recovery(struct timer_list *t)
|
|||
|
||||
xhci = from_timer(xhci, t, comp_mode_recovery_timer);
|
||||
rhub = &xhci->usb3_rhub;
|
||||
hcd = rhub->hcd;
|
||||
|
||||
if (!hcd)
|
||||
return;
|
||||
|
||||
for (i = 0; i < rhub->num_ports; i++) {
|
||||
temp = readl(rhub->ports[i]->addr);
|
||||
|
|
@ -533,7 +537,6 @@ static void compliance_mode_recovery(struct timer_list *t)
|
|||
i + 1);
|
||||
xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
|
||||
"Attempting compliance mode recovery");
|
||||
hcd = xhci->shared_hcd;
|
||||
|
||||
if (hcd->state == HC_STATE_SUSPENDED)
|
||||
usb_hcd_resume_root_hub(hcd);
|
||||
|
|
@ -646,14 +649,11 @@ static int xhci_run_finished(struct xhci_hcd *xhci)
|
|||
xhci_halt(xhci);
|
||||
return -ENODEV;
|
||||
}
|
||||
xhci->shared_hcd->state = HC_STATE_RUNNING;
|
||||
xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
|
||||
|
||||
if (xhci->quirks & XHCI_NEC_HOST)
|
||||
xhci_ring_cmd_db(xhci);
|
||||
|
||||
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
|
||||
"Finished xhci_run for USB3 roothub");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -727,14 +727,19 @@ int xhci_run(struct usb_hcd *hcd)
|
|||
if (ret)
|
||||
xhci_free_command(xhci, command);
|
||||
}
|
||||
set_bit(HCD_FLAG_DEFER_RH_REGISTER, &hcd->flags);
|
||||
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
|
||||
"Finished xhci_run for USB2 roothub");
|
||||
"Finished %s for main hcd", __func__);
|
||||
|
||||
xhci_dbc_init(xhci);
|
||||
|
||||
xhci_debugfs_init(xhci);
|
||||
|
||||
if (xhci_has_one_roothub(xhci))
|
||||
return xhci_run_finished(xhci);
|
||||
|
||||
/* Defer primary roothub registration if we have 2 root hubs only */
|
||||
set_bit(HCD_FLAG_DEFER_RH_REGISTER, &hcd->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xhci_run);
|
||||
|
|
@ -1027,7 +1032,8 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
|
|||
return 0;
|
||||
|
||||
if (hcd->state != HC_STATE_SUSPENDED ||
|
||||
xhci->shared_hcd->state != HC_STATE_SUSPENDED)
|
||||
(xhci->shared_hcd &&
|
||||
xhci->shared_hcd->state != HC_STATE_SUSPENDED))
|
||||
return -EINVAL;
|
||||
|
||||
if (!HCD_HW_ACCESSIBLE(hcd))
|
||||
|
|
@ -1040,18 +1046,22 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
|
|||
xhci_dbc_suspend(xhci);
|
||||
|
||||
/* Don't poll the roothubs on bus suspend. */
|
||||
xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
|
||||
xhci_dbg(xhci, "%s: stopping usb%d port polling.\n",
|
||||
__func__, hcd->self.busnum);
|
||||
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|
||||
del_timer_sync(&hcd->rh_timer);
|
||||
clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
|
||||
del_timer_sync(&xhci->shared_hcd->rh_timer);
|
||||
if (xhci->shared_hcd) {
|
||||
clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
|
||||
del_timer_sync(&xhci->shared_hcd->rh_timer);
|
||||
}
|
||||
|
||||
if (xhci->quirks & XHCI_SUSPEND_DELAY)
|
||||
usleep_range(1000, 1500);
|
||||
|
||||
spin_lock_irq(&xhci->lock);
|
||||
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
|
||||
if (xhci->shared_hcd)
|
||||
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
|
||||
/* step 1: stop endpoint */
|
||||
/* skipped assuming that port suspend has done */
|
||||
|
||||
|
|
@ -1070,7 +1080,8 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
|
|||
* served.
|
||||
*/
|
||||
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||
set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
|
||||
if (xhci->shared_hcd)
|
||||
set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
|
||||
xhci_hc_died(xhci);
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
return -ETIMEDOUT;
|
||||
|
|
@ -1157,7 +1168,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|||
msleep(100);
|
||||
|
||||
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||
set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
|
||||
if (xhci->shared_hcd)
|
||||
set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
|
||||
|
||||
spin_lock_irq(&xhci->lock);
|
||||
|
||||
|
|
@ -1218,7 +1230,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|||
|
||||
/* Let the USB core know _both_ roothubs lost power. */
|
||||
usb_root_hub_lost_power(xhci->main_hcd->self.root_hub);
|
||||
usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub);
|
||||
if (xhci->shared_hcd)
|
||||
usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub);
|
||||
|
||||
xhci_dbg(xhci, "Stop HCD\n");
|
||||
xhci_halt(xhci);
|
||||
|
|
@ -1258,12 +1271,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|||
|
||||
xhci_dbg(xhci, "Start the primary HCD\n");
|
||||
retval = xhci_run(hcd->primary_hcd);
|
||||
if (!retval) {
|
||||
if (!retval && secondary_hcd) {
|
||||
xhci_dbg(xhci, "Start the secondary HCD\n");
|
||||
retval = xhci_run(secondary_hcd);
|
||||
}
|
||||
hcd->state = HC_STATE_SUSPENDED;
|
||||
xhci->shared_hcd->state = HC_STATE_SUSPENDED;
|
||||
if (xhci->shared_hcd)
|
||||
xhci->shared_hcd->state = HC_STATE_SUSPENDED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
@ -1301,7 +1315,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|||
}
|
||||
|
||||
if (pending_portevent) {
|
||||
usb_hcd_resume_root_hub(xhci->shared_hcd);
|
||||
if (xhci->shared_hcd)
|
||||
usb_hcd_resume_root_hub(xhci->shared_hcd);
|
||||
usb_hcd_resume_root_hub(hcd);
|
||||
}
|
||||
}
|
||||
|
|
@ -1318,9 +1333,12 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|||
usb_asmedia_modifyflowcontrol(to_pci_dev(hcd->self.controller));
|
||||
|
||||
/* Re-enable port polling. */
|
||||
xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
|
||||
set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
|
||||
usb_hcd_poll_rh_status(xhci->shared_hcd);
|
||||
xhci_dbg(xhci, "%s: starting usb%d port polling.\n",
|
||||
__func__, hcd->self.busnum);
|
||||
if (xhci->shared_hcd) {
|
||||
set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
|
||||
usb_hcd_poll_rh_status(xhci->shared_hcd);
|
||||
}
|
||||
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|
||||
usb_hcd_poll_rh_status(hcd);
|
||||
|
||||
|
|
@ -5229,6 +5247,55 @@ static int xhci_get_frame(struct usb_hcd *hcd)
|
|||
return readl(&xhci->run_regs->microframe_index) >> 3;
|
||||
}
|
||||
|
||||
static void xhci_hcd_init_usb2_data(struct xhci_hcd *xhci, struct usb_hcd *hcd)
|
||||
{
|
||||
xhci->usb2_rhub.hcd = hcd;
|
||||
hcd->speed = HCD_USB2;
|
||||
hcd->self.root_hub->speed = USB_SPEED_HIGH;
|
||||
/*
|
||||
* USB 2.0 roothub under xHCI has an integrated TT,
|
||||
* (rate matching hub) as opposed to having an OHCI/UHCI
|
||||
* companion controller.
|
||||
*/
|
||||
hcd->has_tt = 1;
|
||||
}
|
||||
|
||||
static void xhci_hcd_init_usb3_data(struct xhci_hcd *xhci, struct usb_hcd *hcd)
|
||||
{
|
||||
unsigned int minor_rev;
|
||||
|
||||
/*
|
||||
* Early xHCI 1.1 spec did not mention USB 3.1 capable hosts
|
||||
* should return 0x31 for sbrn, or that the minor revision
|
||||
* is a two digit BCD containig minor and sub-minor numbers.
|
||||
* This was later clarified in xHCI 1.2.
|
||||
*
|
||||
* Some USB 3.1 capable hosts therefore have sbrn 0x30, and
|
||||
* minor revision set to 0x1 instead of 0x10.
|
||||
*/
|
||||
if (xhci->usb3_rhub.min_rev == 0x1)
|
||||
minor_rev = 1;
|
||||
else
|
||||
minor_rev = xhci->usb3_rhub.min_rev / 0x10;
|
||||
|
||||
switch (minor_rev) {
|
||||
case 2:
|
||||
hcd->speed = HCD_USB32;
|
||||
hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;
|
||||
hcd->self.root_hub->rx_lanes = 2;
|
||||
hcd->self.root_hub->tx_lanes = 2;
|
||||
break;
|
||||
case 1:
|
||||
hcd->speed = HCD_USB31;
|
||||
hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;
|
||||
break;
|
||||
}
|
||||
xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n",
|
||||
minor_rev, minor_rev ? "Enhanced " : "");
|
||||
|
||||
xhci->usb3_rhub.hcd = hcd;
|
||||
}
|
||||
|
||||
int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
|
||||
{
|
||||
struct xhci_hcd *xhci;
|
||||
|
|
@ -5237,7 +5304,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
|
|||
* quirks
|
||||
*/
|
||||
struct device *dev = hcd->self.sysdev;
|
||||
unsigned int minor_rev;
|
||||
int retval;
|
||||
|
||||
/* Accept arbitrarily long scatter-gather lists */
|
||||
|
|
@ -5251,59 +5317,13 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
|
|||
|
||||
xhci = hcd_to_xhci(hcd);
|
||||
|
||||
if (usb_hcd_is_primary_hcd(hcd)) {
|
||||
xhci->main_hcd = hcd;
|
||||
xhci->usb2_rhub.hcd = hcd;
|
||||
/* Mark the first roothub as being USB 2.0.
|
||||
* The xHCI driver will register the USB 3.0 roothub.
|
||||
*/
|
||||
hcd->speed = HCD_USB2;
|
||||
hcd->self.root_hub->speed = USB_SPEED_HIGH;
|
||||
/*
|
||||
* USB 2.0 roothub under xHCI has an integrated TT,
|
||||
* (rate matching hub) as opposed to having an OHCI/UHCI
|
||||
* companion controller.
|
||||
*/
|
||||
hcd->has_tt = 1;
|
||||
} else {
|
||||
/*
|
||||
* Early xHCI 1.1 spec did not mention USB 3.1 capable hosts
|
||||
* should return 0x31 for sbrn, or that the minor revision
|
||||
* is a two digit BCD containig minor and sub-minor numbers.
|
||||
* This was later clarified in xHCI 1.2.
|
||||
*
|
||||
* Some USB 3.1 capable hosts therefore have sbrn 0x30, and
|
||||
* minor revision set to 0x1 instead of 0x10.
|
||||
*/
|
||||
if (xhci->usb3_rhub.min_rev == 0x1)
|
||||
minor_rev = 1;
|
||||
else
|
||||
minor_rev = xhci->usb3_rhub.min_rev / 0x10;
|
||||
|
||||
switch (minor_rev) {
|
||||
case 2:
|
||||
hcd->speed = HCD_USB32;
|
||||
hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;
|
||||
hcd->self.root_hub->rx_lanes = 2;
|
||||
hcd->self.root_hub->tx_lanes = 2;
|
||||
break;
|
||||
case 1:
|
||||
hcd->speed = HCD_USB31;
|
||||
hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;
|
||||
break;
|
||||
}
|
||||
xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n",
|
||||
minor_rev,
|
||||
minor_rev ? "Enhanced " : "");
|
||||
|
||||
xhci->usb3_rhub.hcd = hcd;
|
||||
/* xHCI private pointer was set in xhci_pci_probe for the second
|
||||
* registered roothub.
|
||||
*/
|
||||
if (!usb_hcd_is_primary_hcd(hcd)) {
|
||||
xhci_hcd_init_usb3_data(xhci, hcd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_init(&xhci->mutex);
|
||||
xhci->main_hcd = hcd;
|
||||
xhci->cap_regs = hcd->regs;
|
||||
xhci->op_regs = hcd->regs +
|
||||
HC_LENGTH(readl(&xhci->cap_regs->hc_capbase));
|
||||
|
|
@ -5379,6 +5399,11 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
|
|||
return retval;
|
||||
xhci_dbg(xhci, "Called HCD init\n");
|
||||
|
||||
if (xhci_hcd_is_usb3(hcd))
|
||||
xhci_hcd_init_usb3_data(xhci, hcd);
|
||||
else
|
||||
xhci_hcd_init_usb2_data(xhci, hcd);
|
||||
|
||||
xhci_info(xhci, "hcc params 0x%08x hci version 0x%x quirks 0x%016llx\n",
|
||||
xhci->hcc_params, xhci->hci_version, xhci->quirks);
|
||||
|
||||
|
|
|
|||
|
|
@ -1902,6 +1902,8 @@ struct xhci_hcd {
|
|||
unsigned hw_lpm_support:1;
|
||||
/* Broken Suspend flag for SNPS Suspend resume issue */
|
||||
unsigned broken_suspend:1;
|
||||
/* Indicates that omitting hcd is supported if root hub has no ports */
|
||||
unsigned allow_single_roothub:1;
|
||||
/* cached usb2 extened protocol capabilites */
|
||||
u32 *ext_caps;
|
||||
unsigned int num_ext_caps;
|
||||
|
|
@ -1955,6 +1957,30 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
|
|||
return xhci->main_hcd;
|
||||
}
|
||||
|
||||
static inline struct usb_hcd *xhci_get_usb3_hcd(struct xhci_hcd *xhci)
|
||||
{
|
||||
if (xhci->shared_hcd)
|
||||
return xhci->shared_hcd;
|
||||
|
||||
if (!xhci->usb2_rhub.num_ports)
|
||||
return xhci->main_hcd;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool xhci_hcd_is_usb3(struct usb_hcd *hcd)
|
||||
{
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
|
||||
return hcd == xhci_get_usb3_hcd(xhci);
|
||||
}
|
||||
|
||||
static inline bool xhci_has_one_roothub(struct xhci_hcd *xhci)
|
||||
{
|
||||
return xhci->allow_single_roothub &&
|
||||
(!xhci->usb2_rhub.num_ports || !xhci->usb3_rhub.num_ports);
|
||||
}
|
||||
|
||||
#define xhci_dbg(xhci, fmt, args...) \
|
||||
dev_dbg(xhci_to_hcd(xhci)->self.controller , fmt , ## args)
|
||||
#define xhci_err(xhci, fmt, args...) \
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ extern int qcom_scm_set_remote_state(u32 state, u32 id);
|
|||
extern int qcom_scm_spin_cpu(void);
|
||||
extern void qcom_scm_set_download_mode(enum qcom_download_mode mode,
|
||||
phys_addr_t tcsr_boot_misc);
|
||||
extern int qcom_scm_get_download_mode(unsigned int *mode, phys_addr_t tcsr_boot_misc);
|
||||
extern int qcom_scm_config_cpu_errata(void);
|
||||
extern void qcom_scm_phy_update_scm_level_shifter(u32 val);
|
||||
extern bool qcom_scm_pas_supported(u32 peripheral);
|
||||
|
|
@ -244,6 +245,8 @@ static inline u32 qcom_scm_set_remote_state(u32 state, u32 id)
|
|||
static inline int qcom_scm_spin_cpu(void) { return -ENODEV; }
|
||||
static inline void qcom_scm_set_download_mode(enum qcom_download_mode mode,
|
||||
phys_addr_t tcsr_boot_misc) {}
|
||||
static inline int qcom_scm_get_download_mode(unsigned int *mode,
|
||||
phys_addr_t tcsr_boot_misc) {}
|
||||
static inline int qcom_scm_config_cpu_errata(void)
|
||||
{ return -ENODEV; }
|
||||
static inline void qcom_scm_phy_update_scm_level_shifter(u32 val) {}
|
||||
|
|
|
|||
|
|
@ -1731,7 +1731,7 @@ struct IpaDscpVlanPcpMap_t {
|
|||
uint8_t num_vlan; /* indicate how many vlans valid vlan above */
|
||||
uint8_t num_s_vlan; /* indicate how many vlans valid in s_vlan below */
|
||||
uint8_t dscp_opt; /* indicates if dscp is required or optional */
|
||||
uint8_t pad1; /* for alignment */
|
||||
uint8_t tunnel_id; /* tunnel id */
|
||||
/*
|
||||
* The same lookup scheme, using vlan[] above, is used for
|
||||
* generating the first index of mpls below; and in addition,
|
||||
|
|
@ -1750,8 +1750,8 @@ struct IpaDscpVlanPcpMap_t {
|
|||
* mpls_val_sorted is in ascending order, by mpls label values in mpls array
|
||||
* vlan_c and vlan_s are vlan id values that are corresponding to the mpls label
|
||||
*/
|
||||
uint16_t pad2; /* for alignment */
|
||||
uint8_t pad3; /* for alignment */
|
||||
uint16_t del_add_vlan_id; /* vlan id to add or del */
|
||||
uint8_t is_vlan_to_del_add; /* whether to add or del vlan? */
|
||||
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];
|
||||
uint16_t vlan_c[IPA_EoGRE_MAX_VLAN * IPA_GRE_MAX_S_VLAN];
|
||||
|
|
@ -1825,7 +1825,7 @@ struct singletag_mux_mapping_table_t {
|
|||
uint8_t mux_id;
|
||||
/* flag if 1=>pkt_with_option_hdr 0=>pkt_without_option_hdr */
|
||||
uint8_t is_v6_options_hdr_present;
|
||||
uint16_t pad0; /*for alignment*/
|
||||
uint16_t tunnel_id;/* tunnel_id */
|
||||
uint32_t *tunnel_template_addr;
|
||||
} __packed;
|
||||
|
||||
|
|
@ -1850,13 +1850,22 @@ struct doubletag_mux_mapping_table_t {
|
|||
/* max number of tunnel to support ie: per PDN two tunnel (2*8)*/
|
||||
#define MAX_TUNNEL_SUPPORT 16
|
||||
|
||||
/* configuration table */
|
||||
/* @tunnel_protocols_config_table_t: Config tbl for uC
|
||||
* @untagged_mapping_table : Store the untag tunnel info.
|
||||
* @num_of_single_tag_configs : no of active tunnel in single tag config.
|
||||
* @feature_mode: which tunnel feature is enabled.
|
||||
* @tunnel_id: Which tunnel info receive from ipacm.
|
||||
* @is_tunnel_id_to_del: whether tunnel to delete.
|
||||
* @singletag_mux_mapping_table: Store tunnel info for active tunnels.
|
||||
* @num_of_double_tag_configs: no of active tunnel in double tag config.
|
||||
* @doubletag_mux_mapping_table: Store double tag tunnel info.
|
||||
*/
|
||||
struct tunnel_protocols_config_table_t {
|
||||
struct untag_pkt_config_t untagged_mapping_table;
|
||||
uint8_t num_of_single_tag_configs;
|
||||
uint8_t pad0; /*for alignment*/
|
||||
uint16_t pad1; /*for alignment*/
|
||||
uint32_t pad2; /*for alignment*/
|
||||
uint8_t feature_mode;
|
||||
uint16_t tunnel_id;
|
||||
uint32_t is_tunnel_id_to_del;
|
||||
/* table for single tag pkt */
|
||||
struct singletag_mux_mapping_table_t singletag_mux_mapping_table[MAX_TUNNEL_SUPPORT];
|
||||
uint8_t num_of_double_tag_configs;
|
||||
|
|
|
|||
Loading…
Reference in a new issue