Commit 3001c355 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull USB and Thunderbolt driver fixes from Greg KH:
 "Here are some small Thunderbolt and USB driver fixes for some reported
  issues:

   - thunderbolt fixes for minor problems

   - typec fixes for power issues

   - usb-storage quirk addition

   - usbip bugfix

   - dwc3 bugfix when stopping transfers

   - cdnsp bugfix for isoc transfers

   - gadget use-after-free fix

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

* tag 'usb-5.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: typec: tcpm: Skip sink_cap query only when VDM sm is busy
  usb: dwc3: gadget: Prevent EP queuing while stopping transfers
  usb: typec: tcpm: Invoke power_supply_changed for tcpm-source-psy-
  usb: typec: Remove vdo[3] part of tps6598x_rx_identity_reg struct
  usb-storage: Add quirk to defeat Kindle's automatic unload
  usb: gadget: configfs: Fix KASAN use-after-free
  usbip: Fix incorrect double assignment to udc->ud.tcp_rx
  usb: cdnsp: Fixes incorrect value in ISOC TRB
  thunderbolt: Increase runtime PM reference count on DP tunnel discovery
  thunderbolt: Initialize HopID IDAs in tb_switch_alloc()
parents 5ee96fa9 2b8c956e
...@@ -768,12 +768,6 @@ static int tb_init_port(struct tb_port *port) ...@@ -768,12 +768,6 @@ static int tb_init_port(struct tb_port *port)
tb_dump_port(port->sw->tb, &port->config); tb_dump_port(port->sw->tb, &port->config);
/* Control port does not need HopID allocation */
if (port->port) {
ida_init(&port->in_hopids);
ida_init(&port->out_hopids);
}
INIT_LIST_HEAD(&port->list); INIT_LIST_HEAD(&port->list);
return 0; return 0;
...@@ -1842,10 +1836,8 @@ static void tb_switch_release(struct device *dev) ...@@ -1842,10 +1836,8 @@ static void tb_switch_release(struct device *dev)
dma_port_free(sw->dma_port); dma_port_free(sw->dma_port);
tb_switch_for_each_port(sw, port) { tb_switch_for_each_port(sw, port) {
if (!port->disabled) { ida_destroy(&port->in_hopids);
ida_destroy(&port->in_hopids); ida_destroy(&port->out_hopids);
ida_destroy(&port->out_hopids);
}
} }
kfree(sw->uuid); kfree(sw->uuid);
...@@ -2025,6 +2017,12 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, struct device *parent, ...@@ -2025,6 +2017,12 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, struct device *parent,
/* minimum setup for tb_find_cap and tb_drom_read to work */ /* minimum setup for tb_find_cap and tb_drom_read to work */
sw->ports[i].sw = sw; sw->ports[i].sw = sw;
sw->ports[i].port = i; sw->ports[i].port = i;
/* Control port does not need HopID allocation */
if (i) {
ida_init(&sw->ports[i].in_hopids);
ida_init(&sw->ports[i].out_hopids);
}
} }
ret = tb_switch_find_vse_cap(sw, TB_VSE_CAP_PLUG_EVENTS); ret = tb_switch_find_vse_cap(sw, TB_VSE_CAP_PLUG_EVENTS);
......
...@@ -138,6 +138,10 @@ static void tb_discover_tunnels(struct tb_switch *sw) ...@@ -138,6 +138,10 @@ static void tb_discover_tunnels(struct tb_switch *sw)
parent->boot = true; parent->boot = true;
parent = tb_switch_parent(parent); parent = tb_switch_parent(parent);
} }
} else if (tb_tunnel_is_dp(tunnel)) {
/* Keep the domain from powering down */
pm_runtime_get_sync(&tunnel->src_port->sw->dev);
pm_runtime_get_sync(&tunnel->dst_port->sw->dev);
} }
list_add_tail(&tunnel->list, &tcm->tunnel_list); list_add_tail(&tunnel->list, &tcm->tunnel_list);
......
...@@ -2197,7 +2197,10 @@ static int cdnsp_queue_isoc_tx(struct cdnsp_device *pdev, ...@@ -2197,7 +2197,10 @@ static int cdnsp_queue_isoc_tx(struct cdnsp_device *pdev,
* inverted in the first TDs isoc TRB. * inverted in the first TDs isoc TRB.
*/ */
field = TRB_TYPE(TRB_ISOC) | TRB_TLBPC(last_burst_pkt) | field = TRB_TYPE(TRB_ISOC) | TRB_TLBPC(last_burst_pkt) |
start_cycle ? 0 : 1 | TRB_SIA | TRB_TBC(burst_count); TRB_SIA | TRB_TBC(burst_count);
if (!start_cycle)
field |= TRB_CYCLE;
/* Fill the rest of the TRB fields, and remaining normal TRBs. */ /* Fill the rest of the TRB fields, and remaining normal TRBs. */
for (i = 0; i < trbs_per_td; i++) { for (i = 0; i < trbs_per_td; i++) {
......
...@@ -783,8 +783,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) ...@@ -783,8 +783,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
trace_dwc3_gadget_ep_disable(dep); trace_dwc3_gadget_ep_disable(dep);
dwc3_remove_requests(dwc, dep);
/* make sure HW endpoint isn't stalled */ /* make sure HW endpoint isn't stalled */
if (dep->flags & DWC3_EP_STALL) if (dep->flags & DWC3_EP_STALL)
__dwc3_gadget_ep_set_halt(dep, 0, false); __dwc3_gadget_ep_set_halt(dep, 0, false);
...@@ -803,6 +801,8 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) ...@@ -803,6 +801,8 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->endpoint.desc = NULL; dep->endpoint.desc = NULL;
} }
dwc3_remove_requests(dwc, dep);
return 0; return 0;
} }
...@@ -1617,7 +1617,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) ...@@ -1617,7 +1617,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
{ {
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
if (!dep->endpoint.desc || !dwc->pullups_connected) { if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) {
dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n", dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
dep->name); dep->name);
return -ESHUTDOWN; return -ESHUTDOWN;
...@@ -2247,6 +2247,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) ...@@ -2247,6 +2247,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
if (!is_on) { if (!is_on) {
u32 count; u32 count;
dwc->connected = false;
/* /*
* In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
* Section 4.1.8 Table 4-7, it states that for a device-initiated * Section 4.1.8 Table 4-7, it states that for a device-initiated
...@@ -2271,7 +2272,6 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) ...@@ -2271,7 +2272,6 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) % dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
dwc->ev_buf->length; dwc->ev_buf->length;
} }
dwc->connected = false;
} else { } else {
__dwc3_gadget_start(dwc); __dwc3_gadget_start(dwc);
} }
...@@ -3321,8 +3321,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) ...@@ -3321,8 +3321,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
{ {
u32 reg; u32 reg;
dwc->connected = true;
/* /*
* WORKAROUND: DWC3 revisions <1.88a have an issue which * WORKAROUND: DWC3 revisions <1.88a have an issue which
* would cause a missing Disconnect Event if there's a * would cause a missing Disconnect Event if there's a
...@@ -3362,6 +3360,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) ...@@ -3362,6 +3360,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
* transfers." * transfers."
*/ */
dwc3_stop_active_transfers(dwc); dwc3_stop_active_transfers(dwc);
dwc->connected = true;
reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg &= ~DWC3_DCTL_TSTCTRL_MASK; reg &= ~DWC3_DCTL_TSTCTRL_MASK;
......
...@@ -97,6 +97,8 @@ struct gadget_config_name { ...@@ -97,6 +97,8 @@ struct gadget_config_name {
struct list_head list; struct list_head list;
}; };
#define USB_MAX_STRING_WITH_NULL_LEN (USB_MAX_STRING_LEN+1)
static int usb_string_copy(const char *s, char **s_copy) static int usb_string_copy(const char *s, char **s_copy)
{ {
int ret; int ret;
...@@ -106,12 +108,16 @@ static int usb_string_copy(const char *s, char **s_copy) ...@@ -106,12 +108,16 @@ static int usb_string_copy(const char *s, char **s_copy)
if (ret > USB_MAX_STRING_LEN) if (ret > USB_MAX_STRING_LEN)
return -EOVERFLOW; return -EOVERFLOW;
str = kstrdup(s, GFP_KERNEL); if (copy) {
if (!str) str = copy;
return -ENOMEM; } else {
str = kmalloc(USB_MAX_STRING_WITH_NULL_LEN, GFP_KERNEL);
if (!str)
return -ENOMEM;
}
strcpy(str, s);
if (str[ret - 1] == '\n') if (str[ret - 1] == '\n')
str[ret - 1] = '\0'; str[ret - 1] = '\0';
kfree(copy);
*s_copy = str; *s_copy = str;
return 0; return 0;
} }
......
...@@ -656,6 +656,13 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) ...@@ -656,6 +656,13 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
need_auto_sense = 1; need_auto_sense = 1;
} }
/* Some devices (Kindle) require another command after SYNC CACHE */
if ((us->fflags & US_FL_SENSE_AFTER_SYNC) &&
srb->cmnd[0] == SYNCHRONIZE_CACHE) {
usb_stor_dbg(us, "-- sense after SYNC CACHE\n");
need_auto_sense = 1;
}
/* /*
* If we have a failure, we're going to do a REQUEST_SENSE * If we have a failure, we're going to do a REQUEST_SENSE
* automatically. Note that we differentiate between a command * automatically. Note that we differentiate between a command
......
...@@ -2211,6 +2211,18 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200, ...@@ -2211,6 +2211,18 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
USB_SC_DEVICE, USB_PR_DEVICE, NULL, USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_NO_READ_DISC_INFO ), US_FL_NO_READ_DISC_INFO ),
/*
* Reported by Matthias Schwarzott <zzam@gentoo.org>
* The Amazon Kindle treats SYNCHRONIZE CACHE as an indication that
* the host may be finished with it, and automatically ejects its
* emulated media unless it receives another command within one second.
*/
UNUSUAL_DEV( 0x1949, 0x0004, 0x0000, 0x9999,
"Amazon",
"Kindle",
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_SENSE_AFTER_SYNC ),
/* /*
* Reported by Oliver Neukum <oneukum@suse.com> * Reported by Oliver Neukum <oneukum@suse.com>
* This device morphes spontaneously into another device if the access * This device morphes spontaneously into another device if the access
......
...@@ -942,6 +942,7 @@ static int tcpm_set_current_limit(struct tcpm_port *port, u32 max_ma, u32 mv) ...@@ -942,6 +942,7 @@ static int tcpm_set_current_limit(struct tcpm_port *port, u32 max_ma, u32 mv)
port->supply_voltage = mv; port->supply_voltage = mv;
port->current_limit = max_ma; port->current_limit = max_ma;
power_supply_changed(port->psy);
if (port->tcpc->set_current_limit) if (port->tcpc->set_current_limit)
ret = port->tcpc->set_current_limit(port->tcpc, max_ma, mv); ret = port->tcpc->set_current_limit(port->tcpc, max_ma, mv);
...@@ -2928,6 +2929,7 @@ static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo, ...@@ -2928,6 +2929,7 @@ static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo,
port->pps_data.supported = false; port->pps_data.supported = false;
port->usb_type = POWER_SUPPLY_USB_TYPE_PD; port->usb_type = POWER_SUPPLY_USB_TYPE_PD;
power_supply_changed(port->psy);
/* /*
* Select the source PDO providing the most power which has a * Select the source PDO providing the most power which has a
...@@ -2952,6 +2954,7 @@ static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo, ...@@ -2952,6 +2954,7 @@ static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo,
port->pps_data.supported = true; port->pps_data.supported = true;
port->usb_type = port->usb_type =
POWER_SUPPLY_USB_TYPE_PD_PPS; POWER_SUPPLY_USB_TYPE_PD_PPS;
power_supply_changed(port->psy);
} }
continue; continue;
default: default:
...@@ -3109,6 +3112,7 @@ static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port) ...@@ -3109,6 +3112,7 @@ static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port)
port->pps_data.out_volt)); port->pps_data.out_volt));
port->pps_data.op_curr = min(port->pps_data.max_curr, port->pps_data.op_curr = min(port->pps_data.max_curr,
port->pps_data.op_curr); port->pps_data.op_curr);
power_supply_changed(port->psy);
} }
return src_pdo; return src_pdo;
...@@ -3344,6 +3348,7 @@ static int tcpm_set_charge(struct tcpm_port *port, bool charge) ...@@ -3344,6 +3348,7 @@ static int tcpm_set_charge(struct tcpm_port *port, bool charge)
return ret; return ret;
} }
port->vbus_charge = charge; port->vbus_charge = charge;
power_supply_changed(port->psy);
return 0; return 0;
} }
...@@ -3523,6 +3528,7 @@ static void tcpm_reset_port(struct tcpm_port *port) ...@@ -3523,6 +3528,7 @@ static void tcpm_reset_port(struct tcpm_port *port)
port->try_src_count = 0; port->try_src_count = 0;
port->try_snk_count = 0; port->try_snk_count = 0;
port->usb_type = POWER_SUPPLY_USB_TYPE_C; port->usb_type = POWER_SUPPLY_USB_TYPE_C;
power_supply_changed(port->psy);
port->nr_sink_caps = 0; port->nr_sink_caps = 0;
port->sink_cap_done = false; port->sink_cap_done = false;
if (port->tcpc->enable_frs) if (port->tcpc->enable_frs)
...@@ -5167,7 +5173,7 @@ static void tcpm_enable_frs_work(struct kthread_work *work) ...@@ -5167,7 +5173,7 @@ static void tcpm_enable_frs_work(struct kthread_work *work)
goto unlock; goto unlock;
/* Send when the state machine is idle */ /* Send when the state machine is idle */
if (port->state != SNK_READY || port->vdm_state != VDM_STATE_DONE || port->send_discover) if (port->state != SNK_READY || port->vdm_sm_running || port->send_discover)
goto resched; goto resched;
port->upcoming_state = GET_SINK_CAP; port->upcoming_state = GET_SINK_CAP;
...@@ -5905,7 +5911,7 @@ static int tcpm_psy_set_prop(struct power_supply *psy, ...@@ -5905,7 +5911,7 @@ static int tcpm_psy_set_prop(struct power_supply *psy,
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
power_supply_changed(port->psy);
return ret; return ret;
} }
...@@ -6058,6 +6064,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) ...@@ -6058,6 +6064,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
err = devm_tcpm_psy_register(port); err = devm_tcpm_psy_register(port);
if (err) if (err)
goto out_role_sw_put; goto out_role_sw_put;
power_supply_changed(port->psy);
port->typec_port = typec_register_port(port->dev, &port->typec_caps); port->typec_port = typec_register_port(port->dev, &port->typec_caps);
if (IS_ERR(port->typec_port)) { if (IS_ERR(port->typec_port)) {
......
...@@ -64,7 +64,6 @@ enum { ...@@ -64,7 +64,6 @@ enum {
struct tps6598x_rx_identity_reg { struct tps6598x_rx_identity_reg {
u8 status; u8 status;
struct usb_pd_identity identity; struct usb_pd_identity identity;
u32 vdo[3];
} __packed; } __packed;
/* Standard Task return codes */ /* Standard Task return codes */
......
...@@ -174,7 +174,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, ...@@ -174,7 +174,7 @@ static ssize_t usbip_sockfd_store(struct device *dev,
udc->ud.tcp_socket = socket; udc->ud.tcp_socket = socket;
udc->ud.tcp_rx = tcp_rx; udc->ud.tcp_rx = tcp_rx;
udc->ud.tcp_rx = tcp_tx; udc->ud.tcp_tx = tcp_tx;
udc->ud.status = SDEV_ST_USED; udc->ud.status = SDEV_ST_USED;
spin_unlock_irq(&udc->ud.lock); spin_unlock_irq(&udc->ud.lock);
......
...@@ -86,6 +86,8 @@ ...@@ -86,6 +86,8 @@
/* lies about caching, so always sync */ \ /* lies about caching, so always sync */ \
US_FLAG(NO_SAME, 0x40000000) \ US_FLAG(NO_SAME, 0x40000000) \
/* Cannot handle WRITE_SAME */ \ /* Cannot handle WRITE_SAME */ \
US_FLAG(SENSE_AFTER_SYNC, 0x80000000) \
/* Do REQUEST_SENSE after SYNCHRONIZE_CACHE */ \
#define US_FLAG(name, value) US_FL_##name = value , #define US_FLAG(name, value) US_FL_##name = value ,
enum { US_DO_ALL_FLAGS }; enum { US_DO_ALL_FLAGS };
......
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