Skip to content

Commit 469a2f5

Browse files
committed
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
2 parents 43972cf + f48585c commit 469a2f5

File tree

10 files changed

+79
-14
lines changed

10 files changed

+79
-14
lines changed

drivers/thunderbolt/tb.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1964,6 +1964,8 @@ static void tb_handle_dp_bandwidth_request(struct work_struct *work)
19641964

19651965
pm_runtime_mark_last_busy(&tb->dev);
19661966
pm_runtime_put_autosuspend(&tb->dev);
1967+
1968+
kfree(ev);
19671969
}
19681970

19691971
static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 port)

drivers/thunderbolt/tmu.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,9 @@ int tb_switch_tmu_disable(struct tb_switch *sw)
579579
* uni-directional mode and we don't want to change it's TMU
580580
* mode.
581581
*/
582-
tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_OFF]);
582+
ret = tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_OFF]);
583+
if (ret)
584+
return ret;
583585

584586
tb_port_tmu_time_sync_disable(up);
585587
ret = tb_port_tmu_time_sync_disable(down);

drivers/usb/common/usb-conn-gpio.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct usb_conn_info {
4242

4343
struct power_supply_desc desc;
4444
struct power_supply *charger;
45+
bool initial_detection;
4546
};
4647

4748
/*
@@ -86,11 +87,13 @@ static void usb_conn_detect_cable(struct work_struct *work)
8687
dev_dbg(info->dev, "role %s -> %s, gpios: id %d, vbus %d\n",
8788
usb_role_string(info->last_role), usb_role_string(role), id, vbus);
8889

89-
if (info->last_role == role) {
90+
if (!info->initial_detection && info->last_role == role) {
9091
dev_warn(info->dev, "repeated role: %s\n", usb_role_string(role));
9192
return;
9293
}
9394

95+
info->initial_detection = false;
96+
9497
if (info->last_role == USB_ROLE_HOST && info->vbus)
9598
regulator_disable(info->vbus);
9699

@@ -258,6 +261,7 @@ static int usb_conn_probe(struct platform_device *pdev)
258261
device_set_wakeup_capable(&pdev->dev, true);
259262

260263
/* Perform initial detection */
264+
info->initial_detection = true;
261265
usb_conn_queue_dwork(info, 0);
262266

263267
return 0;

drivers/usb/dwc3/gadget.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4455,9 +4455,14 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
44554455
u32 count;
44564456

44574457
if (pm_runtime_suspended(dwc->dev)) {
4458+
dwc->pending_events = true;
4459+
/*
4460+
* Trigger runtime resume. The get() function will be balanced
4461+
* after processing the pending events in dwc3_process_pending
4462+
* events().
4463+
*/
44584464
pm_runtime_get(dwc->dev);
44594465
disable_irq_nosync(dwc->irq_gadget);
4460-
dwc->pending_events = true;
44614466
return IRQ_HANDLED;
44624467
}
44634468

@@ -4718,6 +4723,8 @@ void dwc3_gadget_process_pending_events(struct dwc3 *dwc)
47184723
{
47194724
if (dwc->pending_events) {
47204725
dwc3_interrupt(dwc->irq_gadget, dwc->ev_buf);
4726+
dwc3_thread_interrupt(dwc->irq_gadget, dwc->ev_buf);
4727+
pm_runtime_put(dwc->dev);
47214728
dwc->pending_events = false;
47224729
enable_irq(dwc->irq_gadget);
47234730
}

drivers/usb/gadget/udc/core.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_disconnect);
822822
* usb_gadget_activate() is called. For example, user mode components may
823823
* need to be activated before the system can talk to hosts.
824824
*
825+
* This routine may sleep; it must not be called in interrupt context
826+
* (such as from within a gadget driver's disconnect() callback).
827+
*
825828
* Returns zero on success, else negative errno.
826829
*/
827830
int usb_gadget_deactivate(struct usb_gadget *gadget)
@@ -860,6 +863,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_deactivate);
860863
* This routine activates gadget which was previously deactivated with
861864
* usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed.
862865
*
866+
* This routine may sleep; it must not be called in interrupt context.
867+
*
863868
* Returns zero on success, else negative errno.
864869
*/
865870
int usb_gadget_activate(struct usb_gadget *gadget)
@@ -1638,7 +1643,11 @@ static void gadget_unbind_driver(struct device *dev)
16381643
usb_gadget_disable_async_callbacks(udc);
16391644
if (gadget->irq)
16401645
synchronize_irq(gadget->irq);
1646+
mutex_unlock(&udc->connect_lock);
1647+
16411648
udc->driver->unbind(gadget);
1649+
1650+
mutex_lock(&udc->connect_lock);
16421651
usb_gadget_udc_stop_locked(udc);
16431652
mutex_unlock(&udc->connect_lock);
16441653

drivers/usb/storage/alauda.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ static int alauda_get_media_status(struct us_data *us, unsigned char *data)
318318
rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
319319
command, 0xc0, 0, 1, data, 2);
320320

321-
usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
321+
if (rc == USB_STOR_XFER_GOOD)
322+
usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
322323

