Commit 469a2f50 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull USB / Thunderbolt driver fixes from Greg KH:
 "Here are some small USB and Thunderbolt driver fixes for reported
  problems. Included in here are:

   - thunderbolt driver memory leak fix

   - thunderbolt display flicker fix

   - usb dwc3 driver fix

   - usb gadget uvc disconnect crash fix

   - usb typec Kconfig build dependency fix

   - usb typec small fixes

   - usb-con-gpio bugfix

   - usb-storage old driver bugfix

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'usb-6.5-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  thunderbolt: Fix memory leak in tb_handle_dp_bandwidth_request()
  usb: dwc3: Properly handle processing of pending events
  usb-storage: alauda: Fix uninit-value in alauda_check_media()
  usb: common: usb-conn-gpio: Prevent bailing out if initial role is none
  USB: Gadget: core: Help prevent panic during UVC unconfigure
  usb: typec: mux: intel: Add dependency on USB_COMMON
  usb: typec: nb7vpq904m: Add an error handling path in nb7vpq904m_probe()
  usb: typec: altmodes/displayport: Signal hpd when configuring pin assignment
  usb: typec: tcpm: Fix response to vsafe0V event
  thunderbolt: Fix Thunderbolt 3 display flickering issue on 2nd hot plug onwards
parents 43972cf2 f48585c4
...@@ -1964,6 +1964,8 @@ static void tb_handle_dp_bandwidth_request(struct work_struct *work) ...@@ -1964,6 +1964,8 @@ static void tb_handle_dp_bandwidth_request(struct work_struct *work)
pm_runtime_mark_last_busy(&tb->dev); pm_runtime_mark_last_busy(&tb->dev);
pm_runtime_put_autosuspend(&tb->dev); pm_runtime_put_autosuspend(&tb->dev);
kfree(ev);
} }
static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 port) static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 port)
......
...@@ -579,7 +579,9 @@ int tb_switch_tmu_disable(struct tb_switch *sw) ...@@ -579,7 +579,9 @@ int tb_switch_tmu_disable(struct tb_switch *sw)
* uni-directional mode and we don't want to change it's TMU * uni-directional mode and we don't want to change it's TMU
* mode. * mode.
*/ */
tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_OFF]); ret = tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_OFF]);
if (ret)
return ret;
tb_port_tmu_time_sync_disable(up); tb_port_tmu_time_sync_disable(up);
ret = tb_port_tmu_time_sync_disable(down); ret = tb_port_tmu_time_sync_disable(down);
......
...@@ -42,6 +42,7 @@ struct usb_conn_info { ...@@ -42,6 +42,7 @@ struct usb_conn_info {
struct power_supply_desc desc; struct power_supply_desc desc;
struct power_supply *charger; struct power_supply *charger;
bool initial_detection;
}; };
/* /*
...@@ -86,11 +87,13 @@ static void usb_conn_detect_cable(struct work_struct *work) ...@@ -86,11 +87,13 @@ static void usb_conn_detect_cable(struct work_struct *work)
dev_dbg(info->dev, "role %s -> %s, gpios: id %d, vbus %d\n", dev_dbg(info->dev, "role %s -> %s, gpios: id %d, vbus %d\n",
usb_role_string(info->last_role), usb_role_string(role), id, vbus); usb_role_string(info->last_role), usb_role_string(role), id, vbus);
if (info->last_role == role) { if (!info->initial_detection && info->last_role == role) {
dev_warn(info->dev, "repeated role: %s\n", usb_role_string(role)); dev_warn(info->dev, "repeated role: %s\n", usb_role_string(role));
return; return;
} }
info->initial_detection = false;
if (info->last_role == USB_ROLE_HOST && info->vbus) if (info->last_role == USB_ROLE_HOST && info->vbus)
regulator_disable(info->vbus); regulator_disable(info->vbus);
...@@ -258,6 +261,7 @@ static int usb_conn_probe(struct platform_device *pdev) ...@@ -258,6 +261,7 @@ static int usb_conn_probe(struct platform_device *pdev)
device_set_wakeup_capable(&pdev->dev, true); device_set_wakeup_capable(&pdev->dev, true);
/* Perform initial detection */ /* Perform initial detection */
info->initial_detection = true;
usb_conn_queue_dwork(info, 0); usb_conn_queue_dwork(info, 0);
return 0; return 0;
......
...@@ -4455,9 +4455,14 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) ...@@ -4455,9 +4455,14 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
u32 count; u32 count;
if (pm_runtime_suspended(dwc->dev)) { if (pm_runtime_suspended(dwc->dev)) {
dwc->pending_events = true;
/*
* Trigger runtime resume. The get() function will be balanced
* after processing the pending events in dwc3_process_pending
* events().
*/
pm_runtime_get(dwc->dev); pm_runtime_get(dwc->dev);
disable_irq_nosync(dwc->irq_gadget); disable_irq_nosync(dwc->irq_gadget);
dwc->pending_events = true;
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -4718,6 +4723,8 @@ void dwc3_gadget_process_pending_events(struct dwc3 *dwc) ...@@ -4718,6 +4723,8 @@ void dwc3_gadget_process_pending_events(struct dwc3 *dwc)
{ {
if (dwc->pending_events) { if (dwc->pending_events) {
dwc3_interrupt(dwc->irq_gadget, dwc->ev_buf); dwc3_interrupt(dwc->irq_gadget, dwc->ev_buf);
dwc3_thread_interrupt(dwc->irq_gadget, dwc->ev_buf);
pm_runtime_put(dwc->dev);
dwc->pending_events = false; dwc->pending_events = false;
enable_irq(dwc->irq_gadget); enable_irq(dwc->irq_gadget);
} }
......
...@@ -822,6 +822,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_disconnect); ...@@ -822,6 +822,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_disconnect);
* usb_gadget_activate() is called. For example, user mode components may * usb_gadget_activate() is called. For example, user mode components may
* need to be activated before the system can talk to hosts. * need to be activated before the system can talk to hosts.
* *
* This routine may sleep; it must not be called in interrupt context
* (such as from within a gadget driver's disconnect() callback).
*
* Returns zero on success, else negative errno. * Returns zero on success, else negative errno.
*/ */
int usb_gadget_deactivate(struct usb_gadget *gadget) int usb_gadget_deactivate(struct usb_gadget *gadget)
...@@ -860,6 +863,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_deactivate); ...@@ -860,6 +863,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_deactivate);
* This routine activates gadget which was previously deactivated with * This routine activates gadget which was previously deactivated with
* usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed. * usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed.
* *
* This routine may sleep; it must not be called in interrupt context.
*
* Returns zero on success, else negative errno. * Returns zero on success, else negative errno.
*/ */
int usb_gadget_activate(struct usb_gadget *gadget) int usb_gadget_activate(struct usb_gadget *gadget)
...@@ -1638,7 +1643,11 @@ static void gadget_unbind_driver(struct device *dev) ...@@ -1638,7 +1643,11 @@ static void gadget_unbind_driver(struct device *dev)
usb_gadget_disable_async_callbacks(udc); usb_gadget_disable_async_callbacks(udc);
if (gadget->irq) if (gadget->irq)
synchronize_irq(gadget->irq); synchronize_irq(gadget->irq);
mutex_unlock(&udc->connect_lock);
udc->driver->unbind(gadget); udc->driver->unbind(gadget);
mutex_lock(&udc->connect_lock);
usb_gadget_udc_stop_locked(udc); usb_gadget_udc_stop_locked(udc);
mutex_unlock(&udc->connect_lock); mutex_unlock(&udc->connect_lock);
......
...@@ -318,6 +318,7 @@ static int alauda_get_media_status(struct us_data *us, unsigned char *data) ...@@ -318,6 +318,7 @@ static int alauda_get_media_status(struct us_data *us, unsigned char *data)
rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe, rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
command, 0xc0, 0, 1, data, 2); command, 0xc0, 0, 1, data, 2);
if (rc == USB_STOR_XFER_GOOD)
usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]); usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
return rc; return rc;
...@@ -454,9 +455,14 @@ static int alauda_init_media(struct us_data *us) ...@@ -454,9 +455,14 @@ static int alauda_init_media(struct us_data *us)
static int alauda_check_media(struct us_data *us) static int alauda_check_media(struct us_data *us)
{ {
struct alauda_info *info = (struct alauda_info *) us->extra; struct alauda_info *info = (struct alauda_info *) us->extra;
unsigned char status[2]; unsigned char *status = us->iobuf;
int rc;
alauda_get_media_status(us, status); rc = alauda_get_media_status(us, status);
if (rc != USB_STOR_XFER_GOOD) {
status[0] = 0xF0; /* Pretend there's no media */
status[1] = 0;
}
/* Check for no media or door open */ /* Check for no media or door open */
if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10) if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)
......
...@@ -60,6 +60,7 @@ struct dp_altmode { ...@@ -60,6 +60,7 @@ struct dp_altmode {
enum dp_state state; enum dp_state state;
bool hpd; bool hpd;
bool pending_hpd;
struct mutex lock; /* device lock */ struct mutex lock; /* device lock */
struct work_struct work; struct work_struct work;
...@@ -144,8 +145,13 @@ static int dp_altmode_status_update(struct dp_altmode *dp) ...@@ -144,8 +145,13 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
dp->state = DP_STATE_EXIT; dp->state = DP_STATE_EXIT;
} else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) { } else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) {
ret = dp_altmode_configure(dp, con); ret = dp_altmode_configure(dp, con);
if (!ret) if (!ret) {
dp->state = DP_STATE_CONFIGURE; dp->state = DP_STATE_CONFIGURE;
if (dp->hpd != hpd) {
dp->hpd = hpd;
dp->pending_hpd = true;
}
}
} else { } else {
if (dp->hpd != hpd) { if (dp->hpd != hpd) {
drm_connector_oob_hotplug_event(dp->connector_fwnode); drm_connector_oob_hotplug_event(dp->connector_fwnode);
...@@ -161,6 +167,16 @@ static int dp_altmode_configured(struct dp_altmode *dp) ...@@ -161,6 +167,16 @@ static int dp_altmode_configured(struct dp_altmode *dp)
{ {
sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration"); sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration");
sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment"); sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment");
/*
* If the DFP_D/UFP_D sends a change in HPD when first notifying the
* DisplayPort driver that it is connected, then we wait until
* configuration is complete to signal HPD.
*/
if (dp->pending_hpd) {
drm_connector_oob_hotplug_event(dp->connector_fwnode);
sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd");
dp->pending_hpd = false;
}
return dp_altmode_notify(dp); return dp_altmode_notify(dp);
} }
......
...@@ -29,6 +29,7 @@ config TYPEC_MUX_INTEL_PMC ...@@ -29,6 +29,7 @@ config TYPEC_MUX_INTEL_PMC
tristate "Intel PMC mux control" tristate "Intel PMC mux control"
depends on ACPI depends on ACPI
depends on INTEL_SCU_IPC depends on INTEL_SCU_IPC
select USB_COMMON
select USB_ROLE_SWITCH select USB_ROLE_SWITCH
help help
Driver for USB muxes controlled by Intel PMC FW. Intel PMC FW can Driver for USB muxes controlled by Intel PMC FW. Intel PMC FW can
......
...@@ -463,16 +463,18 @@ static int nb7vpq904m_probe(struct i2c_client *client) ...@@ -463,16 +463,18 @@ static int nb7vpq904m_probe(struct i2c_client *client)
ret = nb7vpq904m_register_bridge(nb7); ret = nb7vpq904m_register_bridge(nb7);
if (ret) if (ret)
return ret; goto err_disable_gpio;
sw_desc.drvdata = nb7; sw_desc.drvdata = nb7;
sw_desc.fwnode = dev->fwnode; sw_desc.fwnode = dev->fwnode;
sw_desc.set = nb7vpq904m_sw_set; sw_desc.set = nb7vpq904m_sw_set;
nb7->sw = typec_switch_register(dev, &sw_desc); nb7->sw = typec_switch_register(dev, &sw_desc);
if (IS_ERR(nb7->sw)) if (IS_ERR(nb7->sw)) {
return dev_err_probe(dev, PTR_ERR(nb7->sw), ret = dev_err_probe(dev, PTR_ERR(nb7->sw),
"Error registering typec switch\n"); "Error registering typec switch\n");
goto err_disable_gpio;
}
retimer_desc.drvdata = nb7; retimer_desc.drvdata = nb7;
retimer_desc.fwnode = dev->fwnode; retimer_desc.fwnode = dev->fwnode;
...@@ -480,12 +482,21 @@ static int nb7vpq904m_probe(struct i2c_client *client) ...@@ -480,12 +482,21 @@ static int nb7vpq904m_probe(struct i2c_client *client)
nb7->retimer = typec_retimer_register(dev, &retimer_desc); nb7->retimer = typec_retimer_register(dev, &retimer_desc);
if (IS_ERR(nb7->retimer)) { if (IS_ERR(nb7->retimer)) {
typec_switch_unregister(nb7->sw); ret = dev_err_probe(dev, PTR_ERR(nb7->retimer),
return dev_err_probe(dev, PTR_ERR(nb7->retimer),
"Error registering typec retimer\n"); "Error registering typec retimer\n");
goto err_switch_unregister;
} }
return 0; return 0;
err_switch_unregister:
typec_switch_unregister(nb7->sw);
err_disable_gpio:
gpiod_set_value(nb7->enable_gpio, 0);
regulator_disable(nb7->vcc_supply);
return ret;
} }
static void nb7vpq904m_remove(struct i2c_client *client) static void nb7vpq904m_remove(struct i2c_client *client)
......
...@@ -5349,6 +5349,10 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port) ...@@ -5349,6 +5349,10 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
/* Do nothing, vbus drop expected */ /* Do nothing, vbus drop expected */
break; break;
case SNK_HARD_RESET_WAIT_VBUS:
/* Do nothing, its OK to receive vbus off events */
break;
default: default:
if (port->pwr_role == TYPEC_SINK && port->attached) if (port->pwr_role == TYPEC_SINK && port->attached)
tcpm_set_state(port, SNK_UNATTACHED, tcpm_wait_for_discharge(port)); tcpm_set_state(port, SNK_UNATTACHED, tcpm_wait_for_discharge(port));
...@@ -5395,6 +5399,9 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port) ...@@ -5395,6 +5399,9 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
case SNK_DEBOUNCED: case SNK_DEBOUNCED:
/*Do nothing, still waiting for VSAFE5V for connect */ /*Do nothing, still waiting for VSAFE5V for connect */
break; break;
case SNK_HARD_RESET_WAIT_VBUS:
/* Do nothing, its OK to receive vbus off events */
break;
default: default:
if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled) if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
tcpm_set_state(port, SNK_UNATTACHED, 0); tcpm_set_state(port, SNK_UNATTACHED, 0);
......
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