Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(124)

Side by Side Diff: device/usb/usb_device_handle_usbfs.cc

Issue 2274343002: Tell the kernel to discard USB requests when they time out. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « device/usb/usb_device_handle_usbfs.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "device/usb/usb_device_handle_usbfs.h" 5 #include "device/usb/usb_device_handle_usbfs.h"
6 6
7 #if defined(OS_ANDROID) && __ANDROID_API__ < 21 7 #if defined(OS_ANDROID) && __ANDROID_API__ < 21
8 #include <linux/usb_ch9.h> 8 #include <linux/usb_ch9.h>
9 #else 9 #else
10 #include <linux/usb/ch9.h> 10 #include <linux/usb/ch9.h>
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 void RunIsochronousCallback(const std::vector<IsochronousPacket>& packets); 246 void RunIsochronousCallback(const std::vector<IsochronousPacket>& packets);
247 247
248 scoped_refptr<net::IOBuffer> control_transfer_buffer; 248 scoped_refptr<net::IOBuffer> control_transfer_buffer;
249 scoped_refptr<net::IOBuffer> buffer; 249 scoped_refptr<net::IOBuffer> buffer;
250 TransferCallback callback; 250 TransferCallback callback;
251 IsochronousTransferCallback isoc_callback; 251 IsochronousTransferCallback isoc_callback;
252 scoped_refptr<base::SingleThreadTaskRunner> callback_runner; 252 scoped_refptr<base::SingleThreadTaskRunner> callback_runner;
253 base::CancelableClosure timeout_closure; 253 base::CancelableClosure timeout_closure;
254 bool cancelled = false; 254 bool cancelled = false;
255 255
256 // When the URB is |cancelled| these two flags track whether the URB has both
257 // been |discarded| and |reaped| since the possiblity of last-minute
258 // completion makes these two conditions race.
259 bool discarded = false;
260 bool reaped = false;
261
256 // The |urb| field must be the last in the struct so that the extra space 262 // The |urb| field must be the last in the struct so that the extra space
257 // allocated by the overridden new function above extends the length of its 263 // allocated by the overridden new function above extends the length of its
258 // |iso_frame_desc| field. 264 // |iso_frame_desc| field.
259 usbdevfs_urb urb; 265 usbdevfs_urb urb;
260 266
261 private: 267 private:
262 DISALLOW_COPY_AND_ASSIGN(Transfer); 268 DISALLOW_COPY_AND_ASSIGN(Transfer);
263 }; 269 };
264 270
265 UsbDeviceHandleUsbfs::Transfer::Transfer( 271 UsbDeviceHandleUsbfs::Transfer::Transfer(
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 callback_runner->PostTask( 737 callback_runner->PostTask(
732 FROM_HERE, base::Bind(callback, ConvertTransferResult(rc), nullptr, 0)); 738 FROM_HERE, base::Bind(callback, ConvertTransferResult(rc), nullptr, 0));
733 } else { 739 } else {
734 SetUpTimeoutCallback(transfer.get(), timeout); 740 SetUpTimeoutCallback(transfer.get(), timeout);
735 transfers_.push_back(std::move(transfer)); 741 transfers_.push_back(std::move(transfer));
736 } 742 }
737 } 743 }
738 744
739 void UsbDeviceHandleUsbfs::ReapedUrbs(const std::vector<usbdevfs_urb*>& urbs) { 745 void UsbDeviceHandleUsbfs::ReapedUrbs(const std::vector<usbdevfs_urb*>& urbs) {
740 for (auto* urb : urbs) { 746 for (auto* urb : urbs) {
741 Transfer* this_transfer = static_cast<Transfer*>(urb->usercontext); 747 Transfer* transfer = static_cast<Transfer*>(urb->usercontext);
742 DCHECK_EQ(urb, &this_transfer->urb); 748 DCHECK_EQ(urb, &transfer->urb);
743 auto it = std::find_if( 749
744 transfers_.begin(), transfers_.end(), 750 if (transfer->cancelled) {
745 [this_transfer](const std::unique_ptr<Transfer>& transfer) -> bool { 751 transfer->reaped = true;
746 return transfer.get() == this_transfer; 752 if (transfer->discarded)
747 }); 753 RemoveFromTransferList(transfer);
748 DCHECK(it != transfers_.end()); 754 } else {
749 std::unique_ptr<Transfer> transfer = std::move(*it); 755 TransferComplete(RemoveFromTransferList(transfer));
750 transfers_.erase(it); 756 }
751 TransferComplete(std::move(transfer));
752 } 757 }
753 } 758 }
754 759
755 void UsbDeviceHandleUsbfs::TransferComplete( 760 void UsbDeviceHandleUsbfs::TransferComplete(
756 std::unique_ptr<Transfer> transfer) { 761 std::unique_ptr<Transfer> transfer) {
757 if (transfer->cancelled) 762 if (transfer->cancelled)
758 return; 763 return;
759 764
760 // The transfer will soon be freed. Cancel the timeout callback so that the 765 // The transfer will soon be freed. Cancel the timeout callback so that the
761 // raw pointer it holds to |transfer| is not used. 766 // raw pointer it holds to |transfer| is not used.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 packets[i].length = packet_lengths[i]; 828 packets[i].length = packet_lengths[i];
824 packets[i].transferred_length = 0; 829 packets[i].transferred_length = 0;
825 packets[i].status = status; 830 packets[i].status = status;
826 } 831 }
827 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr, packets)); 832 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr, packets));
828 } 833 }
829 834
830 void UsbDeviceHandleUsbfs::SetUpTimeoutCallback(Transfer* transfer, 835 void UsbDeviceHandleUsbfs::SetUpTimeoutCallback(Transfer* transfer,
831 unsigned int timeout) { 836 unsigned int timeout) {
832 if (timeout > 0) { 837 if (timeout > 0) {
833 transfer->timeout_closure.Reset(base::Bind( 838 transfer->timeout_closure.Reset(
834 &UsbDeviceHandleUsbfs::CancelTransfer, transfer, USB_TRANSFER_TIMEOUT)); 839 base::Bind(&UsbDeviceHandleUsbfs::CancelTransfer, this, transfer,
840 USB_TRANSFER_TIMEOUT));
835 task_runner_->PostDelayedTask(FROM_HERE, 841 task_runner_->PostDelayedTask(FROM_HERE,
836 transfer->timeout_closure.callback(), 842 transfer->timeout_closure.callback(),
837 base::TimeDelta::FromMilliseconds(timeout)); 843 base::TimeDelta::FromMilliseconds(timeout));
838 } 844 }
839 } 845 }
840 846
841 // static 847 std::unique_ptr<UsbDeviceHandleUsbfs::Transfer>
848 UsbDeviceHandleUsbfs::RemoveFromTransferList(Transfer* transfer_ptr) {
849 auto it = std::find_if(
850 transfers_.begin(), transfers_.end(),
851 [transfer_ptr](const std::unique_ptr<Transfer>& transfer) -> bool {
852 return transfer.get() == transfer_ptr;
853 });
854 DCHECK(it != transfers_.end());
855 std::unique_ptr<Transfer> transfer = std::move(*it);
856 transfers_.erase(it);
857 return transfer;
858 }
859
842 void UsbDeviceHandleUsbfs::CancelTransfer(Transfer* transfer, 860 void UsbDeviceHandleUsbfs::CancelTransfer(Transfer* transfer,
843 UsbTransferStatus status) { 861 UsbTransferStatus status) {
844 // |transfer| must stay in |transfers_| as it is still being processed by the 862 // |transfer| must stay in |transfers_| as it is still being processed by the
845 // kernel and may be reaped later. 863 // kernel and will be reaped later.
846 transfer->cancelled = true; 864 transfer->cancelled = true;
847 transfer->timeout_closure.Cancel(); 865 transfer->timeout_closure.Cancel();
866
848 if (transfer->urb.type == USBDEVFS_URB_TYPE_ISO) { 867 if (transfer->urb.type == USBDEVFS_URB_TYPE_ISO) {
849 std::vector<IsochronousPacket> packets(transfer->urb.number_of_packets); 868 std::vector<IsochronousPacket> packets(transfer->urb.number_of_packets);
850 for (size_t i = 0; i < packets.size(); ++i) { 869 for (size_t i = 0; i < packets.size(); ++i) {
851 packets[i].length = transfer->urb.iso_frame_desc[i].length; 870 packets[i].length = transfer->urb.iso_frame_desc[i].length;
852 packets[i].transferred_length = 0; 871 packets[i].transferred_length = 0;
853 packets[i].status = status; 872 packets[i].status = status;
854 } 873 }
855 transfer->RunIsochronousCallback(packets); 874 transfer->RunIsochronousCallback(packets);
856 } else { 875 } else {
857 transfer->RunCallback(status, 0); 876 transfer->RunCallback(status, 0);
858 } 877 }
878
879 blocking_task_runner_->PostTask(
880 FROM_HERE,
881 base::Bind(&UsbDeviceHandleUsbfs::DiscardUrbBlocking, this, transfer));
882 }
883
884 void UsbDeviceHandleUsbfs::DiscardUrbBlocking(Transfer* transfer) {
885 if (fd_.is_valid())
886 HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_DISCARDURB, &transfer->urb));
887
888 task_runner_->PostTask(
889 FROM_HERE,
890 base::Bind(&UsbDeviceHandleUsbfs::UrbDiscarded, this, transfer));
891 }
892
893 void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) {
894 transfer->discarded = true;
895 if (transfer->reaped)
896 RemoveFromTransferList(transfer);
859 } 897 }
860 898
861 } // namespace device 899 } // namespace device
OLDNEW
« no previous file with comments | « device/usb/usb_device_handle_usbfs.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698