Merge 126be03494 ("riscv: misaligned: Add handling for ZCB instructions") into android16-6.12-lts

Steps on the way to 6.12.29

Resolves merge conflicts in:
	drivers/usb/dwc3/core.h

Change-Id: I49aaba307edc76ccb70e922ad6bcda97e16c9a9c
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2025-06-03 08:12:21 +00:00
23 changed files with 173 additions and 85 deletions
+2 -1
View File
@@ -65,7 +65,8 @@ static inline void instruction_pointer_set(struct pt_regs *regs,
/* Query offset/name of register from its name/offset */ /* Query offset/name of register from its name/offset */
extern int regs_query_register_offset(const char *name); extern int regs_query_register_offset(const char *name);
#define MAX_REG_OFFSET (offsetof(struct pt_regs, __last)) #define MAX_REG_OFFSET \
(offsetof(struct pt_regs, __last) - sizeof(unsigned long))
/** /**
* regs_get_register() - get register value from its offset * regs_get_register() - get register value from its offset
+17
View File
@@ -87,6 +87,13 @@
#define INSN_MATCH_C_FSWSP 0xe002 #define INSN_MATCH_C_FSWSP 0xe002
#define INSN_MASK_C_FSWSP 0xe003 #define INSN_MASK_C_FSWSP 0xe003
#define INSN_MATCH_C_LHU 0x8400
#define INSN_MASK_C_LHU 0xfc43
#define INSN_MATCH_C_LH 0x8440
#define INSN_MASK_C_LH 0xfc43
#define INSN_MATCH_C_SH 0x8c00
#define INSN_MASK_C_SH 0xfc43
#define INSN_LEN(insn) ((((insn) & 0x3) < 0x3) ? 2 : 4) #define INSN_LEN(insn) ((((insn) & 0x3) < 0x3) ? 2 : 4)
#if defined(CONFIG_64BIT) #if defined(CONFIG_64BIT)
@@ -405,6 +412,13 @@ int handle_misaligned_load(struct pt_regs *regs)
fp = 1; fp = 1;
len = 4; len = 4;
#endif #endif
} else if ((insn & INSN_MASK_C_LHU) == INSN_MATCH_C_LHU) {
len = 2;
insn = RVC_RS2S(insn) << SH_RD;
} else if ((insn & INSN_MASK_C_LH) == INSN_MATCH_C_LH) {
len = 2;
shift = 8 * (sizeof(ulong) - len);
insn = RVC_RS2S(insn) << SH_RD;
} else { } else {
regs->epc = epc; regs->epc = epc;
return -1; return -1;
@@ -504,6 +518,9 @@ int handle_misaligned_store(struct pt_regs *regs)
len = 4; len = 4;
val.data_ulong = GET_F32_RS2C(insn, regs); val.data_ulong = GET_F32_RS2C(insn, regs);
#endif #endif
} else if ((insn & INSN_MASK_C_SH) == INSN_MATCH_C_SH) {
len = 2;
val.data_ulong = GET_RS2S(insn, regs);
} else { } else {
regs->epc = epc; regs->epc = epc;
return -1; return -1;
+1 -1
View File
@@ -231,7 +231,7 @@ struct adxl355_data {
u8 transf_buf[3]; u8 transf_buf[3];
struct { struct {
u8 buf[14]; u8 buf[14];
s64 ts; aligned_s64 ts;
} buffer; } buffer;
} __aligned(IIO_DMA_MINALIGN); } __aligned(IIO_DMA_MINALIGN);
}; };
+3 -7
View File
@@ -604,18 +604,14 @@ static int _adxl367_set_odr(struct adxl367_state *st, enum adxl367_odr odr)
if (ret) if (ret)
return ret; return ret;
st->odr = odr;
/* Activity timers depend on ODR */ /* Activity timers depend on ODR */
ret = _adxl367_set_act_time_ms(st, st->act_time_ms); ret = _adxl367_set_act_time_ms(st, st->act_time_ms);
if (ret) if (ret)
return ret; return ret;
ret = _adxl367_set_inact_time_ms(st, st->inact_time_ms); return _adxl367_set_inact_time_ms(st, st->inact_time_ms);
if (ret)
return ret;
st->odr = odr;
return 0;
} }
static int adxl367_set_odr(struct iio_dev *indio_dev, enum adxl367_odr odr) static int adxl367_set_odr(struct iio_dev *indio_dev, enum adxl367_odr odr)
+1 -1
View File
@@ -481,7 +481,7 @@ static irqreturn_t dln2_adc_trigger_h(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev; struct iio_dev *indio_dev = pf->indio_dev;
struct { struct {
__le16 values[DLN2_ADC_MAX_CHANNELS]; __le16 values[DLN2_ADC_MAX_CHANNELS];
int64_t timestamp_space; aligned_s64 timestamp_space;
} data; } data;
struct dln2_adc_get_all_vals dev_data; struct dln2_adc_get_all_vals dev_data;
struct dln2_adc *dln2 = iio_priv(indio_dev); struct dln2_adc *dln2 = iio_priv(indio_dev);
+1 -1
View File
@@ -121,9 +121,9 @@ static const struct maxim_thermocouple_chip maxim_thermocouple_chips[] = {
struct maxim_thermocouple_data { struct maxim_thermocouple_data {
struct spi_device *spi; struct spi_device *spi;
const struct maxim_thermocouple_chip *chip; const struct maxim_thermocouple_chip *chip;
char tc_type;
u8 buffer[16] __aligned(IIO_DMA_MINALIGN); u8 buffer[16] __aligned(IIO_DMA_MINALIGN);
char tc_type;
}; };
static int maxim_thermocouple_read(struct maxim_thermocouple_data *data, static int maxim_thermocouple_read(struct maxim_thermocouple_data *data,
+31
View File
@@ -138,6 +138,26 @@ static void cdnsp_clear_port_change_bit(struct cdnsp_device *pdev,
(portsc & PORT_CHANGE_BITS), port_regs); (portsc & PORT_CHANGE_BITS), port_regs);
} }
static void cdnsp_set_apb_timeout_value(struct cdnsp_device *pdev)
{
struct cdns *cdns = dev_get_drvdata(pdev->dev);
__le32 __iomem *reg;
void __iomem *base;
u32 offset = 0;
u32 val;
if (!cdns->override_apb_timeout)
return;
base = &pdev->cap_regs->hc_capbase;
offset = cdnsp_find_next_ext_cap(base, offset, D_XEC_PRE_REGS_CAP);
reg = base + offset + REG_CHICKEN_BITS_3_OFFSET;
val = le32_to_cpu(readl(reg));
val = CHICKEN_APB_TIMEOUT_SET(val, cdns->override_apb_timeout);
writel(cpu_to_le32(val), reg);
}
static void cdnsp_set_chicken_bits_2(struct cdnsp_device *pdev, u32 bit) static void cdnsp_set_chicken_bits_2(struct cdnsp_device *pdev, u32 bit)
{ {
__le32 __iomem *reg; __le32 __iomem *reg;
@@ -1772,6 +1792,8 @@ static void cdnsp_get_rev_cap(struct cdnsp_device *pdev)
reg += cdnsp_find_next_ext_cap(reg, 0, RTL_REV_CAP); reg += cdnsp_find_next_ext_cap(reg, 0, RTL_REV_CAP);
pdev->rev_cap = reg; pdev->rev_cap = reg;
pdev->rtl_revision = readl(&pdev->rev_cap->rtl_revision);
dev_info(pdev->dev, "Rev: %08x/%08x, eps: %08x, buff: %08x/%08x\n", dev_info(pdev->dev, "Rev: %08x/%08x, eps: %08x, buff: %08x/%08x\n",
readl(&pdev->rev_cap->ctrl_revision), readl(&pdev->rev_cap->ctrl_revision),
readl(&pdev->rev_cap->rtl_revision), readl(&pdev->rev_cap->rtl_revision),
@@ -1797,6 +1819,15 @@ static int cdnsp_gen_setup(struct cdnsp_device *pdev)
pdev->hci_version = HC_VERSION(pdev->hcc_params); pdev->hci_version = HC_VERSION(pdev->hcc_params);
pdev->hcc_params = readl(&pdev->cap_regs->hcc_params); pdev->hcc_params = readl(&pdev->cap_regs->hcc_params);
/*
* Override the APB timeout value to give the controller more time for
* enabling UTMI clock and synchronizing APB and UTMI clock domains.
* This fix is platform specific and is required to fixes issue with
* reading incorrect value from PORTSC register after resuming
* from L1 state.
*/
cdnsp_set_apb_timeout_value(pdev);
cdnsp_get_rev_cap(pdev); cdnsp_get_rev_cap(pdev);
/* Make sure the Device Controller is halted. */ /* Make sure the Device Controller is halted. */
+6
View File
@@ -520,6 +520,9 @@ struct cdnsp_rev_cap {
#define REG_CHICKEN_BITS_2_OFFSET 0x48 #define REG_CHICKEN_BITS_2_OFFSET 0x48
#define CHICKEN_XDMA_2_TP_CACHE_DIS BIT(28) #define CHICKEN_XDMA_2_TP_CACHE_DIS BIT(28)
#define REG_CHICKEN_BITS_3_OFFSET 0x4C
#define CHICKEN_APB_TIMEOUT_SET(p, val) (((p) & ~GENMASK(21, 0)) | (val))
/* XBUF Extended Capability ID. */ /* XBUF Extended Capability ID. */
#define XBUF_CAP_ID 0xCB #define XBUF_CAP_ID 0xCB
#define XBUF_RX_TAG_MASK_0_OFFSET 0x1C #define XBUF_RX_TAG_MASK_0_OFFSET 0x1C
@@ -1357,6 +1360,7 @@ struct cdnsp_port {
* @rev_cap: Controller Capabilities Registers. * @rev_cap: Controller Capabilities Registers.
* @hcs_params1: Cached register copies of read-only HCSPARAMS1 * @hcs_params1: Cached register copies of read-only HCSPARAMS1
* @hcc_params: Cached register copies of read-only HCCPARAMS1 * @hcc_params: Cached register copies of read-only HCCPARAMS1
* @rtl_revision: Cached controller rtl revision.
* @setup: Temporary buffer for setup packet. * @setup: Temporary buffer for setup packet.
* @ep0_preq: Internal allocated request used during enumeration. * @ep0_preq: Internal allocated request used during enumeration.
* @ep0_stage: ep0 stage during enumeration process. * @ep0_stage: ep0 stage during enumeration process.
@@ -1411,6 +1415,8 @@ struct cdnsp_device {
__u32 hcs_params1; __u32 hcs_params1;
__u32 hcs_params3; __u32 hcs_params3;
__u32 hcc_params; __u32 hcc_params;
#define RTL_REVISION_NEW_LPM 0x2700
__u32 rtl_revision;
/* Lock used in interrupt thread context. */ /* Lock used in interrupt thread context. */
spinlock_t lock; spinlock_t lock;
struct usb_ctrlrequest setup; struct usb_ctrlrequest setup;
+10 -2
View File
@@ -34,6 +34,8 @@
#define PCI_CLASS_SERIAL_USB_CDNS_USB3 (PCI_CLASS_SERIAL_USB << 8 | 0x80) #define PCI_CLASS_SERIAL_USB_CDNS_USB3 (PCI_CLASS_SERIAL_USB << 8 | 0x80)
#define PCI_CLASS_SERIAL_USB_CDNS_UDC PCI_CLASS_SERIAL_USB_DEVICE #define PCI_CLASS_SERIAL_USB_CDNS_UDC PCI_CLASS_SERIAL_USB_DEVICE
#define CHICKEN_APB_TIMEOUT_VALUE 0x1C20
static struct pci_dev *cdnsp_get_second_fun(struct pci_dev *pdev) static struct pci_dev *cdnsp_get_second_fun(struct pci_dev *pdev)
{ {
/* /*
@@ -145,6 +147,14 @@ static int cdnsp_pci_probe(struct pci_dev *pdev,
cdnsp->otg_irq = pdev->irq; cdnsp->otg_irq = pdev->irq;
} }
/*
* Cadence PCI based platform require some longer timeout for APB
* to fixes domain clock synchronization issue after resuming
* controller from L1 state.
*/
cdnsp->override_apb_timeout = CHICKEN_APB_TIMEOUT_VALUE;
pci_set_drvdata(pdev, cdnsp);
if (pci_is_enabled(func)) { if (pci_is_enabled(func)) {
cdnsp->dev = dev; cdnsp->dev = dev;
cdnsp->gadget_init = cdnsp_gadget_init; cdnsp->gadget_init = cdnsp_gadget_init;
@@ -154,8 +164,6 @@ static int cdnsp_pci_probe(struct pci_dev *pdev,
goto free_cdnsp; goto free_cdnsp;
} }
pci_set_drvdata(pdev, cdnsp);
device_wakeup_enable(&pdev->dev); device_wakeup_enable(&pdev->dev);
if (pci_dev_run_wake(pdev)) if (pci_dev_run_wake(pdev))
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
+2 -1
View File
@@ -308,7 +308,8 @@ static bool cdnsp_ring_ep_doorbell(struct cdnsp_device *pdev,
writel(db_value, reg_addr); writel(db_value, reg_addr);
cdnsp_force_l0_go(pdev); if (pdev->rtl_revision < RTL_REVISION_NEW_LPM)
cdnsp_force_l0_go(pdev);
/* Doorbell was set. */ /* Doorbell was set. */
return true; return true;
+3
View File
@@ -79,6 +79,8 @@ struct cdns3_platform_data {
* @pdata: platform data from glue layer * @pdata: platform data from glue layer
* @lock: spinlock structure * @lock: spinlock structure
* @xhci_plat_data: xhci private data structure pointer * @xhci_plat_data: xhci private data structure pointer
* @override_apb_timeout: hold value of APB timeout. For value 0 the default
* value in CHICKEN_BITS_3 will be preserved.
* @gadget_init: pointer to gadget initialization function * @gadget_init: pointer to gadget initialization function
*/ */
struct cdns { struct cdns {
@@ -117,6 +119,7 @@ struct cdns {
struct cdns3_platform_data *pdata; struct cdns3_platform_data *pdata;
spinlock_t lock; spinlock_t lock;
struct xhci_plat_priv *xhci_plat_data; struct xhci_plat_priv *xhci_plat_data;
u32 override_apb_timeout;
int (*gadget_init)(struct cdns *cdns); int (*gadget_init)(struct cdns *cdns);
}; };
+36 -23
View File
@@ -482,6 +482,7 @@ static int usbtmc_get_stb(struct usbtmc_file_data *file_data, __u8 *stb)
u8 *buffer; u8 *buffer;
u8 tag; u8 tag;
int rv; int rv;
long wait_rv;
dev_dbg(dev, "Enter ioctl_read_stb iin_ep_present: %d\n", dev_dbg(dev, "Enter ioctl_read_stb iin_ep_present: %d\n",
data->iin_ep_present); data->iin_ep_present);
@@ -511,16 +512,17 @@ static int usbtmc_get_stb(struct usbtmc_file_data *file_data, __u8 *stb)
} }
if (data->iin_ep_present) { if (data->iin_ep_present) {
rv = wait_event_interruptible_timeout( wait_rv = wait_event_interruptible_timeout(
data->waitq, data->waitq,
atomic_read(&data->iin_data_valid) != 0, atomic_read(&data->iin_data_valid) != 0,
file_data->timeout); file_data->timeout);
if (rv < 0) { if (wait_rv < 0) {
dev_dbg(dev, "wait interrupted %d\n", rv); dev_dbg(dev, "wait interrupted %ld\n", wait_rv);
rv = wait_rv;
goto exit; goto exit;
} }
if (rv == 0) { if (wait_rv == 0) {
dev_dbg(dev, "wait timed out\n"); dev_dbg(dev, "wait timed out\n");
rv = -ETIMEDOUT; rv = -ETIMEDOUT;
goto exit; goto exit;
@@ -539,6 +541,8 @@ static int usbtmc_get_stb(struct usbtmc_file_data *file_data, __u8 *stb)
dev_dbg(dev, "stb:0x%02x received %d\n", (unsigned int)*stb, rv); dev_dbg(dev, "stb:0x%02x received %d\n", (unsigned int)*stb, rv);
rv = 0;
exit: exit:
/* bump interrupt bTag */ /* bump interrupt bTag */
data->iin_bTag += 1; data->iin_bTag += 1;
@@ -602,9 +606,9 @@ static int usbtmc488_ioctl_wait_srq(struct usbtmc_file_data *file_data,
{ {
struct usbtmc_device_data *data = file_data->data; struct usbtmc_device_data *data = file_data->data;
struct device *dev = &data->intf->dev; struct device *dev = &data->intf->dev;
int rv;
u32 timeout; u32 timeout;
unsigned long expire; unsigned long expire;
long wait_rv;
if (!data->iin_ep_present) { if (!data->iin_ep_present) {
dev_dbg(dev, "no interrupt endpoint present\n"); dev_dbg(dev, "no interrupt endpoint present\n");
@@ -618,25 +622,24 @@ static int usbtmc488_ioctl_wait_srq(struct usbtmc_file_data *file_data,
mutex_unlock(&data->io_mutex); mutex_unlock(&data->io_mutex);
rv = wait_event_interruptible_timeout( wait_rv = wait_event_interruptible_timeout(
data->waitq, data->waitq,
atomic_read(&file_data->srq_asserted) != 0 || atomic_read(&file_data->srq_asserted) != 0 ||
atomic_read(&file_data->closing), atomic_read(&file_data->closing),
expire); expire);
mutex_lock(&data->io_mutex); mutex_lock(&data->io_mutex);
/* Note! disconnect or close could be called in the meantime */ /* Note! disconnect or close could be called in the meantime */
if (atomic_read(&file_data->closing) || data->zombie) if (atomic_read(&file_data->closing) || data->zombie)
rv = -ENODEV; return -ENODEV;
if (rv < 0) { if (wait_rv < 0) {
/* dev can be invalid now! */ dev_dbg(dev, "%s - wait interrupted %ld\n", __func__, wait_rv);
pr_debug("%s - wait interrupted %d\n", __func__, rv); return wait_rv;
return rv;
} }
if (rv == 0) { if (wait_rv == 0) {
dev_dbg(dev, "%s - wait timed out\n", __func__); dev_dbg(dev, "%s - wait timed out\n", __func__);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@@ -830,6 +833,7 @@ static ssize_t usbtmc_generic_read(struct usbtmc_file_data *file_data,
unsigned long expire; unsigned long expire;
int bufcount = 1; int bufcount = 1;
int again = 0; int again = 0;
long wait_rv;
/* mutex already locked */ /* mutex already locked */
@@ -942,19 +946,24 @@ static ssize_t usbtmc_generic_read(struct usbtmc_file_data *file_data,
if (!(flags & USBTMC_FLAG_ASYNC)) { if (!(flags & USBTMC_FLAG_ASYNC)) {
dev_dbg(dev, "%s: before wait time %lu\n", dev_dbg(dev, "%s: before wait time %lu\n",
__func__, expire); __func__, expire);
retval = wait_event_interruptible_timeout( wait_rv = wait_event_interruptible_timeout(
file_data->wait_bulk_in, file_data->wait_bulk_in,
usbtmc_do_transfer(file_data), usbtmc_do_transfer(file_data),
expire); expire);
dev_dbg(dev, "%s: wait returned %d\n", dev_dbg(dev, "%s: wait returned %ld\n",
__func__, retval); __func__, wait_rv);
if (retval <= 0) { if (wait_rv < 0) {
if (retval == 0) retval = wait_rv;
retval = -ETIMEDOUT;
goto error; goto error;
} }
if (wait_rv == 0) {
retval = -ETIMEDOUT;
goto error;
}
} }
urb = usb_get_from_anchor(&file_data->in_anchor); urb = usb_get_from_anchor(&file_data->in_anchor);
@@ -1380,7 +1389,10 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
if (!buffer) if (!buffer)
return -ENOMEM; return -ENOMEM;
mutex_lock(&data->io_mutex); retval = mutex_lock_interruptible(&data->io_mutex);
if (retval < 0)
goto exit_nolock;
if (data->zombie) { if (data->zombie) {
retval = -ENODEV; retval = -ENODEV;
goto exit; goto exit;
@@ -1503,6 +1515,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
exit: exit:
mutex_unlock(&data->io_mutex); mutex_unlock(&data->io_mutex);
exit_nolock:
kfree(buffer); kfree(buffer);
return retval; return retval;
} }
+4
View File
@@ -1181,6 +1181,9 @@ struct dwc3_scratchpad_array {
* @gsbuscfg0_reqinfo: store GSBUSCFG0.DATRDREQINFO, DESRDREQINFO, * @gsbuscfg0_reqinfo: store GSBUSCFG0.DATRDREQINFO, DESRDREQINFO,
* DATWRREQINFO, and DESWRREQINFO value passed from * DATWRREQINFO, and DESWRREQINFO value passed from
* glue driver. * glue driver.
* @wakeup_pending_funcs: Indicates whether any interface has requested for
* function wakeup in bitmap format where bit position
* represents interface_id.
*/ */
struct dwc3 { struct dwc3 {
struct work_struct drd_work; struct work_struct drd_work;
@@ -1412,6 +1415,7 @@ struct dwc3 {
int num_ep_resized; int num_ep_resized;
struct dentry *debug_root; struct dentry *debug_root;
u32 gsbuscfg0_reqinfo; u32 gsbuscfg0_reqinfo;
u32 wakeup_pending_funcs;
ANDROID_KABI_RESERVE(1); ANDROID_KABI_RESERVE(1);
ANDROID_KABI_RESERVE(2); ANDROID_KABI_RESERVE(2);
+23 -37
View File
@@ -277,8 +277,6 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd,
return ret; return ret;
} }
static int __dwc3_gadget_wakeup(struct dwc3 *dwc, bool async);
/** /**
* dwc3_send_gadget_ep_cmd - issue an endpoint command * dwc3_send_gadget_ep_cmd - issue an endpoint command
* @dep: the endpoint to which the command is going to be issued * @dep: the endpoint to which the command is going to be issued
@@ -2348,10 +2346,8 @@ static int dwc3_gadget_get_frame(struct usb_gadget *g)
return __dwc3_gadget_get_frame(dwc); return __dwc3_gadget_get_frame(dwc);
} }
static int __dwc3_gadget_wakeup(struct dwc3 *dwc, bool async) static int __dwc3_gadget_wakeup(struct dwc3 *dwc)
{ {
int retries;
int ret; int ret;
u32 reg; u32 reg;
@@ -2379,8 +2375,7 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc, bool async)
return -EINVAL; return -EINVAL;
} }
if (async) dwc3_gadget_enable_linksts_evts(dwc, true);
dwc3_gadget_enable_linksts_evts(dwc, true);
ret = dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RECOV); ret = dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RECOV);
if (ret < 0) { if (ret < 0) {
@@ -2399,27 +2394,8 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc, bool async)
/* /*
* Since link status change events are enabled we will receive * Since link status change events are enabled we will receive
* an U0 event when wakeup is successful. So bail out. * an U0 event when wakeup is successful.
*/ */
if (async)
return 0;
/* poll until Link State changes to ON */
retries = 20000;
while (retries--) {
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
/* in HS, means ON */
if (DWC3_DSTS_USBLNKST(reg) == DWC3_LINK_STATE_U0)
break;
}
if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U0) {
dev_err(dwc->dev, "failed to send remote wakeup\n");
return -EINVAL;
}
return 0; return 0;
} }
@@ -2440,7 +2416,7 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g)
spin_unlock_irqrestore(&dwc->lock, flags); spin_unlock_irqrestore(&dwc->lock, flags);
return -EINVAL; return -EINVAL;
} }
ret = __dwc3_gadget_wakeup(dwc, true); ret = __dwc3_gadget_wakeup(dwc);
spin_unlock_irqrestore(&dwc->lock, flags); spin_unlock_irqrestore(&dwc->lock, flags);
@@ -2468,14 +2444,10 @@ static int dwc3_gadget_func_wakeup(struct usb_gadget *g, int intf_id)
*/ */
link_state = dwc3_gadget_get_link_state(dwc); link_state = dwc3_gadget_get_link_state(dwc);
if (link_state == DWC3_LINK_STATE_U3) { if (link_state == DWC3_LINK_STATE_U3) {
ret = __dwc3_gadget_wakeup(dwc, false); dwc->wakeup_pending_funcs |= BIT(intf_id);
if (ret) { ret = __dwc3_gadget_wakeup(dwc);
spin_unlock_irqrestore(&dwc->lock, flags); spin_unlock_irqrestore(&dwc->lock, flags);
return -EINVAL; return ret;
}
dwc3_resume_gadget(dwc);
dwc->suspended = false;
dwc->link_state = DWC3_LINK_STATE_U0;
} }
ret = dwc3_send_gadget_generic_command(dwc, DWC3_DGCMD_DEV_NOTIFICATION, ret = dwc3_send_gadget_generic_command(dwc, DWC3_DGCMD_DEV_NOTIFICATION,
@@ -4322,6 +4294,8 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
{ {
enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK; enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK;
unsigned int pwropt; unsigned int pwropt;
int ret;
int intf_id;
/* /*
* WORKAROUND: DWC3 < 2.50a have an issue when configured without * WORKAROUND: DWC3 < 2.50a have an issue when configured without
@@ -4397,7 +4371,7 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
switch (next) { switch (next) {
case DWC3_LINK_STATE_U0: case DWC3_LINK_STATE_U0:
if (dwc->gadget->wakeup_armed) { if (dwc->gadget->wakeup_armed || dwc->wakeup_pending_funcs) {
dwc3_gadget_enable_linksts_evts(dwc, false); dwc3_gadget_enable_linksts_evts(dwc, false);
dwc3_resume_gadget(dwc); dwc3_resume_gadget(dwc);
dwc->suspended = false; dwc->suspended = false;
@@ -4420,6 +4394,18 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
} }
dwc->link_state = next; dwc->link_state = next;
/* Proceed with func wakeup if any interfaces that has requested */
while (dwc->wakeup_pending_funcs && (next == DWC3_LINK_STATE_U0)) {
intf_id = ffs(dwc->wakeup_pending_funcs) - 1;
ret = dwc3_send_gadget_generic_command(dwc, DWC3_DGCMD_DEV_NOTIFICATION,
DWC3_DGCMDPAR_DN_FUNC_WAKE |
DWC3_DGCMDPAR_INTF_SEL(intf_id));
if (ret)
dev_err(dwc->dev, "Failed to send DN wake for intf %d\n", intf_id);
dwc->wakeup_pending_funcs &= ~BIT(intf_id);
}
} }
static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc, static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc,
+5 -7
View File
@@ -2017,15 +2017,13 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (f->get_status) { if (f->get_status) {
status = f->get_status(f); status = f->get_status(f);
if (status < 0) if (status < 0)
break; break;
} else {
/* Set D0 and D1 bits based on func wakeup capability */ /* if D5 is not set, then device is not wakeup capable */
if (f->config->bmAttributes & USB_CONFIG_ATT_WAKEUP) { if (!(f->config->bmAttributes & USB_CONFIG_ATT_WAKEUP))
status |= USB_INTRF_STAT_FUNC_RW_CAP; status &= ~(USB_INTRF_STAT_FUNC_RW_CAP | USB_INTRF_STAT_FUNC_RW);
if (f->func_wakeup_armed)
status |= USB_INTRF_STAT_FUNC_RW;
}
} }
put_unaligned_le16(status & 0x0000ffff, req->buf); put_unaligned_le16(status & 0x0000ffff, req->buf);
+7
View File
@@ -892,6 +892,12 @@ static void ecm_resume(struct usb_function *f)
gether_resume(&ecm->port); gether_resume(&ecm->port);
} }
static int ecm_get_status(struct usb_function *f)
{
return (f->func_wakeup_armed ? USB_INTRF_STAT_FUNC_RW : 0) |
USB_INTRF_STAT_FUNC_RW_CAP;
}
static void ecm_free(struct usb_function *f) static void ecm_free(struct usb_function *f)
{ {
struct f_ecm *ecm; struct f_ecm *ecm;
@@ -960,6 +966,7 @@ static struct usb_function *ecm_alloc(struct usb_function_instance *fi)
ecm->port.func.disable = ecm_disable; ecm->port.func.disable = ecm_disable;
ecm->port.func.free_func = ecm_free; ecm->port.func.free_func = ecm_free;
ecm->port.func.suspend = ecm_suspend; ecm->port.func.suspend = ecm_suspend;
ecm->port.func.get_status = ecm_get_status;
ecm->port.func.resume = ecm_resume; ecm->port.func.resume = ecm_resume;
return &ecm->port.func; return &ecm->port.func;
+4
View File
@@ -1749,6 +1749,10 @@ static int __tegra_xudc_ep_disable(struct tegra_xudc_ep *ep)
val = xudc_readl(xudc, CTRL); val = xudc_readl(xudc, CTRL);
val &= ~CTRL_RUN; val &= ~CTRL_RUN;
xudc_writel(xudc, val, CTRL); xudc_writel(xudc, val, CTRL);
val = xudc_readl(xudc, ST);
if (val & ST_RC)
xudc_writel(xudc, ST_RC, ST);
} }
dev_info(xudc->dev, "ep %u disabled\n", ep->index); dev_info(xudc->dev, "ep %u disabled\n", ep->index);
+3
View File
@@ -1363,6 +1363,7 @@ static void tegra_xhci_id_work(struct work_struct *work)
tegra->otg_usb3_port = tegra_xusb_padctl_get_usb3_companion(tegra->padctl, tegra->otg_usb3_port = tegra_xusb_padctl_get_usb3_companion(tegra->padctl,
tegra->otg_usb2_port); tegra->otg_usb2_port);
pm_runtime_get_sync(tegra->dev);
if (tegra->host_mode) { if (tegra->host_mode) {
/* switch to host mode */ /* switch to host mode */
if (tegra->otg_usb3_port >= 0) { if (tegra->otg_usb3_port >= 0) {
@@ -1392,6 +1393,7 @@ static void tegra_xhci_id_work(struct work_struct *work)
} }
tegra_xhci_set_port_power(tegra, true, true); tegra_xhci_set_port_power(tegra, true, true);
pm_runtime_mark_last_busy(tegra->dev);
} else { } else {
if (tegra->otg_usb3_port >= 0) if (tegra->otg_usb3_port >= 0)
@@ -1399,6 +1401,7 @@ static void tegra_xhci_id_work(struct work_struct *work)
tegra_xhci_set_port_power(tegra, true, false); tegra_xhci_set_port_power(tegra, true, false);
} }
pm_runtime_put_autosuspend(tegra->dev);
} }
#if IS_ENABLED(CONFIG_PM) || IS_ENABLED(CONFIG_PM_SLEEP) #if IS_ENABLED(CONFIG_PM) || IS_ENABLED(CONFIG_PM_SLEEP)
+8 -2
View File
@@ -569,8 +569,14 @@ static void onboard_dev_usbdev_disconnect(struct usb_device *udev)
} }
static const struct usb_device_id onboard_dev_id_table[] = { static const struct usb_device_id onboard_dev_id_table[] = {
{ USB_DEVICE(VENDOR_ID_CYPRESS, 0x6504) }, /* CYUSB33{0,1,2}x/CYUSB230x 3.0 HUB */ { USB_DEVICE(VENDOR_ID_CYPRESS, 0x6500) }, /* CYUSB330x 3.0 HUB */
{ USB_DEVICE(VENDOR_ID_CYPRESS, 0x6506) }, /* CYUSB33{0,1,2}x/CYUSB230x 2.0 HUB */ { USB_DEVICE(VENDOR_ID_CYPRESS, 0x6502) }, /* CYUSB330x 2.0 HUB */
{ USB_DEVICE(VENDOR_ID_CYPRESS, 0x6503) }, /* CYUSB33{0,1}x 2.0 HUB, Vendor Mode */
{ USB_DEVICE(VENDOR_ID_CYPRESS, 0x6504) }, /* CYUSB331x 3.0 HUB */
{ USB_DEVICE(VENDOR_ID_CYPRESS, 0x6506) }, /* CYUSB331x 2.0 HUB */
{ USB_DEVICE(VENDOR_ID_CYPRESS, 0x6507) }, /* CYUSB332x 2.0 HUB, Vendor Mode */
{ USB_DEVICE(VENDOR_ID_CYPRESS, 0x6508) }, /* CYUSB332x 3.0 HUB */
{ USB_DEVICE(VENDOR_ID_CYPRESS, 0x650a) }, /* CYUSB332x 2.0 HUB */
{ USB_DEVICE(VENDOR_ID_CYPRESS, 0x6570) }, /* CY7C6563x 2.0 HUB */ { USB_DEVICE(VENDOR_ID_CYPRESS, 0x6570) }, /* CY7C6563x 2.0 HUB */
{ USB_DEVICE(VENDOR_ID_GENESYS, 0x0608) }, /* Genesys Logic GL850G USB 2.0 HUB */ { USB_DEVICE(VENDOR_ID_GENESYS, 0x0608) }, /* Genesys Logic GL850G USB 2.0 HUB */
{ USB_DEVICE(VENDOR_ID_GENESYS, 0x0610) }, /* Genesys Logic GL852G USB 2.0 HUB */ { USB_DEVICE(VENDOR_ID_GENESYS, 0x0610) }, /* Genesys Logic GL852G USB 2.0 HUB */
+1 -1
View File
@@ -5964,7 +5964,7 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
case SNK_TRY_WAIT_DEBOUNCE: case SNK_TRY_WAIT_DEBOUNCE:
if (!tcpm_port_is_sink(port)) { if (!tcpm_port_is_sink(port)) {
port->max_wait = 0; port->max_wait = 0;
tcpm_set_state(port, SRC_TRYWAIT, 0); tcpm_set_state(port, SRC_TRYWAIT, PD_T_PD_DEBOUNCE);
} }
break; break;
case SRC_TRY_WAIT: case SRC_TRY_WAIT:
+2
View File
@@ -296,6 +296,8 @@ void ucsi_displayport_remove_partner(struct typec_altmode *alt)
if (!dp) if (!dp)
return; return;
cancel_work_sync(&dp->work);
dp->data.conf = 0; dp->data.conf = 0;
dp->data.status = 0; dp->data.status = 0;
dp->initialized = false; dp->initialized = false;
+2 -1
View File
@@ -115,8 +115,9 @@ typedef u64 u_int64_t;
typedef s64 int64_t; typedef s64 int64_t;
#endif #endif
/* this is a special 64bit data type that is 8-byte aligned */ /* These are the special 64-bit data types that are 8-byte aligned */
#define aligned_u64 __aligned_u64 #define aligned_u64 __aligned_u64
#define aligned_s64 __aligned_s64
#define aligned_be64 __aligned_be64 #define aligned_be64 __aligned_be64
#define aligned_le64 __aligned_le64 #define aligned_le64 __aligned_le64
+1
View File
@@ -53,6 +53,7 @@ typedef __u32 __bitwise __wsum;
* No conversions are necessary between 32-bit user-space and a 64-bit kernel. * No conversions are necessary between 32-bit user-space and a 64-bit kernel.
*/ */
#define __aligned_u64 __u64 __attribute__((aligned(8))) #define __aligned_u64 __u64 __attribute__((aligned(8)))
#define __aligned_s64 __s64 __attribute__((aligned(8)))
#define __aligned_be64 __be64 __attribute__((aligned(8))) #define __aligned_be64 __be64 __attribute__((aligned(8)))
#define __aligned_le64 __le64 __attribute__((aligned(8))) #define __aligned_le64 __le64 __attribute__((aligned(8)))