diff options
Diffstat (limited to 'drivers/usb')
| -rw-r--r-- | drivers/usb/common/usb-conn-gpio.c | 6 | ||||
| -rw-r--r-- | drivers/usb/core/devio.c | 16 | ||||
| -rw-r--r-- | drivers/usb/dwc3/gadget.c | 9 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 3 | ||||
| -rw-r--r-- | drivers/usb/gadget/legacy/inode.c | 3 | ||||
| -rw-r--r-- | drivers/usb/gadget/udc/core.c | 9 | ||||
| -rw-r--r-- | drivers/usb/storage/alauda.c | 12 | ||||
| -rw-r--r-- | drivers/usb/typec/altmodes/displayport.c | 18 | ||||
| -rw-r--r-- | drivers/usb/typec/mux/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/usb/typec/mux/nb7vpq904m.c | 25 | ||||
| -rw-r--r-- | drivers/usb/typec/tcpm/tcpm.c | 7 | 
11 files changed, 84 insertions, 25 deletions
diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c index 766005d20bae..501e8bc9738e 100644 --- a/drivers/usb/common/usb-conn-gpio.c +++ b/drivers/usb/common/usb-conn-gpio.c @@ -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; diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 1a16a8bdea60..4f68f6ef3cc1 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -2642,21 +2642,21 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,  		snoop(&dev->dev, "%s: CONTROL\n", __func__);  		ret = proc_control(ps, p);  		if (ret >= 0) -			inode->i_mtime = inode->i_ctime = current_time(inode); +			inode->i_mtime = inode_set_ctime_current(inode);  		break;  	case USBDEVFS_BULK:  		snoop(&dev->dev, "%s: BULK\n", __func__);  		ret = proc_bulk(ps, p);  		if (ret >= 0) -			inode->i_mtime = inode->i_ctime = current_time(inode); +			inode->i_mtime = inode_set_ctime_current(inode);  		break;  	case USBDEVFS_RESETEP:  		snoop(&dev->dev, "%s: RESETEP\n", __func__);  		ret = proc_resetep(ps, p);  		if (ret >= 0) -			inode->i_mtime = inode->i_ctime = current_time(inode); +			inode->i_mtime = inode_set_ctime_current(inode);  		break;  	case USBDEVFS_RESET: @@ -2668,7 +2668,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,  		snoop(&dev->dev, "%s: CLEAR_HALT\n", __func__);  		ret = proc_clearhalt(ps, p);  		if (ret >= 0) -			inode->i_mtime = inode->i_ctime = current_time(inode); +			inode->i_mtime = inode_set_ctime_current(inode);  		break;  	case USBDEVFS_GETDRIVER: @@ -2695,7 +2695,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,  		snoop(&dev->dev, "%s: SUBMITURB\n", __func__);  		ret = proc_submiturb(ps, p);  		if (ret >= 0) -			inode->i_mtime = inode->i_ctime = current_time(inode); +			inode->i_mtime = inode_set_ctime_current(inode);  		break;  #ifdef CONFIG_COMPAT @@ -2703,14 +2703,14 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,  		snoop(&dev->dev, "%s: CONTROL32\n", __func__);  		ret = proc_control_compat(ps, p);  		if (ret >= 0) -			inode->i_mtime = inode->i_ctime = current_time(inode); +			inode->i_mtime = inode_set_ctime_current(inode);  		break;  	case USBDEVFS_BULK32:  		snoop(&dev->dev, "%s: BULK32\n", __func__);  		ret = proc_bulk_compat(ps, p);  		if (ret >= 0) -			inode->i_mtime = inode->i_ctime = current_time(inode); +			inode->i_mtime = inode_set_ctime_current(inode);  		break;  	case USBDEVFS_DISCSIGNAL32: @@ -2722,7 +2722,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,  		snoop(&dev->dev, "%s: SUBMITURB32\n", __func__);  		ret = proc_submiturb_compat(ps, p);  		if (ret >= 0) -			inode->i_mtime = inode->i_ctime = current_time(inode); +			inode->i_mtime = inode_set_ctime_current(inode);  		break;  	case USBDEVFS_IOCTL32: diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5fd067151fbf..858fe4c299b7 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -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);  	} diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index f41a385a5c42..6e9ef35a43a7 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1377,7 +1377,7 @@ ffs_sb_make_inode(struct super_block *sb, void *data,  	inode = new_inode(sb);  	if (inode) { -		struct timespec64 ts = current_time(inode); +		struct timespec64 ts = inode_set_ctime_current(inode);  		inode->i_ino	 = get_next_ino();  		inode->i_mode    = perms->mode; @@ -1385,7 +1385,6 @@ ffs_sb_make_inode(struct super_block *sb, void *data,  		inode->i_gid     = perms->gid;  		inode->i_atime   = ts;  		inode->i_mtime   = ts; -		inode->i_ctime   = ts;  		inode->i_private = data;  		if (fops)  			inode->i_fop = fops; diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 28249d0bf062..ce9e31f3d26b 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -1969,8 +1969,7 @@ gadgetfs_make_inode (struct super_block *sb,  		inode->i_mode = mode;  		inode->i_uid = make_kuid(&init_user_ns, default_uid);  		inode->i_gid = make_kgid(&init_user_ns, default_gid); -		inode->i_atime = inode->i_mtime = inode->i_ctime -				= current_time(inode); +		inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode);  		inode->i_private = data;  		inode->i_fop = fops;  	} diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index cd58f2a4e7f3..7d49d8a0b00c 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -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); diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index 5e912dd29b4c..115f05a6201a 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -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) diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 66de880b28d0..cdf8261e22db 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -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);  } diff --git a/drivers/usb/typec/mux/Kconfig b/drivers/usb/typec/mux/Kconfig index 784b9d8107e9..65da61150ba7 100644 --- a/drivers/usb/typec/mux/Kconfig +++ b/drivers/usb/typec/mux/Kconfig @@ -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 diff --git a/drivers/usb/typec/mux/nb7vpq904m.c b/drivers/usb/typec/mux/nb7vpq904m.c index 80e580d50129..4d1122d95013 100644 --- a/drivers/usb/typec/mux/nb7vpq904m.c +++ b/drivers/usb/typec/mux/nb7vpq904m.c @@ -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) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 829d75ebab42..cc1d83926497 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -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);  | 
