Commit b68c1895 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-6.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB driver fixes from Greg KH:
 "Here are some small USB driver fixes and new device ids for 6.12-rc4:

   - xhci driver fixes for a number of reported issues

   - new usb-serial driver ids

   - dwc3 driver fixes for reported problems.

   - usb gadget driver fixes for reported problems

   - typec driver fixes

   - MAINTAINER file updates

  All of these have been in linux-next this week with no reported issues"

* tag 'usb-6.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  USB: serial: option: add Telit FN920C04 MBIM compositions
  USB: serial: option: add support for Quectel EG916Q-GL
  xhci: dbc: honor usb transfer size boundaries.
  usb: xhci: Fix handling errors mid TD followed by other errors
  xhci: Mitigate failed set dequeue pointer commands
  xhci: Fix incorrect stream context type macro
  USB: gadget: dummy-hcd: Fix "task hung" problem
  usb: gadget: f_uac2: fix return value for UAC2_ATTRIBUTE_STRING store
  usb: dwc3: core: Fix system suspend on TI AM62 platforms
  xhci: tegra: fix checked USB2 port number
  usb: dwc3: Wait for EndXfer completion before restoring GUSB2PHYCFG
  usb: typec: qcom-pmic-typec: fix sink status being overwritten with RP_DEF
  usb: typec: altmode should keep reference to parent
  MAINTAINERS: usb: raw-gadget: add bug tracker link
  MAINTAINERS: Add an entry for the LJCA drivers
