diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/host/hwa-hc.c | 102 | ||||
-rw-r--r-- | drivers/usb/host/whci/whcd.h | 2 | ||||
-rw-r--r-- | drivers/usb/host/whci/whci-hc.h | 2 | ||||
-rw-r--r-- | drivers/usb/host/whci/wusb.c | 15 | ||||
-rw-r--r-- | drivers/usb/wusbcore/mmc.c | 8 | ||||
-rw-r--r-- | drivers/usb/wusbcore/wusbhc.h | 24 |
6 files changed, 79 insertions, 74 deletions
diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 64be4d88df11..0e18989e1658 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c | |||
@@ -171,11 +171,6 @@ static int hwahc_op_start(struct usb_hcd *usb_hcd) | |||
171 | if (result < 0) | 171 | if (result < 0) |
172 | goto error_set_cluster_id; | 172 | goto error_set_cluster_id; |
173 | 173 | ||
174 | result = wa_nep_arm(&hwahc->wa, GFP_KERNEL); | ||
175 | if (result < 0) { | ||
176 | dev_err(dev, "cannot listen to notifications: %d\n", result); | ||
177 | goto error_stop; | ||
178 | } | ||
179 | usb_hcd->uses_new_polling = 1; | 174 | usb_hcd->uses_new_polling = 1; |
180 | usb_hcd->poll_rh = 1; | 175 | usb_hcd->poll_rh = 1; |
181 | usb_hcd->state = HC_STATE_RUNNING; | 176 | usb_hcd->state = HC_STATE_RUNNING; |
@@ -185,8 +180,6 @@ out: | |||
185 | d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); | 180 | d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); |
186 | return result; | 181 | return result; |
187 | 182 | ||
188 | error_stop: | ||
189 | __wa_stop(&hwahc->wa); | ||
190 | error_set_cluster_id: | 183 | error_set_cluster_id: |
191 | wusb_cluster_id_put(wusbhc->cluster_id); | 184 | wusb_cluster_id_put(wusbhc->cluster_id); |
192 | error_cluster_id_get: | 185 | error_cluster_id_get: |
@@ -194,39 +187,6 @@ error_cluster_id_get: | |||
194 | 187 | ||
195 | } | 188 | } |
196 | 189 | ||
197 | /* | ||
198 | * FIXME: break this function up | ||
199 | */ | ||
200 | static int __hwahc_op_wusbhc_start(struct wusbhc *wusbhc) | ||
201 | { | ||
202 | int result; | ||
203 | struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); | ||
204 | struct device *dev = &hwahc->wa.usb_iface->dev; | ||
205 | |||
206 | /* Set up a Host Info WUSB Information Element */ | ||
207 | d_fnstart(4, dev, "(hwahc %p)\n", hwahc); | ||
208 | result = -ENOSPC; | ||
209 | |||
210 | result = __wa_set_feature(&hwahc->wa, WA_ENABLE); | ||
211 | if (result < 0) { | ||
212 | dev_err(dev, "error commanding HC to start: %d\n", result); | ||
213 | goto error_stop; | ||
214 | } | ||
215 | result = __wa_wait_status(&hwahc->wa, WA_ENABLE, WA_ENABLE); | ||
216 | if (result < 0) { | ||
217 | dev_err(dev, "error waiting for HC to start: %d\n", result); | ||
218 | goto error_stop; | ||
219 | } | ||
220 | result = 0; | ||
221 | out: | ||
222 | d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); | ||
223 | return result; | ||
224 | |||
225 | error_stop: | ||
226 | result = __wa_clear_feature(&hwahc->wa, WA_ENABLE); | ||
227 | goto out; | ||
228 | } | ||
229 | |||
230 | static int hwahc_op_suspend(struct usb_hcd *usb_hcd, pm_message_t msg) | 190 | static int hwahc_op_suspend(struct usb_hcd *usb_hcd, pm_message_t msg) |
231 | { | 191 | { |
232 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); | 192 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); |
@@ -246,18 +206,6 @@ static int hwahc_op_resume(struct usb_hcd *usb_hcd) | |||
246 | return -ENOSYS; | 206 | return -ENOSYS; |
247 | } | 207 | } |
248 | 208 | ||
249 | static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc) | ||
250 | { | ||
251 | int result; | ||
252 | struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); | ||
253 | struct device *dev = &hwahc->wa.usb_iface->dev; | ||
254 | |||
255 | d_fnstart(4, dev, "(hwahc %p)\n", hwahc); | ||
256 | /* Nothing for now */ | ||
257 | d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); | ||
258 | return; | ||
259 | } | ||
260 | |||
261 | /* | 209 | /* |
262 | * No need to abort pipes, as when this is called, all the children | 210 | * No need to abort pipes, as when this is called, all the children |
263 | * has been disconnected and that has done it [through | 211 | * has been disconnected and that has done it [through |
@@ -275,8 +223,6 @@ static void hwahc_op_stop(struct usb_hcd *usb_hcd) | |||
275 | d_fnstart(4, dev, "(hwahc %p)\n", hwahc); | 223 | d_fnstart(4, dev, "(hwahc %p)\n", hwahc); |
276 | mutex_lock(&wusbhc->mutex); | 224 | mutex_lock(&wusbhc->mutex); |
277 | wusbhc_stop(wusbhc); | 225 | wusbhc_stop(wusbhc); |
278 | wa_nep_disarm(&hwahc->wa); | ||
279 | result = __wa_stop(&hwahc->wa); | ||
280 | wusb_cluster_id_put(wusbhc->cluster_id); | 226 | wusb_cluster_id_put(wusbhc->cluster_id); |
281 | mutex_unlock(&wusbhc->mutex); | 227 | mutex_unlock(&wusbhc->mutex); |
282 | d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); | 228 | d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); |
@@ -325,6 +271,54 @@ static void hwahc_op_endpoint_disable(struct usb_hcd *usb_hcd, | |||
325 | rpipe_ep_disable(&hwahc->wa, ep); | 271 | rpipe_ep_disable(&hwahc->wa, ep); |
326 | } | 272 | } |
327 | 273 | ||
274 | static int __hwahc_op_wusbhc_start(struct wusbhc *wusbhc) | ||
275 | { | ||
276 | int result; | ||
277 | struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); | ||
278 | struct device *dev = &hwahc->wa.usb_iface->dev; | ||
279 | |||
280 | result = __wa_set_feature(&hwahc->wa, WA_ENABLE); | ||
281 | if (result < 0) { | ||
282 | dev_err(dev, "error commanding HC to start: %d\n", result); | ||
283 | goto error_stop; | ||
284 | } | ||
285 | result = __wa_wait_status(&hwahc->wa, WA_ENABLE, WA_ENABLE); | ||
286 | if (result < 0) { | ||
287 | dev_err(dev, "error waiting for HC to start: %d\n", result); | ||
288 | goto error_stop; | ||
289 | } | ||
290 | result = wa_nep_arm(&hwahc->wa, GFP_KERNEL); | ||
291 | if (result < 0) { | ||
292 | dev_err(dev, "cannot listen to notifications: %d\n", result); | ||
293 | goto error_stop; | ||
294 | } | ||
295 | return result; | ||
296 | |||
297 | error_stop: | ||
298 | __wa_clear_feature(&hwahc->wa, WA_ENABLE); | ||
299 | return result; | ||
300 | } | ||
301 | |||
302 | static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc, int delay) | ||
303 | { | ||
304 | struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); | ||
305 | struct wahc *wa = &hwahc->wa; | ||
306 | u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; | ||
307 | int ret; | ||
308 | |||
309 | ret = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), | ||
310 | WUSB_REQ_CHAN_STOP, | ||
311 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
312 | delay * 1000, | ||
313 | iface_no, | ||
314 | NULL, 0, 1000 /* FIXME: arbitrary */); | ||
315 | if (ret == 0) | ||
316 | msleep(delay); | ||
317 | |||
318 | wa_nep_disarm(&hwahc->wa); | ||
319 | __wa_stop(&hwahc->wa); | ||
320 | } | ||
321 | |||
328 | /* | 322 | /* |
329 | * Set the UWB MAS allocation for the WUSB cluster | 323 | * Set the UWB MAS allocation for the WUSB cluster |
330 | * | 324 | * |
diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h index 1d2a53bd39fd..1bbb8cb6bf80 100644 --- a/drivers/usb/host/whci/whcd.h +++ b/drivers/usb/host/whci/whcd.h | |||
@@ -136,7 +136,7 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len); | |||
136 | 136 | ||
137 | /* wusb.c */ | 137 | /* wusb.c */ |
138 | int whc_wusbhc_start(struct wusbhc *wusbhc); | 138 | int whc_wusbhc_start(struct wusbhc *wusbhc); |
139 | void whc_wusbhc_stop(struct wusbhc *wusbhc); | 139 | void whc_wusbhc_stop(struct wusbhc *wusbhc, int delay); |
140 | int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, | 140 | int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, |
141 | u8 handle, struct wuie_hdr *wuie); | 141 | u8 handle, struct wuie_hdr *wuie); |
142 | int whc_mmcie_rm(struct wusbhc *wusbhc, u8 handle); | 142 | int whc_mmcie_rm(struct wusbhc *wusbhc, u8 handle); |
diff --git a/drivers/usb/host/whci/whci-hc.h b/drivers/usb/host/whci/whci-hc.h index bff1eb7a35cf..51df7e313b38 100644 --- a/drivers/usb/host/whci/whci-hc.h +++ b/drivers/usb/host/whci/whci-hc.h | |||
@@ -410,6 +410,8 @@ struct dn_buf_entry { | |||
410 | # define WUSBDNTSCTRL_SLOTS(s) ((s) << 0) | 410 | # define WUSBDNTSCTRL_SLOTS(s) ((s) << 0) |
411 | 411 | ||
412 | #define WUSBTIME 0x68 | 412 | #define WUSBTIME 0x68 |
413 | # define WUSBTIME_CHANNEL_TIME_MASK 0x00ffffff | ||
414 | |||
413 | #define WUSBBPST 0x6c | 415 | #define WUSBBPST 0x6c |
414 | #define WUSBDIBUPDATED 0x70 | 416 | #define WUSBDIBUPDATED 0x70 |
415 | 417 | ||
diff --git a/drivers/usb/host/whci/wusb.c b/drivers/usb/host/whci/wusb.c index 66e4ddcd961d..2befd475def4 100644 --- a/drivers/usb/host/whci/wusb.c +++ b/drivers/usb/host/whci/wusb.c | |||
@@ -64,8 +64,9 @@ static int whc_update_di(struct whc *whc, int idx) | |||
64 | } | 64 | } |
65 | 65 | ||
66 | /* | 66 | /* |
67 | * WHCI starts and stops MMCs based on there being a valid GTK so | 67 | * WHCI starts MMCs based on there being a valid GTK so these need |
68 | * these need only start/stop the asynchronous and periodic schedules. | 68 | * only start/stop the asynchronous and periodic schedules and send a |
69 | * channel stop command. | ||
69 | */ | 70 | */ |
70 | 71 | ||
71 | int whc_wusbhc_start(struct wusbhc *wusbhc) | 72 | int whc_wusbhc_start(struct wusbhc *wusbhc) |
@@ -78,12 +79,20 @@ int whc_wusbhc_start(struct wusbhc *wusbhc) | |||
78 | return 0; | 79 | return 0; |
79 | } | 80 | } |
80 | 81 | ||
81 | void whc_wusbhc_stop(struct wusbhc *wusbhc) | 82 | void whc_wusbhc_stop(struct wusbhc *wusbhc, int delay) |
82 | { | 83 | { |
83 | struct whc *whc = wusbhc_to_whc(wusbhc); | 84 | struct whc *whc = wusbhc_to_whc(wusbhc); |
85 | u32 stop_time, now_time; | ||
86 | int ret; | ||
84 | 87 | ||
85 | pzl_stop(whc); | 88 | pzl_stop(whc); |
86 | asl_stop(whc); | 89 | asl_stop(whc); |
90 | |||
91 | now_time = le_readl(whc->base + WUSBTIME) & WUSBTIME_CHANNEL_TIME_MASK; | ||
92 | stop_time = (now_time + ((delay * 8) << 7)) & 0x00ffffff; | ||
93 | ret = whc_do_gencmd(whc, WUSBGENCMDSTS_CHAN_STOP, stop_time, NULL, 0); | ||
94 | if (ret == 0) | ||
95 | msleep(delay); | ||
87 | } | 96 | } |
88 | 97 | ||
89 | int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, | 98 | int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, |
diff --git a/drivers/usb/wusbcore/mmc.c b/drivers/usb/wusbcore/mmc.c index cfa77a01cebd..af2aee0fdffa 100644 --- a/drivers/usb/wusbcore/mmc.c +++ b/drivers/usb/wusbcore/mmc.c | |||
@@ -250,18 +250,14 @@ error_alloc: | |||
250 | * wusbhc_stop - stop transmitting MMCs | 250 | * wusbhc_stop - stop transmitting MMCs |
251 | * @wusbhc: the HC to stop | 251 | * @wusbhc: the HC to stop |
252 | * | 252 | * |
253 | * Send a Host Disconnect IE, wait, remove all the MMCs (stop sending MMCs). | 253 | * Stops the WUSB channel and removes the cluster reservation. |
254 | * | ||
255 | * If we can't allocate a Host Stop IE, screw it, we don't notify the | ||
256 | * devices we are disconnecting... | ||
257 | */ | 254 | */ |
258 | void wusbhc_stop(struct wusbhc *wusbhc) | 255 | void wusbhc_stop(struct wusbhc *wusbhc) |
259 | { | 256 | { |
260 | if (wusbhc->active) { | 257 | if (wusbhc->active) { |
261 | wusbhc->active = 0; | 258 | wusbhc->active = 0; |
262 | wusbhc->stop(wusbhc); | 259 | wusbhc->stop(wusbhc, WUSB_CHANNEL_STOP_DELAY_MS); |
263 | wusbhc_sec_stop(wusbhc); | 260 | wusbhc_sec_stop(wusbhc); |
264 | __wusbhc_host_disconnect_ie(wusbhc); | ||
265 | wusbhc_devconnect_stop(wusbhc); | 261 | wusbhc_devconnect_stop(wusbhc); |
266 | wusbhc_rsv_terminate(wusbhc); | 262 | wusbhc_rsv_terminate(wusbhc); |
267 | } | 263 | } |
diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h index d0c132434f1b..b9bdf5a5f11b 100644 --- a/drivers/usb/wusbcore/wusbhc.h +++ b/drivers/usb/wusbcore/wusbhc.h | |||
@@ -64,6 +64,13 @@ | |||
64 | #include <linux/uwb.h> | 64 | #include <linux/uwb.h> |
65 | #include <linux/usb/wusb.h> | 65 | #include <linux/usb/wusb.h> |
66 | 66 | ||
67 | /* | ||
68 | * Time from a WUSB channel stop request to the last transmitted MMC. | ||
69 | * | ||
70 | * This needs to be > 4.096 ms in case no MMCs can be transmitted in | ||
71 | * zone 0. | ||
72 | */ | ||
73 | #define WUSB_CHANNEL_STOP_DELAY_MS 8 | ||
67 | 74 | ||
68 | /** | 75 | /** |
69 | * Wireless USB device | 76 | * Wireless USB device |
@@ -198,21 +205,18 @@ struct wusb_port { | |||
198 | * @mmcies_max Max number of Information Elements this HC can send | 205 | * @mmcies_max Max number of Information Elements this HC can send |
199 | * in its MMC. Read-only. | 206 | * in its MMC. Read-only. |
200 | * | 207 | * |
208 | * @start Start the WUSB channel. | ||
209 | * | ||
210 | * @stop Stop the WUSB channel after the specified number of | ||
211 | * milliseconds. Channel Stop IEs should be transmitted | ||
212 | * as required by [WUSB] 4.16.2.1. | ||
213 | * | ||
201 | * @mmcie_add HC specific operation (WHCI or HWA) for adding an | 214 | * @mmcie_add HC specific operation (WHCI or HWA) for adding an |
202 | * MMCIE. | 215 | * MMCIE. |
203 | * | 216 | * |
204 | * @mmcie_rm HC specific operation (WHCI or HWA) for removing an | 217 | * @mmcie_rm HC specific operation (WHCI or HWA) for removing an |
205 | * MMCIE. | 218 | * MMCIE. |
206 | * | 219 | * |
207 | * @enc_types Array which describes the encryptions methods | ||
208 | * supported by the host as described in WUSB1.0 -- | ||
209 | * one entry per supported method. As of WUSB1.0 there | ||
210 | * is only four methods, we make space for eight just in | ||
211 | * case they decide to add some more (and pray they do | ||
212 | * it in sequential order). if 'enc_types[enc_method] | ||
213 | * != 0', then it is supported by the host. enc_method | ||
214 | * is USB_ENC_TYPE*. | ||
215 | * | ||
216 | * @set_ptk: Set the PTK and enable encryption for a device. Or, if | 220 | * @set_ptk: Set the PTK and enable encryption for a device. Or, if |
217 | * the supplied key is NULL, disable encryption for that | 221 | * the supplied key is NULL, disable encryption for that |
218 | * device. | 222 | * device. |
@@ -269,7 +273,7 @@ struct wusbhc { | |||
269 | u8 mmcies_max; | 273 | u8 mmcies_max; |
270 | /* FIXME: make wusbhc_ops? */ | 274 | /* FIXME: make wusbhc_ops? */ |
271 | int (*start)(struct wusbhc *wusbhc); | 275 | int (*start)(struct wusbhc *wusbhc); |
272 | void (*stop)(struct wusbhc *wusbhc); | 276 | void (*stop)(struct wusbhc *wusbhc, int delay); |
273 | int (*mmcie_add)(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, | 277 | int (*mmcie_add)(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, |
274 | u8 handle, struct wuie_hdr *wuie); | 278 | u8 handle, struct wuie_hdr *wuie); |
275 | int (*mmcie_rm)(struct wusbhc *wusbhc, u8 handle); | 279 | int (*mmcie_rm)(struct wusbhc *wusbhc, u8 handle); |