summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorb14ckcat <b14ckcat@protonmail.com>2022-06-26 18:33:53 -0400
committerLinus Groh <mail@linusgroh.de>2022-07-03 01:15:07 +0200
commit143339767b330bfe1dac820b70ca1c519fec5f55 (patch)
treee3f4e835594e8abee4b901d4173eb3c60802075d /Kernel
parent5f726ace536cf5e4d71d5d5b1852da0c6aa92ffa (diff)
downloadserenity-143339767b330bfe1dac820b70ca1c519fec5f55.zip
Kernel/USB: Move buffer allocation from USB transfer to USB pipe
Currently when allocating buffers for USB transfers, it is done once for every transfer rather than once upon creation of the USB device. This commit changes that by moving allocation of buffers to the USB Pipe class where they can be reused.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Bus/USB/USBPipe.cpp20
-rw-r--r--Kernel/Bus/USB/USBPipe.h11
-rw-r--r--Kernel/Bus/USB/USBTransfer.cpp13
-rw-r--r--Kernel/Bus/USB/USBTransfer.h20
4 files changed, 37 insertions, 27 deletions
diff --git a/Kernel/Bus/USB/USBPipe.cpp b/Kernel/Bus/USB/USBPipe.cpp
index 982cc14093..6b0ff1f3cd 100644
--- a/Kernel/Bus/USB/USBPipe.cpp
+++ b/Kernel/Bus/USB/USBPipe.cpp
@@ -14,10 +14,11 @@ namespace Kernel::USB {
ErrorOr<NonnullOwnPtr<Pipe>> Pipe::try_create_pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, i8 device_address, u8 poll_interval)
{
- return adopt_nonnull_own_or_enomem(new (nothrow) Pipe(controller, type, direction, endpoint_address, max_packet_size, poll_interval, device_address));
+ auto dma_region = TRY(MM.allocate_kernel_region(PAGE_SIZE, "USB device DMA buffer", Memory::Region::Access::ReadWrite));
+ return adopt_nonnull_own_or_enomem(new (nothrow) Pipe(controller, type, direction, endpoint_address, max_packet_size, poll_interval, device_address, move(dma_region)));
}
-Pipe::Pipe(USBController const& controller, Type type, Pipe::Direction direction, u16 max_packet_size)
+Pipe::Pipe(USBController const& controller, Type type, Pipe::Direction direction, u16 max_packet_size, NonnullOwnPtr<Memory::Region> dma_buffer)
: m_controller(controller)
, m_type(type)
, m_direction(direction)
@@ -25,18 +26,20 @@ Pipe::Pipe(USBController const& controller, Type type, Pipe::Direction direction
, m_max_packet_size(max_packet_size)
, m_poll_interval(0)
, m_data_toggle(false)
+ , m_dma_buffer(move(dma_buffer))
{
}
-Pipe::Pipe(USBController const& controller, Type type, Direction direction, USBEndpointDescriptor& endpoint [[maybe_unused]])
+Pipe::Pipe(USBController const& controller, Type type, Direction direction, USBEndpointDescriptor& endpoint [[maybe_unused]], NonnullOwnPtr<Memory::Region> dma_buffer)
: m_controller(controller)
, m_type(type)
, m_direction(direction)
+ , m_dma_buffer(move(dma_buffer))
{
// TODO: decode endpoint structure
}
-Pipe::Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address)
+Pipe::Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address, NonnullOwnPtr<Memory::Region> dma_buffer)
: m_controller(controller)
, m_type(type)
, m_direction(direction)
@@ -45,11 +48,14 @@ Pipe::Pipe(USBController const& controller, Type type, Direction direction, u8 e
, m_max_packet_size(max_packet_size)
, m_poll_interval(poll_interval)
, m_data_toggle(false)
+ , m_dma_buffer(move(dma_buffer))
{
}
ErrorOr<size_t> Pipe::control_transfer(u8 request_type, u8 request, u16 value, u16 index, u16 length, void* data)
{
+ MutexLocker lock(m_dma_buffer_lock);
+
USBRequestData usb_request;
usb_request.request_type = request_type;
@@ -58,7 +64,7 @@ ErrorOr<size_t> Pipe::control_transfer(u8 request_type, u8 request, u16 value, u
usb_request.index = index;
usb_request.length = length;
- auto transfer = TRY(Transfer::try_create(*this, length));
+ auto transfer = TRY(Transfer::try_create(*this, length, *m_dma_buffer));
transfer->set_setup_packet(usb_request);
dbgln_if(USB_DEBUG, "Pipe: Transfer allocated @ {}", transfer->buffer_physical());
@@ -74,8 +80,10 @@ ErrorOr<size_t> Pipe::control_transfer(u8 request_type, u8 request, u16 value, u
ErrorOr<size_t> Pipe::bulk_transfer(u16 length, void* data)
{
+ MutexLocker lock(m_dma_buffer_lock);
+
size_t transfer_length = 0;
- auto transfer = TRY(Transfer::try_create(*this, length));
+ auto transfer = TRY(Transfer::try_create(*this, length, *m_dma_buffer));
if (m_direction == Direction::In) {
dbgln_if(USB_DEBUG, "Pipe: Bulk in transfer allocated @ {}", transfer->buffer_physical());
diff --git a/Kernel/Bus/USB/USBPipe.h b/Kernel/Bus/USB/USBPipe.h
index 0371f80517..2d43203984 100644
--- a/Kernel/Bus/USB/USBPipe.h
+++ b/Kernel/Bus/USB/USBPipe.h
@@ -9,6 +9,7 @@
#include <AK/OwnPtr.h>
#include <AK/Types.h>
#include <Kernel/Bus/USB/USBDescriptors.h>
+#include <Kernel/Locking/Mutex.h>
#include <Kernel/Memory/Region.h>
namespace Kernel::USB {
@@ -59,9 +60,9 @@ public:
ErrorOr<size_t> control_transfer(u8 request_type, u8 request, u16 value, u16 index, u16 length, void* data);
ErrorOr<size_t> bulk_transfer(u16 length, void* data);
- Pipe(USBController const& controller, Type type, Direction direction, u16 max_packet_size);
- Pipe(USBController const& controller, Type type, Direction direction, USBEndpointDescriptor& endpoint);
- Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address);
+ Pipe(USBController const& controller, Type type, Direction direction, u16 max_packet_size, NonnullOwnPtr<Memory::Region> dma_buffer);
+ Pipe(USBController const& controller, Type type, Direction direction, USBEndpointDescriptor& endpoint, NonnullOwnPtr<Memory::Region> dma_buffer);
+ Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address, NonnullOwnPtr<Memory::Region> dma_buffer);
private:
friend class Device;
@@ -77,5 +78,9 @@ private:
u16 m_max_packet_size { 0 }; // Max packet size for this pipe
u8 m_poll_interval { 0 }; // Polling interval (in frames)
bool m_data_toggle { false }; // Data toggle for stuffing bit
+
+ Mutex m_dma_buffer_lock { "USB pipe mutex" };
+
+ NonnullOwnPtr<Memory::Region> m_dma_buffer;
};
}
diff --git a/Kernel/Bus/USB/USBTransfer.cpp b/Kernel/Bus/USB/USBTransfer.cpp
index e664e7ced9..4f489389f2 100644
--- a/Kernel/Bus/USB/USBTransfer.cpp
+++ b/Kernel/Bus/USB/USBTransfer.cpp
@@ -9,17 +9,14 @@
namespace Kernel::USB {
-ErrorOr<NonnullRefPtr<Transfer>> Transfer::try_create(Pipe& pipe, u16 length)
+ErrorOr<NonnullRefPtr<Transfer>> Transfer::try_create(Pipe& pipe, u16 length, Memory::Region& dma_buffer)
{
- // Initialize data buffer for transfer
- // This will definitely need to be refactored in the future, I doubt this will scale well...
- auto region = TRY(MM.allocate_kernel_region(PAGE_SIZE, "USB Transfer Buffer", Memory::Region::Access::ReadWrite));
- return adopt_nonnull_ref_or_enomem(new (nothrow) Transfer(pipe, length, move(region)));
+ return adopt_nonnull_ref_or_enomem(new (nothrow) Transfer(pipe, length, dma_buffer));
}
-Transfer::Transfer(Pipe& pipe, u16 len, NonnullOwnPtr<Memory::Region> data_buffer)
+Transfer::Transfer(Pipe& pipe, u16 len, Memory::Region& dma_buffer)
: m_pipe(pipe)
- , m_data_buffer(move(data_buffer))
+ , m_dma_buffer(dma_buffer)
, m_transfer_data_size(len)
{
}
@@ -45,7 +42,7 @@ void Transfer::set_setup_packet(USBRequestData const& request)
ErrorOr<void> Transfer::write_buffer(u16 len, void* data)
{
- VERIFY(len <= m_data_buffer->size());
+ VERIFY(len <= m_dma_buffer.size());
m_transfer_data_size = len;
memcpy(buffer().as_ptr(), data, len);
diff --git a/Kernel/Bus/USB/USBTransfer.h b/Kernel/Bus/USB/USBTransfer.h
index 914a3c6d72..fe8e7d6713 100644
--- a/Kernel/Bus/USB/USBTransfer.h
+++ b/Kernel/Bus/USB/USBTransfer.h
@@ -19,7 +19,7 @@ namespace Kernel::USB {
class Transfer : public RefCounted<Transfer> {
public:
- static ErrorOr<NonnullRefPtr<Transfer>> try_create(Pipe&, u16 length);
+ static ErrorOr<NonnullRefPtr<Transfer>> try_create(Pipe&, u16 length, Memory::Region& dma_buffer);
Transfer() = delete;
~Transfer();
@@ -34,20 +34,20 @@ public:
USBRequestData const& request() const { return m_request; }
Pipe const& pipe() const { return m_pipe; }
Pipe& pipe() { return m_pipe; }
- VirtualAddress buffer() const { return m_data_buffer->vaddr(); }
- PhysicalAddress buffer_physical() const { return m_data_buffer->physical_page(0)->paddr(); }
+ VirtualAddress buffer() const { return m_dma_buffer.vaddr(); }
+ PhysicalAddress buffer_physical() const { return m_dma_buffer.physical_page(0)->paddr(); }
u16 transfer_data_size() const { return m_transfer_data_size; }
bool complete() const { return m_complete; }
bool error_occurred() const { return m_error_occurred; }
private:
- Transfer(Pipe& pipe, u16 len, NonnullOwnPtr<Memory::Region>);
- Pipe& m_pipe; // Pipe that initiated this transfer
- USBRequestData m_request; // USB request
- NonnullOwnPtr<Memory::Region> m_data_buffer; // DMA Data buffer for transaction
- u16 m_transfer_data_size { 0 }; // Size of the transfer's data stage
- bool m_complete { false }; // Has this transfer been completed?
- bool m_error_occurred { false }; // Did an error occur during this transfer?
+ Transfer(Pipe& pipe, u16 len, Memory::Region& dma_buffer);
+ Pipe& m_pipe; // Pipe that initiated this transfer
+ Memory::Region& m_dma_buffer; // DMA buffer
+ USBRequestData m_request; // USB request
+ u16 m_transfer_data_size { 0 }; // Size of the transfer's data stage
+ bool m_complete { false }; // Has this transfer been completed?
+ bool m_error_occurred { false }; // Did an error occur during this transfer?
};
}