diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 190 |
1 files changed, 92 insertions, 98 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index d4361dc0773e..fca29ae57e71 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -261,6 +261,89 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) | |||
261 | } | 261 | } |
262 | } | 262 | } |
263 | 263 | ||
264 | /* | ||
265 | * RX data handlers. | ||
266 | */ | ||
267 | static void rt2x00usb_work_rxdone(struct work_struct *work) | ||
268 | { | ||
269 | struct rt2x00_dev *rt2x00dev = | ||
270 | container_of(work, struct rt2x00_dev, rxdone_work); | ||
271 | struct queue_entry *entry; | ||
272 | struct skb_frame_desc *skbdesc; | ||
273 | u8 rxd[32]; | ||
274 | |||
275 | while (!rt2x00queue_empty(rt2x00dev->rx)) { | ||
276 | entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE); | ||
277 | |||
278 | if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | ||
279 | break; | ||
280 | |||
281 | /* | ||
282 | * Fill in desc fields of the skb descriptor | ||
283 | */ | ||
284 | skbdesc = get_skb_frame_desc(entry->skb); | ||
285 | skbdesc->desc = rxd; | ||
286 | skbdesc->desc_len = entry->queue->desc_size; | ||
287 | |||
288 | /* | ||
289 | * Send the frame to rt2x00lib for further processing. | ||
290 | */ | ||
291 | rt2x00lib_rxdone(entry); | ||
292 | } | ||
293 | } | ||
294 | |||
295 | static void rt2x00usb_interrupt_rxdone(struct urb *urb) | ||
296 | { | ||
297 | struct queue_entry *entry = (struct queue_entry *)urb->context; | ||
298 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
299 | |||
300 | if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | ||
301 | return; | ||
302 | |||
303 | /* | ||
304 | * Report the frame as DMA done | ||
305 | */ | ||
306 | rt2x00lib_dmadone(entry); | ||
307 | |||
308 | /* | ||
309 | * Check if the received data is simply too small | ||
310 | * to be actually valid, or if the urb is signaling | ||
311 | * a problem. | ||
312 | */ | ||
313 | if (urb->actual_length < entry->queue->desc_size || urb->status) | ||
314 | set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); | ||
315 | |||
316 | /* | ||
317 | * Schedule the delayed work for reading the RX status | ||
318 | * from the device. | ||
319 | */ | ||
320 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); | ||
321 | } | ||
322 | |||
323 | static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) | ||
324 | { | ||
325 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
326 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); | ||
327 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | ||
328 | int status; | ||
329 | |||
330 | if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | ||
331 | return; | ||
332 | |||
333 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, | ||
334 | usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint), | ||
335 | entry->skb->data, entry->skb->len, | ||
336 | rt2x00usb_interrupt_rxdone, entry); | ||
337 | |||
338 | status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); | ||
339 | if (status) { | ||
340 | if (status == -ENODEV) | ||
341 | clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); | ||
342 | set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); | ||
343 | rt2x00lib_dmadone(entry); | ||
344 | } | ||
345 | } | ||
346 | |||
264 | void rt2x00usb_kick_queue(struct data_queue *queue) | 347 | void rt2x00usb_kick_queue(struct data_queue *queue) |
265 | { | 348 | { |
266 | switch (queue->qid) { | 349 | switch (queue->qid) { |
@@ -272,6 +355,11 @@ void rt2x00usb_kick_queue(struct data_queue *queue) | |||
272 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, | 355 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, |
273 | rt2x00usb_kick_tx_entry); | 356 | rt2x00usb_kick_tx_entry); |
274 | break; | 357 | break; |
358 | case QID_RX: | ||
359 | if (!rt2x00queue_full(queue)) | ||
360 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, | ||
361 | rt2x00usb_kick_rx_entry); | ||
362 | break; | ||
275 | default: | 363 | default: |
276 | break; | 364 | break; |
277 | } | 365 | } |
@@ -307,7 +395,6 @@ EXPORT_SYMBOL_GPL(rt2x00usb_stop_queue); | |||
307 | static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) | 395 | static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) |
308 | { | 396 | { |
309 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | 397 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; |
310 | unsigned short threshold = queue->threshold; | ||
311 | 398 | ||
312 | WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," | 399 | WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," |
313 | " invoke forced forced reset\n", queue->qid); | 400 | " invoke forced forced reset\n", queue->qid); |
@@ -315,18 +402,8 @@ static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) | |||
315 | /* | 402 | /* |
316 | * Temporarily disable the TX queue, this will force mac80211 | 403 | * Temporarily disable the TX queue, this will force mac80211 |
317 | * to use the other queues until this queue has been restored. | 404 | * to use the other queues until this queue has been restored. |
318 | * | ||
319 | * Set the queue threshold to the queue limit. This prevents the | ||
320 | * queue from being enabled during the txdone handler. | ||
321 | */ | 405 | */ |
322 | queue->threshold = queue->limit; | 406 | rt2x00queue_stop_queue(queue); |
323 | ieee80211_stop_queue(rt2x00dev->hw, queue->qid); | ||
324 | |||
325 | /* | ||
326 | * Kill all entries in the queue, afterwards we need to | ||
327 | * wait a bit for all URBs to be cancelled. | ||
328 | */ | ||
329 | rt2x00usb_stop_queue(queue); | ||
330 | 407 | ||
331 | /* | 408 | /* |
332 | * In case that a driver has overriden the txdone_work | 409 | * In case that a driver has overriden the txdone_work |
@@ -338,8 +415,7 @@ static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) | |||
338 | * The queue has been reset, and mac80211 is allowed to use the | 415 | * The queue has been reset, and mac80211 is allowed to use the |
339 | * queue again. | 416 | * queue again. |
340 | */ | 417 | */ |
341 | queue->threshold = threshold; | 418 | rt2x00queue_start_queue(queue); |
342 | ieee80211_wake_queue(rt2x00dev->hw, queue->qid); | ||
343 | } | 419 | } |
344 | 420 | ||
345 | static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) | 421 | static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) |
@@ -366,73 +442,12 @@ void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) | |||
366 | EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); | 442 | EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); |
367 | 443 | ||
368 | /* | 444 | /* |
369 | * RX data handlers. | ||
370 | */ | ||
371 | static void rt2x00usb_work_rxdone(struct work_struct *work) | ||
372 | { | ||
373 | struct rt2x00_dev *rt2x00dev = | ||
374 | container_of(work, struct rt2x00_dev, rxdone_work); | ||
375 | struct queue_entry *entry; | ||
376 | struct skb_frame_desc *skbdesc; | ||
377 | u8 rxd[32]; | ||
378 | |||
379 | while (!rt2x00queue_empty(rt2x00dev->rx)) { | ||
380 | entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE); | ||
381 | |||
382 | if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | ||
383 | break; | ||
384 | |||
385 | /* | ||
386 | * Fill in desc fields of the skb descriptor | ||
387 | */ | ||
388 | skbdesc = get_skb_frame_desc(entry->skb); | ||
389 | skbdesc->desc = rxd; | ||
390 | skbdesc->desc_len = entry->queue->desc_size; | ||
391 | |||
392 | /* | ||
393 | * Send the frame to rt2x00lib for further processing. | ||
394 | */ | ||
395 | rt2x00lib_rxdone(entry); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | static void rt2x00usb_interrupt_rxdone(struct urb *urb) | ||
400 | { | ||
401 | struct queue_entry *entry = (struct queue_entry *)urb->context; | ||
402 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
403 | |||
404 | if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | ||
405 | return; | ||
406 | |||
407 | /* | ||
408 | * Report the frame as DMA done | ||
409 | */ | ||
410 | rt2x00lib_dmadone(entry); | ||
411 | |||
412 | /* | ||
413 | * Check if the received data is simply too small | ||
414 | * to be actually valid, or if the urb is signaling | ||
415 | * a problem. | ||
416 | */ | ||
417 | if (urb->actual_length < entry->queue->desc_size || urb->status) | ||
418 | set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); | ||
419 | |||
420 | /* | ||
421 | * Schedule the delayed work for reading the RX status | ||
422 | * from the device. | ||
423 | */ | ||
424 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); | ||
425 | } | ||
426 | |||
427 | /* | ||
428 | * Radio handlers | 445 | * Radio handlers |
429 | */ | 446 | */ |
430 | void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) | 447 | void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) |
431 | { | 448 | { |
432 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0, | 449 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0, |
433 | REGISTER_TIMEOUT); | 450 | REGISTER_TIMEOUT); |
434 | |||
435 | rt2x00dev->ops->lib->stop_queue(rt2x00dev->rx); | ||
436 | } | 451 | } |
437 | EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); | 452 | EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); |
438 | 453 | ||
@@ -441,31 +456,10 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); | |||
441 | */ | 456 | */ |
442 | void rt2x00usb_clear_entry(struct queue_entry *entry) | 457 | void rt2x00usb_clear_entry(struct queue_entry *entry) |
443 | { | 458 | { |
444 | struct usb_device *usb_dev = | ||
445 | to_usb_device_intf(entry->queue->rt2x00dev->dev); | ||
446 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | ||
447 | int pipe; | ||
448 | int status; | ||
449 | |||
450 | entry->flags = 0; | 459 | entry->flags = 0; |
451 | 460 | ||
452 | if (entry->queue->qid == QID_RX) { | 461 | if (entry->queue->qid == QID_RX) |
453 | pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); | 462 | rt2x00usb_kick_rx_entry(entry); |
454 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, | ||
455 | entry->skb->data, entry->skb->len, | ||
456 | rt2x00usb_interrupt_rxdone, entry); | ||
457 | |||
458 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | ||
459 | |||
460 | status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); | ||
461 | if (status) { | ||
462 | if (status == -ENODEV) | ||
463 | clear_bit(DEVICE_STATE_PRESENT, | ||
464 | &entry->queue->rt2x00dev->flags); | ||
465 | set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); | ||
466 | rt2x00lib_dmadone(entry); | ||
467 | } | ||
468 | } | ||
469 | } | 463 | } |
470 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); | 464 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); |
471 | 465 | ||