USB: wusb: add wusb_phy_rate sysfs file to host controllers
authorDavid Vrabel <david.vrabel@csr.com>
Mon, 12 Oct 2009 15:45:18 +0000 (15:45 +0000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 11 Dec 2009 19:55:16 +0000 (11:55 -0800)
Add the wusb_phy_rate sysfs file to Wireless USB host controllers.  This
sets the maximum PHY rate that will be used for all connected devices.

Signed-off-by: David Vrabel <david.vrabel@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc
drivers/usb/host/whci/qset.c
drivers/usb/host/whci/whci-hc.h
drivers/usb/wusbcore/wusbhc.c
drivers/usb/wusbcore/wusbhc.h

index 4e8106f..25b1e75 100644 (file)
@@ -23,3 +23,16 @@ Description:
                 Since this relates to security (specifically, the
                 lifetime of PTKs and GTKs) it should not be changed
                 from the default.
                 Since this relates to security (specifically, the
                 lifetime of PTKs and GTKs) it should not be changed
                 from the default.
+
+What:           /sys/class/uwb_rc/uwbN/wusbhc/wusb_phy_rate
+Date:           August 2009
+KernelVersion:  2.6.32
+Contact:        David Vrabel <david.vrabel@csr.com>
+Description:
+                The maximum PHY rate to use for all connected devices.
+                This is only of limited use for testing and
+                development as the hardware's automatic rate
+                adaptation is better then this simple control.
+
+                Refer to [ECMA-368] section 10.3.1.1 for the value to
+                use.
index 0828086..39e855a 100644 (file)
@@ -49,11 +49,13 @@ struct whc_qset *qset_alloc(struct whc *whc, gfp_t mem_flags)
  *        state
  * @urb:  an urb for a transfer to this endpoint
  */
  *        state
  * @urb:  an urb for a transfer to this endpoint
  */
-static void qset_fill_qh(struct whc_qset *qset, struct urb *urb)
+static void qset_fill_qh(struct whc *whc, struct whc_qset *qset, struct urb *urb)
 {
        struct usb_device *usb_dev = urb->dev;
 {
        struct usb_device *usb_dev = urb->dev;
+       struct wusb_dev *wusb_dev = usb_dev->wusb_dev;
        struct usb_wireless_ep_comp_descriptor *epcd;
        bool is_out;
        struct usb_wireless_ep_comp_descriptor *epcd;
        bool is_out;
+       uint8_t phy_rate;
 
        is_out = usb_pipeout(urb->pipe);
 
 
        is_out = usb_pipeout(urb->pipe);
 
@@ -68,6 +70,22 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb)
                qset->max_burst = 1;
        }
 
                qset->max_burst = 1;
        }
 
+       /*
+        * Initial PHY rate is 53.3 Mbit/s for control endpoints or
+        * the maximum supported by the device for other endpoints
+        * (unless limited by the user).
+        */
+       if (usb_pipecontrol(urb->pipe))
+               phy_rate = UWB_PHY_RATE_53;
+       else {
+               uint16_t phy_rates;
+
+               phy_rates = le16_to_cpu(wusb_dev->wusb_cap_descr->wPHYRates);
+               phy_rate = fls(phy_rates) - 1;
+               if (phy_rate > whc->wusbhc.phy_rate)
+                       phy_rate = whc->wusbhc.phy_rate;
+       }
+
        qset->qh.info1 = cpu_to_le32(
                QH_INFO1_EP(usb_pipeendpoint(urb->pipe))
                | (is_out ? QH_INFO1_DIR_OUT : QH_INFO1_DIR_IN)
        qset->qh.info1 = cpu_to_le32(
                QH_INFO1_EP(usb_pipeendpoint(urb->pipe))
                | (is_out ? QH_INFO1_DIR_OUT : QH_INFO1_DIR_IN)
@@ -87,7 +105,7 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb)
         * strength and can presumably guess the Tx power required
         * from that? */
        qset->qh.info3 = cpu_to_le32(
         * strength and can presumably guess the Tx power required
         * from that? */
        qset->qh.info3 = cpu_to_le32(
-               QH_INFO3_TX_RATE_53_3
+               QH_INFO3_TX_RATE(phy_rate)
                | QH_INFO3_TX_PWR(0) /* 0 == max power */
                );
 
                | QH_INFO3_TX_PWR(0) /* 0 == max power */
                );
 
@@ -149,7 +167,7 @@ struct whc_qset *get_qset(struct whc *whc, struct urb *urb,
 
                qset->ep = urb->ep;
                urb->ep->hcpriv = qset;
 
                qset->ep = urb->ep;
                urb->ep->hcpriv = qset;
-               qset_fill_qh(qset, urb);
+               qset_fill_qh(whc, qset, urb);
        }
        return qset;
 }
        }
        return qset;
 }