323324
return rc;
324325
}
@@ -454,9 +455,14 @@ static int alauda_init_media(struct us_data *us)
454455
static int alauda_check_media(struct us_data *us)
455456
{
456457
struct alauda_info *info = (struct alauda_info *) us->extra;
457-
unsigned char status[2];
458+
unsigned char *status = us->iobuf;
459+
int rc;
458460

459-
alauda_get_media_status(us, status);
461+
rc = alauda_get_media_status(us, status);
462+
if (rc != USB_STOR_XFER_GOOD) {
463+
status[0] = 0xF0; /* Pretend there's no media */
464+
status[1] = 0;
465+
}
460466

461467
/* Check for no media or door open */
462468
if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)

drivers/usb/typec/altmodes/displayport.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct dp_altmode {
6060

6161
enum dp_state state;
6262
bool hpd;
63+
bool pending_hpd;
6364

6465
struct mutex lock; /* device lock */
6566
struct work_struct work;
@@ -144,8 +145,13 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
144145
dp->state = DP_STATE_EXIT;
145146
} else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) {
146147
ret = dp_altmode_configure(dp, con);
147-
if (!ret)
148+
if (!ret) {
148149
dp->state = DP_STATE_CONFIGURE;
150+
if (dp->hpd != hpd) {
151+
dp->hpd = hpd;
152+
dp->pending_hpd = true;
153+
}
154+
}
149155
} else {
150156
if (dp->hpd != hpd) {
151157
drm_connector_oob_hotplug_event(dp->connector_fwnode);
@@ -161,6 +167,16 @@ static int dp_altmode_configured(struct dp_altmode *dp)
161167
{
162168
sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration");
163169
sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment");
170+
/*
171+
* If the DFP_D/UFP_D sends a change in HPD when first notifying the
172+
* DisplayPort driver that it is connected, then we wait until
173+
* configuration is complete to signal HPD.
174+
*/
175+
if (dp->pending_hpd) {
176+
drm_connector_oob_hotplug_event(dp->connector_fwnode);
177+
sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd");
178+
dp->pending_hpd = false;
179+
}
164180

165181
return dp_altmode_notify(dp);
166182
}

drivers/usb/typec/mux/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ config TYPEC_MUX_INTEL_PMC
2929
tristate "Intel PMC mux control"
3030
depends on ACPI
3131
depends on INTEL_SCU_IPC
32+
select USB_COMMON
3233
select USB_ROLE_SWITCH
3334
help
3435
Driver for USB muxes controlled by Intel PMC FW. Intel PMC FW can

drivers/usb/typec/mux/nb7vpq904m.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -463,29 +463,40 @@ static int nb7vpq904m_probe(struct i2c_client *client)
463463

464464
ret = nb7vpq904m_register_bridge(nb7);
465465
if (ret)
466-
return ret;
466+
goto err_disable_gpio;
467467

468468
sw_desc.drvdata = nb7;
469469
sw_desc.fwnode = dev->fwnode;
470470
sw_desc.set = nb7vpq904m_sw_set;
471471

472472
nb7->sw = typec_switch_register(dev, &sw_desc);
473-
if (IS_ERR(nb7->sw))
474-
return dev_err_probe(dev, PTR_ERR(nb7->sw),
475-
"Error registering typec switch\n");
473+
if (IS_ERR(nb7->sw)) {
474+
ret = dev_err_probe(dev, PTR_ERR(nb7->sw),
475+
"Error registering typec switch\n");
476+
goto err_disable_gpio;
477+
}
476478

477479
retimer_desc.drvdata = nb7;
478480
retimer_desc.fwnode = dev->fwnode;
479481
retimer_desc.set = nb7vpq904m_retimer_set;
480482

481483
nb7->retimer = typec_retimer_register(dev, &retimer_desc);
482484
if (IS_ERR(nb7->retimer)) {
483-
typec_switch_unregister(nb7->sw);
484-
return dev_err_probe(dev, PTR_ERR(nb7->retimer),
485-
"Error registering typec retimer\n");
485+
ret = dev_err_probe(dev, PTR_ERR(nb7->retimer),
486+
"Error registering typec retimer\n");
487+
goto err_switch_unregister;
486488
}
487489

488490
return 0;
491+
492+
err_switch_unregister:
493+
typec_switch_unregister(nb7->sw);
494+
495+
err_disable_gpio:
496+
gpiod_set_value(nb7->enable_gpio, 0);
497+
regulator_disable(nb7->vcc_supply);
498+
499+
return ret;
489500
}
490501

491502
static void nb7vpq904m_remove(struct i2c_client *client)

drivers/usb/typec/tcpm/tcpm.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5349,6 +5349,10 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
53495349
/* Do nothing, vbus drop expected */
53505350
break;
53515351

5352+
case SNK_HARD_RESET_WAIT_VBUS:
5353+
/* Do nothing, its OK to receive vbus off events */
5354+
break;
5355+
53525356
default:
53535357
if (port->pwr_role == TYPEC_SINK && port->attached)
53545358
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)
53955399
case SNK_DEBOUNCED:
53965400
/*Do nothing, still waiting for VSAFE5V for connect */
53975401
break;
5402+
case SNK_HARD_RESET_WAIT_VBUS:
5403+
/* Do nothing, its OK to receive vbus off events */
5404+
break;
53985405
default:
53995406
if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
54005407
tcpm_set_state(port, SNK_UNATTACHED, 0);

0 commit comments

Comments
 (0)