| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
|---|
| 3 | 4 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> |
|---|
| 4 | 5 | <http://rt2x00.serialmonkey.com> |
|---|
| 5 | 6 | |
|---|
| 6 | | - This program is free software; you can redistribute it and/or modify |
|---|
| 7 | | - it under the terms of the GNU General Public License as published by |
|---|
| 8 | | - the Free Software Foundation; either version 2 of the License, or |
|---|
| 9 | | - (at your option) any later version. |
|---|
| 10 | | - |
|---|
| 11 | | - This program is distributed in the hope that it will be useful, |
|---|
| 12 | | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 13 | | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 14 | | - GNU General Public License for more details. |
|---|
| 15 | | - |
|---|
| 16 | | - You should have received a copy of the GNU General Public License |
|---|
| 17 | | - along with this program; if not, see <http://www.gnu.org/licenses/>. |
|---|
| 18 | 7 | */ |
|---|
| 19 | 8 | |
|---|
| 20 | 9 | /* |
|---|
| .. | .. |
|---|
| 30 | 19 | |
|---|
| 31 | 20 | #include "rt2x00.h" |
|---|
| 32 | 21 | #include "rt2x00usb.h" |
|---|
| 22 | + |
|---|
| 23 | +static bool rt2x00usb_check_usb_error(struct rt2x00_dev *rt2x00dev, int status) |
|---|
| 24 | +{ |
|---|
| 25 | + if (status == -ENODEV || status == -ENOENT) |
|---|
| 26 | + return true; |
|---|
| 27 | + |
|---|
| 28 | + if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) |
|---|
| 29 | + return false; |
|---|
| 30 | + |
|---|
| 31 | + if (status == -EPROTO || status == -ETIMEDOUT) |
|---|
| 32 | + rt2x00dev->num_proto_errs++; |
|---|
| 33 | + else |
|---|
| 34 | + rt2x00dev->num_proto_errs = 0; |
|---|
| 35 | + |
|---|
| 36 | + if (rt2x00dev->num_proto_errs > 3) |
|---|
| 37 | + return true; |
|---|
| 38 | + |
|---|
| 39 | + return false; |
|---|
| 40 | +} |
|---|
| 33 | 41 | |
|---|
| 34 | 42 | /* |
|---|
| 35 | 43 | * Interfacing with the HW. |
|---|
| .. | .. |
|---|
| 57 | 65 | if (status >= 0) |
|---|
| 58 | 66 | return 0; |
|---|
| 59 | 67 | |
|---|
| 60 | | - if (status == -ENODEV || status == -ENOENT) { |
|---|
| 68 | + if (rt2x00usb_check_usb_error(rt2x00dev, status)) { |
|---|
| 61 | 69 | /* Device has disappeared. */ |
|---|
| 62 | 70 | clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); |
|---|
| 63 | 71 | break; |
|---|
| .. | .. |
|---|
| 321 | 329 | |
|---|
| 322 | 330 | status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); |
|---|
| 323 | 331 | if (status) { |
|---|
| 324 | | - if (status == -ENODEV || status == -ENOENT) |
|---|
| 332 | + if (rt2x00usb_check_usb_error(rt2x00dev, status)) |
|---|
| 325 | 333 | clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); |
|---|
| 326 | 334 | set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); |
|---|
| 327 | 335 | rt2x00lib_dmadone(entry); |
|---|
| .. | .. |
|---|
| 344 | 352 | while (!rt2x00queue_empty(rt2x00dev->rx)) { |
|---|
| 345 | 353 | entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE); |
|---|
| 346 | 354 | |
|---|
| 347 | | - if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || |
|---|
| 348 | | - !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) |
|---|
| 355 | + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
|---|
| 349 | 356 | break; |
|---|
| 350 | 357 | |
|---|
| 351 | 358 | /* |
|---|
| .. | .. |
|---|
| 367 | 374 | struct queue_entry *entry = (struct queue_entry *)urb->context; |
|---|
| 368 | 375 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
|---|
| 369 | 376 | |
|---|
| 370 | | - if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
|---|
| 377 | + if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
|---|
| 371 | 378 | return; |
|---|
| 372 | | - |
|---|
| 373 | | - /* |
|---|
| 374 | | - * Report the frame as DMA done |
|---|
| 375 | | - */ |
|---|
| 376 | | - rt2x00lib_dmadone(entry); |
|---|
| 377 | 379 | |
|---|
| 378 | 380 | /* |
|---|
| 379 | 381 | * Check if the received data is simply too small |
|---|
| .. | .. |
|---|
| 384 | 386 | set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); |
|---|
| 385 | 387 | |
|---|
| 386 | 388 | /* |
|---|
| 387 | | - * Schedule the delayed work for reading the RX status |
|---|
| 388 | | - * from the device. |
|---|
| 389 | + * Report the frame as DMA done |
|---|
| 390 | + */ |
|---|
| 391 | + rt2x00lib_dmadone(entry); |
|---|
| 392 | + |
|---|
| 393 | + /* |
|---|
| 394 | + * Schedule the delayed work for processing RX data |
|---|
| 389 | 395 | */ |
|---|
| 390 | 396 | queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); |
|---|
| 391 | 397 | } |
|---|
| .. | .. |
|---|
| 397 | 403 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
|---|
| 398 | 404 | int status; |
|---|
| 399 | 405 | |
|---|
| 400 | | - if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || |
|---|
| 401 | | - test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) |
|---|
| 406 | + if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
|---|
| 402 | 407 | return false; |
|---|
| 403 | 408 | |
|---|
| 404 | 409 | rt2x00lib_dmastart(entry); |
|---|
| .. | .. |
|---|
| 410 | 415 | |
|---|
| 411 | 416 | status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); |
|---|
| 412 | 417 | if (status) { |
|---|
| 413 | | - if (status == -ENODEV || status == -ENOENT) |
|---|
| 418 | + if (rt2x00usb_check_usb_error(rt2x00dev, status)) |
|---|
| 414 | 419 | clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); |
|---|
| 415 | 420 | set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); |
|---|
| 416 | 421 | rt2x00lib_dmadone(entry); |
|---|
| .. | .. |
|---|
| 520 | 525 | |
|---|
| 521 | 526 | static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) |
|---|
| 522 | 527 | { |
|---|
| 523 | | - rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n", |
|---|
| 528 | + rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced reset\n", |
|---|
| 524 | 529 | queue->qid); |
|---|
| 525 | 530 | |
|---|
| 526 | 531 | rt2x00queue_stop_queue(queue); |
|---|
| .. | .. |
|---|
| 884 | 889 | struct ieee80211_hw *hw = usb_get_intfdata(usb_intf); |
|---|
| 885 | 890 | struct rt2x00_dev *rt2x00dev = hw->priv; |
|---|
| 886 | 891 | |
|---|
| 887 | | - return rt2x00lib_suspend(rt2x00dev, state); |
|---|
| 892 | + return rt2x00lib_suspend(rt2x00dev); |
|---|
| 888 | 893 | } |
|---|
| 889 | 894 | EXPORT_SYMBOL_GPL(rt2x00usb_suspend); |
|---|
| 890 | 895 | |
|---|