index d5e5c3a..4d4cbc0 100644 (file)
@@ -172,14 +172,7 @@ struct whc_qhead {
 #define QH_INFO3_MAX_DELAY(d)    ((d) << 0)  /* maximum stream delay in 125 us units (isoc only) */
 #define QH_INFO3_INTERVAL(i)     ((i) << 16) /* segment interval in 125 us units (isoc only) */
 
 #define QH_INFO3_MAX_DELAY(d)    ((d) << 0)  /* maximum stream delay in 125 us units (isoc only) */
 #define QH_INFO3_INTERVAL(i)     ((i) << 16) /* segment interval in 125 us units (isoc only) */
 
-#define QH_INFO3_TX_RATE_53_3    (0 << 24)
-#define QH_INFO3_TX_RATE_80      (1 << 24)
-#define QH_INFO3_TX_RATE_106_7   (2 << 24)
-#define QH_INFO3_TX_RATE_160     (3 << 24)
-#define QH_INFO3_TX_RATE_200     (4 << 24)
-#define QH_INFO3_TX_RATE_320     (5 << 24)
-#define QH_INFO3_TX_RATE_400     (6 << 24)
-#define QH_INFO3_TX_RATE_480     (7 << 24)
+#define QH_INFO3_TX_RATE(r)      ((r) << 24) /* PHY rate (see [ECMA-368] section 10.3.1.1) */
 #define QH_INFO3_TX_PWR(p)       ((p) << 29) /* transmit power (see [WUSB] section 5.2.1.2) */
 
 #define QH_STATUS_FLOW_CTRL      (1 << 15)
 #define QH_INFO3_TX_PWR(p)       ((p) << 29) /* transmit power (see [WUSB] section 5.2.1.2) */
 
 #define QH_STATUS_FLOW_CTRL      (1 << 15)
index ee6256f..eab86e4 100644 (file)
@@ -147,10 +147,40 @@ static ssize_t wusb_chid_store(struct device *dev,
 }
 static DEVICE_ATTR(wusb_chid, 0644, wusb_chid_show, wusb_chid_store);
 
 }
 static DEVICE_ATTR(wusb_chid, 0644, wusb_chid_show, wusb_chid_store);
 
+
+static ssize_t wusb_phy_rate_show(struct device *dev,
+                                 struct device_attribute *attr,
+                                 char *buf)
+{
+       struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev);
+
+       return sprintf(buf, "%d\n", wusbhc->phy_rate);
+}
+
+static ssize_t wusb_phy_rate_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t size)
+{
+       struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev);
+       uint8_t phy_rate;
+       ssize_t result;
+
+       result = sscanf(buf, "%hhu", &phy_rate);
+       if (result != 1)
+               return -EINVAL;
+       if (phy_rate >= UWB_PHY_RATE_INVALID)
+               return -EINVAL;
+
+       wusbhc->phy_rate = phy_rate;
+       return size;
+}
+static DEVICE_ATTR(wusb_phy_rate, 0644, wusb_phy_rate_show, wusb_phy_rate_store);
+
 /* Group all the WUSBHC attributes */
 static struct attribute *wusbhc_attrs[] = {
                &dev_attr_wusb_trust_timeout.attr,
                &dev_attr_wusb_chid.attr,
 /* 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,
                NULL,
 };
 
                NULL,
 };
 
@@ -177,6 +207,8 @@ int wusbhc_create(struct wusbhc *wusbhc)
        int result = 0;
 
        wusbhc->trust_timeout = WUSB_TRUST_TIMEOUT_MS;
        int result = 0;
 
        wusbhc->trust_timeout = WUSB_TRUST_TIMEOUT_MS;
+       wusbhc->phy_rate = UWB_PHY_RATE_INVALID - 1;
+
        mutex_init(&wusbhc->mutex);
        result = wusbhc_mmcie_create(wusbhc);
        if (result < 0)
        mutex_init(&wusbhc->mutex);
        result = wusbhc_mmcie_create(wusbhc);
        if (result < 0)
index 797c245..fd2fd4e 100644 (file)
@@ -253,6 +253,7 @@ struct wusbhc {
 
        unsigned trust_timeout;                 /* in jiffies */
        struct wusb_ckhdid chid;
 
        unsigned trust_timeout;                 /* in jiffies */
        struct wusb_ckhdid chid;
+       uint8_t phy_rate;
        struct wuie_host_info *wuie_host_info;
 
        struct mutex mutex;                     /* locks everything else */
        struct wuie_host_info *wuie_host_info;
 
        struct mutex mutex;                     /* locks everything else */