diff options
Diffstat (limited to 'drivers/usb/wusbcore/wusbhc.c')
| -rw-r--r-- | drivers/usb/wusbcore/wusbhc.c | 96 | 
1 files changed, 80 insertions, 16 deletions
diff --git a/drivers/usb/wusbcore/wusbhc.c b/drivers/usb/wusbcore/wusbhc.c index 2054d4ee977..3e1ba51d1a4 100644 --- a/drivers/usb/wusbcore/wusbhc.c +++ b/drivers/usb/wusbcore/wusbhc.c @@ -55,7 +55,8 @@ static struct wusbhc *usbhc_dev_to_wusbhc(struct device *dev)   * value of trust_timeout is jiffies.   */  static ssize_t wusb_trust_timeout_show(struct device *dev, -				       struct device_attribute *attr, char *buf) +					struct device_attribute *attr, +					char *buf)  {  	struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); @@ -75,12 +76,11 @@ static ssize_t wusb_trust_timeout_store(struct device *dev,  		result = -EINVAL;  		goto out;  	} -	/* FIXME: maybe we should check for range validity? */ -	wusbhc->trust_timeout = trust_timeout; +	wusbhc->trust_timeout = min_t(unsigned, trust_timeout, 500);  	cancel_delayed_work(&wusbhc->keep_alive_timer);  	flush_workqueue(wusbd);  	queue_delayed_work(wusbd, &wusbhc->keep_alive_timer, -			   (trust_timeout * CONFIG_HZ)/1000/2); +			   msecs_to_jiffies(wusbhc->trust_timeout / 2));  out:  	return result < 0 ? result : size;  } @@ -174,13 +174,76 @@ static ssize_t wusb_phy_rate_store(struct device *dev,  	wusbhc->phy_rate = phy_rate;  	return size;  } -static DEVICE_ATTR(wusb_phy_rate, 0644, wusb_phy_rate_show, wusb_phy_rate_store); +static DEVICE_ATTR(wusb_phy_rate, 0644, wusb_phy_rate_show, +			wusb_phy_rate_store); + +static ssize_t wusb_dnts_show(struct device *dev, +				  struct device_attribute *attr, +				  char *buf) +{ +	struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); + +	return sprintf(buf, "num slots: %d\ninterval: %dms\n", +			wusbhc->dnts_num_slots, wusbhc->dnts_interval); +} + +static ssize_t wusb_dnts_store(struct device *dev, +				   struct device_attribute *attr, +				   const char *buf, size_t size) +{ +	struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); +	uint8_t num_slots, interval; +	ssize_t result; + +	result = sscanf(buf, "%hhu %hhu", &num_slots, &interval); + +	if (result != 2) +		return -EINVAL; + +	wusbhc->dnts_num_slots = num_slots; +	wusbhc->dnts_interval = interval; + +	return size; +} +static DEVICE_ATTR(wusb_dnts, 0644, wusb_dnts_show, wusb_dnts_store); + +static ssize_t wusb_retry_count_show(struct device *dev, +				  struct device_attribute *attr, +				  char *buf) +{ +	struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); + +	return sprintf(buf, "%d\n", wusbhc->retry_count); +} + +static ssize_t wusb_retry_count_store(struct device *dev, +				   struct device_attribute *attr, +				   const char *buf, size_t size) +{ +	struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); +	uint8_t retry_count; +	ssize_t result; + +	result = sscanf(buf, "%hhu", &retry_count); + +	if (result != 1) +		return -EINVAL; + +	wusbhc->retry_count = max_t(uint8_t, retry_count, +					WUSB_RETRY_COUNT_MAX); + +	return size; +} +static DEVICE_ATTR(wusb_retry_count, 0644, wusb_retry_count_show, +	wusb_retry_count_store);  /* Group all the WUSBHC attributes */  static struct attribute *wusbhc_attrs[] = {  		&dev_attr_wusb_trust_timeout.attr,  		&dev_attr_wusb_chid.attr,  		&dev_attr_wusb_phy_rate.attr, +		&dev_attr_wusb_dnts.attr, +		&dev_attr_wusb_retry_count.attr,  		NULL,  }; @@ -206,8 +269,12 @@ int wusbhc_create(struct wusbhc *wusbhc)  {  	int result = 0; +	/* set defaults.  These can be overwritten using sysfs attributes. */  	wusbhc->trust_timeout = WUSB_TRUST_TIMEOUT_MS;  	wusbhc->phy_rate = UWB_PHY_RATE_INVALID - 1; +	wusbhc->dnts_num_slots = 4; +	wusbhc->dnts_interval = 2; +	wusbhc->retry_count = WUSB_RETRY_COUNT_INFINITE;  	mutex_init(&wusbhc->mutex);  	result = wusbhc_mmcie_create(wusbhc); @@ -257,17 +324,12 @@ int wusbhc_b_create(struct wusbhc *wusbhc)  	result = sysfs_create_group(wusbhc_kobj(wusbhc), &wusbhc_attr_group);  	if (result < 0) { -		dev_err(dev, "Cannot register WUSBHC attributes: %d\n", result); +		dev_err(dev, "Cannot register WUSBHC attributes: %d\n", +			result);  		goto error_create_attr_group;  	} -	result = wusbhc_pal_register(wusbhc); -	if (result < 0) -		goto error_pal_register;  	return 0; - -error_pal_register: -	sysfs_remove_group(wusbhc_kobj(wusbhc), &wusbhc_attr_group);  error_create_attr_group:  	return result;  } @@ -320,7 +382,7 @@ u8 wusb_cluster_id_get(void)  	u8 id;  	spin_lock(&wusb_cluster_ids_lock);  	id = find_first_zero_bit(wusb_cluster_id_table, CLUSTER_IDS); -	if (id > CLUSTER_IDS) { +	if (id >= CLUSTER_IDS) {  		id = 0;  		goto out;  	} @@ -361,13 +423,14 @@ EXPORT_SYMBOL_GPL(wusb_cluster_id_put);   *  - After a successful transfer, update the trust timeout timestamp   *    for the WUSB device.   * - *  - [WUSB] sections 4.13 and 7.5.1 specifies the stop retrasmittion + *  - [WUSB] sections 4.13 and 7.5.1 specify the stop retransmission   *    condition for the WCONNECTACK_IE is that the host has observed   *    the associated device responding to a control transfer.   */  void wusbhc_giveback_urb(struct wusbhc *wusbhc, struct urb *urb, int status)  { -	struct wusb_dev *wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb->dev); +	struct wusb_dev *wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, +					urb->dev);  	if (status == 0 && wusb_dev) {  		wusb_dev->entry_ts = jiffies; @@ -393,7 +456,8 @@ EXPORT_SYMBOL_GPL(wusbhc_giveback_urb);   */  void wusbhc_reset_all(struct wusbhc *wusbhc)  { -	uwb_rc_reset_all(wusbhc->uwb_rc); +	if (wusbhc->uwb_rc) +		uwb_rc_reset_all(wusbhc->uwb_rc);  }  EXPORT_SYMBOL_GPL(wusbhc_reset_all);  | 
