diff options
author | Thomas Pugliese <thomas.pugliese@gmail.com> | 2013-08-08 13:11:45 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-08-12 16:13:32 -0400 |
commit | 467d296f47731bcba578cfdea8416b4c152c4f1b (patch) | |
tree | 9f1e649793a2699b002e7dac26739432d9ab62d1 | |
parent | 9841f37a1cca5357c1fd198b1068c12955aa632f (diff) |
wusbcore: fix root hub hub_status_data to only return > 0 if status has actually changed
The hub_status_data function on the wireless USB root hub controller
(wusbhc_rh_status_data) always returns a positive value even if no ports
have changed. This patch updates wusbhc_rh_status_data to only return a
positive value if the root hub status needs to be queried. The current
implementation can also leave the upper bits of the port bitmap
uninitialized if wusbhc->ports_max is not one less than an even multiple
of 8. This patch fixes that as well by initializing the buffer to 0.
Signed-off-by: Thomas Pugliese <thomas.pugliese@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/wusbcore/rh.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/drivers/usb/wusbcore/rh.c b/drivers/usb/wusbcore/rh.c index bdb0cc3046b5..fe8bc777ab88 100644 --- a/drivers/usb/wusbcore/rh.c +++ b/drivers/usb/wusbcore/rh.c | |||
@@ -141,18 +141,26 @@ static int wusbhc_rh_port_reset(struct wusbhc *wusbhc, u8 port_idx) | |||
141 | int wusbhc_rh_status_data(struct usb_hcd *usb_hcd, char *_buf) | 141 | int wusbhc_rh_status_data(struct usb_hcd *usb_hcd, char *_buf) |
142 | { | 142 | { |
143 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); | 143 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); |
144 | size_t cnt, size; | 144 | size_t cnt, size, bits_set = 0; |
145 | unsigned long *buf = (unsigned long *) _buf; | ||
146 | 145 | ||
147 | /* WE DON'T LOCK, see comment */ | 146 | /* WE DON'T LOCK, see comment */ |
148 | size = wusbhc->ports_max + 1 /* hub bit */; | 147 | /* round up to bytes. Hub bit is bit 0 so add 1. */ |
149 | size = (size + 8 - 1) / 8; /* round to bytes */ | 148 | size = DIV_ROUND_UP(wusbhc->ports_max + 1, 8); |
150 | for (cnt = 0; cnt < wusbhc->ports_max; cnt++) | 149 | |
151 | if (wusb_port_by_idx(wusbhc, cnt)->change) | 150 | /* clear the output buffer. */ |
152 | set_bit(cnt + 1, buf); | 151 | memset(_buf, 0, size); |
153 | else | 152 | /* set the bit for each changed port. */ |
154 | clear_bit(cnt + 1, buf); | 153 | for (cnt = 0; cnt < wusbhc->ports_max; cnt++) { |
155 | return size; | 154 | |
155 | if (wusb_port_by_idx(wusbhc, cnt)->change) { | ||
156 | const int bitpos = cnt+1; | ||
157 | |||
158 | _buf[bitpos/8] |= (1 << (bitpos % 8)); | ||
159 | bits_set++; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | return bits_set ? size : 0; | ||
156 | } | 164 | } |
157 | EXPORT_SYMBOL_GPL(wusbhc_rh_status_data); | 165 | EXPORT_SYMBOL_GPL(wusbhc_rh_status_data); |
158 | 166 | ||