USB/Thunderbolt driver fixes for 6.5-rc6
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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZNdb/g8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+yk09QCg0F3JgIt/upbSHkzTfuZhAhyyEQ4Ani3VN9QS gmrwM74YbefSpQFxkdzx =pnq0 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
469a2f5041
@ -1964,6 +1964,8 @@ unlock:
|
||||
|
||||
pm_runtime_mark_last_busy(&tb->dev);
|
||||
pm_runtime_put_autosuspend(&tb->dev);
|
||||
|
||||
kfree(ev);
|
||||
}
|
||||
|
||||
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)
|
||||
* uni-directional mode and we don't want to change it's TMU
|
||||
* 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);
|
||||
ret = tb_port_tmu_time_sync_disable(down);
|
||||
|
@ -42,6 +42,7 @@ struct usb_conn_info {
|
||||
|
||||
struct power_supply_desc desc;
|
||||
struct power_supply *charger;
|
||||
bool initial_detection;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -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",
|
||||
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));
|
||||
return;
|
||||
}
|
||||
|
||||
info->initial_detection = false;
|
||||
|
||||
if (info->last_role == USB_ROLE_HOST && info->vbus)
|
||||
regulator_disable(info->vbus);
|
||||
|
||||
@ -258,6 +261,7 @@ static int usb_conn_probe(struct platform_device *pdev)
|
||||
device_set_wakeup_capable(&pdev->dev, true);
|
||||
|
||||
/* Perform initial detection */
|
||||
info->initial_detection = true;
|
||||
usb_conn_queue_dwork(info, 0);
|
||||
|
||||
return 0;
|
||||
|
@ -4455,9 +4455,14 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
|
||||
u32 count;
|
||||
|
||||
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);
|
||||
disable_irq_nosync(dwc->irq_gadget);
|
||||
dwc->pending_events = true;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -4718,6 +4723,8 @@ void dwc3_gadget_process_pending_events(struct dwc3 *dwc)
|
||||
{
|
||||
if (dwc->pending_events) {
|
||||
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;
|
||||
enable_irq(dwc->irq_gadget);
|
||||
}
|
||||
|
@ -822,6 +822,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_disconnect);
|
||||
* usb_gadget_activate() is called. For example, user mode components may
|
||||
* 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.
|
||||
*/
|
||||
int usb_gadget_deactivate(struct usb_gadget *gadget)
|
||||
@ -860,6 +863,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_deactivate);
|
||||
* This routine activates gadget which was previously deactivated with
|
||||
* 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.
|
||||
*/
|
||||
int usb_gadget_activate(struct usb_gadget *gadget)
|
||||
@ -1638,7 +1643,11 @@ static void gadget_unbind_driver(struct device *dev)
|
||||
usb_gadget_disable_async_callbacks(udc);
|
||||
if (gadget->irq)
|
||||
synchronize_irq(gadget->irq);
|
||||
mutex_unlock(&udc->connect_lock);
|
||||
|
||||
udc->driver->unbind(gadget);
|
||||
|
||||
mutex_lock(&udc->connect_lock);
|
||||
usb_gadget_udc_stop_locked(udc);
|
||||
mutex_unlock(&udc->connect_lock);
|
||||
|
||||
|
@ -318,7 +318,8 @@ static int alauda_get_media_status(struct us_data *us, unsigned char *data)
|
||||
rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
|
||||
command, 0xc0, 0, 1, data, 2);
|
||||
|
||||
usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
|
||||
if (rc == USB_STOR_XFER_GOOD)
|
||||
usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -454,9 +455,14 @@ static int alauda_init_media(struct us_data *us)
|
||||
static int alauda_check_media(struct us_data *us)
|
||||
{
|
||||
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 */
|
||||
if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)
|
||||
|
@ -60,6 +60,7 @@ struct dp_altmode {
|
||||
|
||||
enum dp_state state;
|
||||
bool hpd;
|
||||
bool pending_hpd;
|
||||
|
||||
struct mutex lock; /* device lock */
|
||||
struct work_struct work;
|
||||
@ -144,8 +145,13 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
|
||||
dp->state = DP_STATE_EXIT;
|
||||
} else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) {
|
||||
ret = dp_altmode_configure(dp, con);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
dp->state = DP_STATE_CONFIGURE;
|
||||
if (dp->hpd != hpd) {
|
||||
dp->hpd = hpd;
|
||||
dp->pending_hpd = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (dp->hpd != hpd) {
|
||||
drm_connector_oob_hotplug_event(dp->connector_fwnode);
|
||||
@ -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", "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);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ config TYPEC_MUX_INTEL_PMC
|
||||
tristate "Intel PMC mux control"
|
||||
depends on ACPI
|
||||
depends on INTEL_SCU_IPC
|
||||
select USB_COMMON
|
||||
select USB_ROLE_SWITCH
|
||||
help
|
||||
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)
|
||||
|
||||
ret = nb7vpq904m_register_bridge(nb7);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_disable_gpio;
|
||||
|
||||
sw_desc.drvdata = nb7;
|
||||
sw_desc.fwnode = dev->fwnode;
|
||||
sw_desc.set = nb7vpq904m_sw_set;
|
||||
|
||||
nb7->sw = typec_switch_register(dev, &sw_desc);
|
||||
if (IS_ERR(nb7->sw))
|
||||
return dev_err_probe(dev, PTR_ERR(nb7->sw),
|
||||
"Error registering typec switch\n");
|
||||
if (IS_ERR(nb7->sw)) {
|
||||
ret = dev_err_probe(dev, PTR_ERR(nb7->sw),
|
||||
"Error registering typec switch\n");
|
||||
goto err_disable_gpio;
|
||||
}
|
||||
|
||||
retimer_desc.drvdata = nb7;
|
||||
retimer_desc.fwnode = dev->fwnode;
|
||||
@ -480,12 +482,21 @@ static int nb7vpq904m_probe(struct i2c_client *client)
|
||||
|
||||
nb7->retimer = typec_retimer_register(dev, &retimer_desc);
|
||||
if (IS_ERR(nb7->retimer)) {
|
||||
typec_switch_unregister(nb7->sw);
|
||||
return dev_err_probe(dev, PTR_ERR(nb7->retimer),
|
||||
"Error registering typec retimer\n");
|
||||
ret = dev_err_probe(dev, PTR_ERR(nb7->retimer),
|
||||
"Error registering typec retimer\n");
|
||||
goto err_switch_unregister;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -5349,6 +5349,10 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
|
||||
/* Do nothing, vbus drop expected */
|
||||
break;
|
||||
|
||||
case SNK_HARD_RESET_WAIT_VBUS:
|
||||
/* Do nothing, its OK to receive vbus off events */
|
||||
break;
|
||||
|
||||
default:
|
||||
if (port->pwr_role == TYPEC_SINK && port->attached)
|
||||
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)
|
||||
case SNK_DEBOUNCED:
|
||||
/*Do nothing, still waiting for VSAFE5V for connect */
|
||||
break;
|
||||
case SNK_HARD_RESET_WAIT_VBUS:
|
||||
/* Do nothing, its OK to receive vbus off events */
|
||||
break;
|
||||
default:
|
||||
if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
|
||||
tcpm_set_state(port, SNK_UNATTACHED, 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user