parents db87114d 1154a599
...@@ -11604,6 +11604,16 @@ F: drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c ...@@ -11604,6 +11604,16 @@ F: drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c
F: drivers/crypto/intel/keembay/ocs-hcu.c F: drivers/crypto/intel/keembay/ocs-hcu.c
F: drivers/crypto/intel/keembay/ocs-hcu.h F: drivers/crypto/intel/keembay/ocs-hcu.h
INTEL LA JOLLA COVE ADAPTER (LJCA) USB I/O EXPANDER DRIVERS
M: Wentong Wu <wentong.wu@intel.com>
M: Sakari Ailus <sakari.ailus@linux.intel.com>
S: Maintained
F: drivers/gpio/gpio-ljca.c
F: drivers/i2c/busses/i2c-ljca.c
F: drivers/spi/spi-ljca.c
F: drivers/usb/misc/usb-ljca.c
F: include/linux/usb/ljca.h
INTEL MANAGEMENT ENGINE (mei) INTEL MANAGEMENT ENGINE (mei)
M: Tomas Winkler <tomas.winkler@intel.com> M: Tomas Winkler <tomas.winkler@intel.com>
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
...@@ -24078,6 +24088,7 @@ USB RAW GADGET DRIVER ...@@ -24078,6 +24088,7 @@ USB RAW GADGET DRIVER
R: Andrey Konovalov <andreyknvl@gmail.com> R: Andrey Konovalov <andreyknvl@gmail.com>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
S: Maintained S: Maintained
B: https://github.com/xairy/raw-gadget/issues
F: Documentation/usb/raw-gadget.rst F: Documentation/usb/raw-gadget.rst
F: drivers/usb/gadget/legacy/raw_gadget.c F: drivers/usb/gadget/legacy/raw_gadget.c
F: include/uapi/linux/usb/raw_gadget.h F: include/uapi/linux/usb/raw_gadget.h
......
...@@ -2342,6 +2342,11 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) ...@@ -2342,6 +2342,11 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
u32 reg; u32 reg;
int i; int i;
dwc->susphy_state = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) &
DWC3_GUSB2PHYCFG_SUSPHY) ||
(dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)) &
DWC3_GUSB3PIPECTL_SUSPHY);
switch (dwc->current_dr_role) { switch (dwc->current_dr_role) {
case DWC3_GCTL_PRTCAP_DEVICE: case DWC3_GCTL_PRTCAP_DEVICE:
if (pm_runtime_suspended(dwc->dev)) if (pm_runtime_suspended(dwc->dev))
...@@ -2393,6 +2398,15 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) ...@@ -2393,6 +2398,15 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
break; break;
} }
if (!PMSG_IS_AUTO(msg)) {
/*
* TI AM62 platform requires SUSPHY to be
* enabled for system suspend to work.
*/
if (!dwc->susphy_state)
dwc3_enable_susphy(dwc, true);
}
return 0; return 0;
} }
...@@ -2460,6 +2474,11 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) ...@@ -2460,6 +2474,11 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
break; break;
} }
if (!PMSG_IS_AUTO(msg)) {
/* restore SUSPHY state to that before system suspend. */
dwc3_enable_susphy(dwc, dwc->susphy_state);
}
return 0; return 0;
} }
......
...@@ -1150,6 +1150,8 @@ struct dwc3_scratchpad_array { ...@@ -1150,6 +1150,8 @@ struct dwc3_scratchpad_array {
* @sys_wakeup: set if the device may do system wakeup. * @sys_wakeup: set if the device may do system wakeup.
* @wakeup_configured: set if the device is configured for remote wakeup. * @wakeup_configured: set if the device is configured for remote wakeup.
* @suspended: set to track suspend event due to U3/L2. * @suspended: set to track suspend event due to U3/L2.
* @susphy_state: state of DWC3_GUSB2PHYCFG_SUSPHY + DWC3_GUSB3PIPECTL_SUSPHY
* before PM suspend.
* @imod_interval: set the interrupt moderation interval in 250ns * @imod_interval: set the interrupt moderation interval in 250ns
* increments or 0 to disable. * increments or 0 to disable.
* @max_cfg_eps: current max number of IN eps used across all USB configs. * @max_cfg_eps: current max number of IN eps used across all USB configs.
...@@ -1382,6 +1384,7 @@ struct dwc3 { ...@@ -1382,6 +1384,7 @@ struct dwc3 {
unsigned sys_wakeup:1; unsigned sys_wakeup:1;
unsigned wakeup_configured:1; unsigned wakeup_configured:1;
unsigned suspended:1; unsigned suspended:1;
unsigned susphy_state:1;
u16 imod_interval; u16 imod_interval;
......
...@@ -438,6 +438,10 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, ...@@ -438,6 +438,10 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
dwc3_gadget_ep_get_transfer_index(dep); dwc3_gadget_ep_get_transfer_index(dep);
} }
if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_ENDTRANSFER &&
!(cmd & DWC3_DEPCMD_CMDIOC))
mdelay(1);
if (saved_config) { if (saved_config) {
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
reg |= saved_config; reg |= saved_config;
...@@ -1715,12 +1719,10 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int ...@@ -1715,12 +1719,10 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int
WARN_ON_ONCE(ret); WARN_ON_ONCE(ret);
dep->resource_index = 0; dep->resource_index = 0;
if (!interrupt) { if (!interrupt)
mdelay(1);
dep->flags &= ~DWC3_EP_TRANSFER_STARTED; dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
} else if (!ret) { else if (!ret)
dep->flags |= DWC3_EP_END_TRANSFER_PENDING; dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
}
dep->flags &= ~DWC3_EP_DELAY_STOP; dep->flags &= ~DWC3_EP_DELAY_STOP;
return ret; return ret;
......
...@@ -2061,7 +2061,7 @@ static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ ...@@ -2061,7 +2061,7 @@ static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \
const char *page, size_t len) \ const char *page, size_t len) \
{ \ { \
struct f_uac2_opts *opts = to_f_uac2_opts(item); \ struct f_uac2_opts *opts = to_f_uac2_opts(item); \
int ret = 0; \ int ret = len; \
\ \
mutex_lock(&opts->lock); \ mutex_lock(&opts->lock); \
if (opts->refcnt) { \ if (opts->refcnt) { \
...@@ -2072,7 +2072,7 @@ static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ ...@@ -2072,7 +2072,7 @@ static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \
if (len && page[len - 1] == '\n') \ if (len && page[len - 1] == '\n') \
len--; \ len--; \
\ \
ret = scnprintf(opts->name, min(sizeof(opts->name), len + 1), \ scnprintf(opts->name, min(sizeof(opts->name), len + 1), \
"%s", page); \ "%s", page); \
\ \
end: \ end: \
......
...@@ -254,6 +254,7 @@ struct dummy_hcd { ...@@ -254,6 +254,7 @@ struct dummy_hcd {
u32 stream_en_ep; u32 stream_en_ep;
u8 num_stream[30 / 2]; u8 num_stream[30 / 2];
unsigned timer_pending:1;
unsigned active:1; unsigned active:1;
unsigned old_active:1; unsigned old_active:1;
unsigned resuming:1; unsigned resuming:1;
...@@ -1303,9 +1304,11 @@ static int dummy_urb_enqueue( ...@@ -1303,9 +1304,11 @@ static int dummy_urb_enqueue(
urb->error_count = 1; /* mark as a new urb */ urb->error_count = 1; /* mark as a new urb */
/* kick the scheduler, it'll do the rest */ /* kick the scheduler, it'll do the rest */
if (!hrtimer_active(&dum_hcd->timer)) if (!dum_hcd->timer_pending) {
dum_hcd->timer_pending = 1;
hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS),
HRTIMER_MODE_REL_SOFT); HRTIMER_MODE_REL_SOFT);
}
done: done:
spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
...@@ -1324,9 +1327,10 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -1324,9 +1327,10 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
spin_lock_irqsave(&dum_hcd->dum->lock, flags); spin_lock_irqsave(&dum_hcd->dum->lock, flags);
rc = usb_hcd_check_unlink_urb(hcd, urb, status); rc = usb_hcd_check_unlink_urb(hcd, urb, status);
if (!rc && dum_hcd->rh_state != DUMMY_RH_RUNNING && if (rc == 0 && !dum_hcd->timer_pending) {
!list_empty(&dum_hcd->urbp_list)) dum_hcd->timer_pending = 1;
hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT); hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT);
}
spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
return rc; return rc;
...@@ -1813,6 +1817,7 @@ static enum hrtimer_restart dummy_timer(struct hrtimer *t) ...@@ -1813,6 +1817,7 @@ static enum hrtimer_restart dummy_timer(struct hrtimer *t)
/* look at each urb queued by the host side driver */ /* look at each urb queued by the host side driver */
spin_lock_irqsave(&dum->lock, flags); spin_lock_irqsave(&dum->lock, flags);
dum_hcd->timer_pending = 0;
if (!dum_hcd->udev) { if (!dum_hcd->udev) {
dev_err(dummy_dev(dum_hcd), dev_err(dummy_dev(dum_hcd),
...@@ -1994,8 +1999,10 @@ static enum hrtimer_restart dummy_timer(struct hrtimer *t) ...@@ -1994,8 +1999,10 @@ static enum hrtimer_restart dummy_timer(struct hrtimer *t)
if (list_empty(&dum_hcd->urbp_list)) { if (list_empty(&dum_hcd->urbp_list)) {
usb_put_dev(dum_hcd->udev); usb_put_dev(dum_hcd->udev);
dum_hcd->udev = NULL; dum_hcd->udev = NULL;
} else if (dum_hcd->rh_state == DUMMY_RH_RUNNING) { } else if (!dum_hcd->timer_pending &&
dum_hcd->rh_state == DUMMY_RH_RUNNING) {
/* want a 1 msec delay here */ /* want a 1 msec delay here */
dum_hcd->timer_pending = 1;
hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS),
HRTIMER_MODE_REL_SOFT); HRTIMER_MODE_REL_SOFT);
} }
...@@ -2390,8 +2397,10 @@ static int dummy_bus_resume(struct usb_hcd *hcd) ...@@ -2390,8 +2397,10 @@ static int dummy_bus_resume(struct usb_hcd *hcd)
} else { } else {
dum_hcd->rh_state = DUMMY_RH_RUNNING; dum_hcd->rh_state = DUMMY_RH_RUNNING;
set_link_state(dum_hcd); set_link_state(dum_hcd);
if (!list_empty(&dum_hcd->urbp_list)) if (!list_empty(&dum_hcd->urbp_list)) {
dum_hcd->timer_pending = 1;
hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT); hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT);
}
hcd->state = HC_STATE_RUNNING; hcd->state = HC_STATE_RUNNING;
} }
spin_unlock_irq(&dum_hcd->dum->lock); spin_unlock_irq(&dum_hcd->dum->lock);
...@@ -2522,6 +2531,7 @@ static void dummy_stop(struct usb_hcd *hcd) ...@@ -2522,6 +2531,7 @@ static void dummy_stop(struct usb_hcd *hcd)
struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd); struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
hrtimer_cancel(&dum_hcd->timer); hrtimer_cancel(&dum_hcd->timer);
dum_hcd->timer_pending = 0;
device_remove_file(dummy_dev(dum_hcd), &dev_attr_urbs); device_remove_file(dummy_dev(dum_hcd), &dev_attr_urbs);
dev_info(dummy_dev(dum_hcd), "stopped\n"); dev_info(dummy_dev(dum_hcd), "stopped\n");
} }
......
...@@ -110,6 +110,7 @@ struct dbc_port { ...@@ -110,6 +110,7 @@ struct dbc_port {
struct tasklet_struct push; struct tasklet_struct push;
struct list_head write_pool; struct list_head write_pool;
unsigned int tx_boundary;
bool registered; bool registered;
}; };
......
...@@ -24,6 +24,29 @@ static inline struct dbc_port *dbc_to_port(struct xhci_dbc *dbc) ...@@ -24,6 +24,29 @@ static inline struct dbc_port *dbc_to_port(struct xhci_dbc *dbc)
return dbc->priv; return dbc->priv;
} }
static unsigned int
dbc_kfifo_to_req(struct dbc_port *port, char *packet)
{
unsigned int len;
len = kfifo_len(&port->port.xmit_fifo);
if (len == 0)
return 0;
len = min(len, DBC_MAX_PACKET);
if (port->tx_boundary)
len = min(port->tx_boundary, len);
len = kfifo_out(&port->port.xmit_fifo, packet, len);
if (port->tx_boundary)
port->tx_boundary -= len;
return len;
}
static int dbc_start_tx(struct dbc_port *port) static int dbc_start_tx(struct dbc_port *port)
__releases(&port->port_lock) __releases(&port->port_lock)
__acquires(&port->port_lock) __acquires(&port->port_lock)
...@@ -36,7 +59,7 @@ static int dbc_start_tx(struct dbc_port *port) ...@@ -36,7 +59,7 @@ static int dbc_start_tx(struct dbc_port *port)
while (!list_empty(pool)) { while (!list_empty(pool)) {
req = list_entry(pool->next, struct dbc_request, list_pool); req = list_entry(pool->next, struct dbc_request, list_pool);
len = kfifo_out(&port->port.xmit_fifo, req->buf, DBC_MAX_PACKET); len = dbc_kfifo_to_req(port, req->buf);
if (len == 0) if (len == 0)
break; break;
do_tty_wake = true; do_tty_wake = true;
...@@ -200,14 +223,32 @@ static ssize_t dbc_tty_write(struct tty_struct *tty, const u8 *buf, ...@@ -200,14 +223,32 @@ static ssize_t dbc_tty_write(struct tty_struct *tty, const u8 *buf,
{ {
struct dbc_port *port = tty->driver_data; struct dbc_port *port = tty->driver_data;
unsigned long flags; unsigned long flags;
unsigned int written = 0;
spin_lock_irqsave(&port->port_lock, flags); spin_lock_irqsave(&port->port_lock, flags);
if (count)
count = kfifo_in(&port->port.xmit_fifo, buf, count); /*
* Treat tty write as one usb transfer. Make sure the writes are turned
* into TRB request having the same size boundaries as the tty writes.
* Don't add data to kfifo before previous write is turned into TRBs
*/
if (port->tx_boundary) {
spin_unlock_irqrestore(&port->port_lock, flags);
return 0;
}
if (count) {
written = kfifo_in(&port->port.xmit_fifo, buf, count);
if (written == count)
port->tx_boundary = kfifo_len(&port->port.xmit_fifo);
dbc_start_tx(port); dbc_start_tx(port);
}
spin_unlock_irqrestore(&port->port_lock, flags); spin_unlock_irqrestore(&port->port_lock, flags);
return count; return written;
} }
static int dbc_tty_put_char(struct tty_struct *tty, u8 ch) static int dbc_tty_put_char(struct tty_struct *tty, u8 ch)
...@@ -241,6 +282,10 @@ static unsigned int dbc_tty_write_room(struct tty_struct *tty) ...@@ -241,6 +282,10 @@ static unsigned int dbc_tty_write_room(struct tty_struct *tty)
spin_lock_irqsave(&port->port_lock, flags); spin_lock_irqsave(&port->port_lock, flags);
room = kfifo_avail(&port->port.xmit_fifo); room = kfifo_avail(&port->port.xmit_fifo);
if (port->tx_boundary)
room = 0;
spin_unlock_irqrestore(&port->port_lock, flags); spin_unlock_irqrestore(&port->port_lock, flags);
return room; return room;
......
...@@ -1023,7 +1023,7 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep) ...@@ -1023,7 +1023,7 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
td_to_noop(xhci, ring, cached_td, false); td_to_noop(xhci, ring, cached_td, false);
cached_td->cancel_status = TD_CLEARED; cached_td->cancel_status = TD_CLEARED;
} }
td_to_noop(xhci, ring, td, false);
td->cancel_status = TD_CLEARING_CACHE; td->cancel_status = TD_CLEARING_CACHE;
cached_td = td; cached_td = td;
break; break;
...@@ -2775,6 +2775,29 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -2775,6 +2775,29 @@ static int handle_tx_event(struct xhci_hcd *xhci,
return 0; return 0;
} }
/*
* xhci 4.10.2 states isoc endpoints should continue
* processing the next TD if there was an error mid TD.
* So host like NEC don't generate an event for the last
* isoc TRB even if the IOC flag is set.
* xhci 4.9.1 states that if there are errors in mult-TRB
* TDs xHC should generate an error for that TRB, and if xHC
* proceeds to the next TD it should genete an event for
* any TRB with IOC flag on the way. Other host follow this.
*
* We wait for the final IOC event, but if we get an event
* anywhere outside this TD, just give it back already.
*/
td = list_first_entry_or_null(&ep_ring->td_list, struct xhci_td, td_list);
if (td && td->error_mid_td && !trb_in_td(xhci, td, ep_trb_dma, false)) {
xhci_dbg(xhci, "Missing TD completion event after mid TD error\n");
ep_ring->dequeue = td->last_trb;
ep_ring->deq_seg = td->last_trb_seg;
inc_deq(xhci, ep_ring);
xhci_td_cleanup(xhci, td, ep_ring, td->status);
}
if (list_empty(&ep_ring->td_list)) { if (list_empty(&ep_ring->td_list)) {
/* /*
* Don't print wanings if ring is empty due to a stopped endpoint generating an * Don't print wanings if ring is empty due to a stopped endpoint generating an
...@@ -2836,45 +2859,14 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -2836,45 +2859,14 @@ static int handle_tx_event(struct xhci_hcd *xhci,
return 0; return 0;
} }
/*
* xhci 4.10.2 states isoc endpoints should continue
* processing the next TD if there was an error mid TD.
* So host like NEC don't generate an event for the last
* isoc TRB even if the IOC flag is set.
* xhci 4.9.1 states that if there are errors in mult-TRB
* TDs xHC should generate an error for that TRB, and if xHC
* proceeds to the next TD it should genete an event for
* any TRB with IOC flag on the way. Other host follow this.
* So this event might be for the next TD.
*/
if (td->error_mid_td &&
!list_is_last(&td->td_list, &ep_ring->td_list)) {
struct xhci_td *td_next = list_next_entry(td, td_list);
ep_seg = trb_in_td(xhci, td_next, ep_trb_dma, false);
if (ep_seg) {
/* give back previous TD, start handling new */
xhci_dbg(xhci, "Missing TD completion event after mid TD error\n");
ep_ring->dequeue = td->last_trb;
ep_ring->deq_seg = td->last_trb_seg;
inc_deq(xhci, ep_ring);
xhci_td_cleanup(xhci, td, ep_ring, td->status);
td = td_next;
}
}
if (!ep_seg) {
/* HC is busted, give up! */ /* HC is busted, give up! */
xhci_err(xhci, xhci_err(xhci,
"ERROR Transfer event TRB DMA ptr not " "ERROR Transfer event TRB DMA ptr not part of current TD ep_index %d comp_code %u\n",
"part of current TD ep_index %d " ep_index, trb_comp_code);
"comp_code %u\n", ep_index,
trb_comp_code);
trb_in_td(xhci, td, ep_trb_dma, true); trb_in_td(xhci, td, ep_trb_dma, true);
return -ESHUTDOWN; return -ESHUTDOWN;
} }
}
if (ep->skip) { if (ep->skip) {
xhci_dbg(xhci, xhci_dbg(xhci,
......
...@@ -2183,7 +2183,7 @@ static int tegra_xusb_enter_elpg(struct tegra_xusb *tegra, bool runtime) ...@@ -2183,7 +2183,7 @@ static int tegra_xusb_enter_elpg(struct tegra_xusb *tegra, bool runtime)
goto out; goto out;
} }
for (i = 0; i < tegra->num_usb_phys; i++) { for (i = 0; i < xhci->usb2_rhub.num_ports; i++) {
if (!xhci->usb2_rhub.ports[i]) if (!xhci->usb2_rhub.ports[i])
continue; continue;
portsc = readl(xhci->usb2_rhub.ports[i]->addr); portsc = readl(xhci->usb2_rhub.ports[i]->addr);
......
...@@ -1001,7 +1001,7 @@ enum xhci_setup_dev { ...@@ -1001,7 +1001,7 @@ enum xhci_setup_dev {
/* Set TR Dequeue Pointer command TRB fields, 6.4.3.9 */ /* Set TR Dequeue Pointer command TRB fields, 6.4.3.9 */
#define TRB_TO_STREAM_ID(p) ((((p) & (0xffff << 16)) >> 16)) #define TRB_TO_STREAM_ID(p) ((((p) & (0xffff << 16)) >> 16))
#define STREAM_ID_FOR_TRB(p) ((((p)) & 0xffff) << 16) #define STREAM_ID_FOR_TRB(p) ((((p)) & 0xffff) << 16)
#define SCT_FOR_TRB(p) (((p) << 1) & 0x7) #define SCT_FOR_TRB(p) (((p) & 0x7) << 1)
/* Link TRB specific fields */ /* Link TRB specific fields */
#define TRB_TC (1<<1) #define TRB_TC (1<<1)
......
...@@ -279,6 +279,7 @@ static void option_instat_callback(struct urb *urb); ...@@ -279,6 +279,7 @@ static void option_instat_callback(struct urb *urb);
#define QUECTEL_PRODUCT_EG912Y 0x6001 #define QUECTEL_PRODUCT_EG912Y 0x6001
#define QUECTEL_PRODUCT_EC200S_CN 0x6002 #define QUECTEL_PRODUCT_EC200S_CN 0x6002
#define QUECTEL_PRODUCT_EC200A 0x6005 #define QUECTEL_PRODUCT_EC200A 0x6005
#define QUECTEL_PRODUCT_EG916Q 0x6007
#define QUECTEL_PRODUCT_EM061K_LWW 0x6008 #define QUECTEL_PRODUCT_EM061K_LWW 0x6008
#define QUECTEL_PRODUCT_EM061K_LCN 0x6009 #define QUECTEL_PRODUCT_EM061K_LCN 0x6009
#define QUECTEL_PRODUCT_EC200T 0x6026 #define QUECTEL_PRODUCT_EC200T 0x6026
...@@ -1270,6 +1271,7 @@ static const struct usb_device_id option_ids[] = { ...@@ -1270,6 +1271,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG912Y, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG912Y, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG916Q, 0xff, 0x00, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
...@@ -1380,10 +1382,16 @@ static const struct usb_device_id option_ids[] = { ...@@ -1380,10 +1382,16 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(0) | RSVD(1) }, .driver_info = NCTRL(0) | RSVD(1) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a0, 0xff), /* Telit FN20C04 (rmnet) */ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a0, 0xff), /* Telit FN20C04 (rmnet) */
.driver_info = RSVD(0) | NCTRL(3) }, .driver_info = RSVD(0) | NCTRL(3) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a2, 0xff), /* Telit FN920C04 (MBIM) */
.driver_info = NCTRL(4) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a4, 0xff), /* Telit FN20C04 (rmnet) */ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a4, 0xff), /* Telit FN20C04 (rmnet) */
.driver_info = RSVD(0) | NCTRL(3) }, .driver_info = RSVD(0) | NCTRL(3) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a7, 0xff), /* Telit FN920C04 (MBIM) */
.driver_info = NCTRL(4) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a9, 0xff), /* Telit FN20C04 (rmnet) */ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a9, 0xff), /* Telit FN20C04 (rmnet) */
.driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) }, .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10aa, 0xff), /* Telit FN920C04 (MBIM) */
.driver_info = NCTRL(3) | RSVD(4) | RSVD(5) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
......
...@@ -519,6 +519,7 @@ static void typec_altmode_release(struct device *dev) ...@@ -519,6 +519,7 @@ static void typec_altmode_release(struct device *dev)
typec_altmode_put_partner(alt); typec_altmode_put_partner(alt);
altmode_id_remove(alt->adev.dev.parent, alt->id); altmode_id_remove(alt->adev.dev.parent, alt->id);
put_device(alt->adev.dev.parent);
kfree(alt); kfree(alt);
} }
...@@ -568,6 +569,8 @@ typec_register_altmode(struct device *parent, ...@@ -568,6 +569,8 @@ typec_register_altmode(struct device *parent,
alt->adev.dev.type = &typec_altmode_dev_type; alt->adev.dev.type = &typec_altmode_dev_type;
dev_set_name(&alt->adev.dev, "%s.%u", dev_name(parent), id); dev_set_name(&alt->adev.dev, "%s.%u", dev_name(parent), id);
get_device(alt->adev.dev.parent);
/* Link partners and plugs with the ports */ /* Link partners and plugs with the ports */
if (!is_port) if (!is_port)
typec_altmode_set_partner(alt); typec_altmode_set_partner(alt);
......
...@@ -432,7 +432,6 @@ static int qcom_pmic_typec_port_get_cc(struct tcpc_dev *tcpc, ...@@ -432,7 +432,6 @@ static int qcom_pmic_typec_port_get_cc(struct tcpc_dev *tcpc,
val = TYPEC_CC_RP_DEF; val = TYPEC_CC_RP_DEF;
break; break;
} }
val = TYPEC_CC_RP_DEF;
} }
if (misc & CC_ORIENTATION) if (misc & CC_ORIENTATION)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment