summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2011-04-11 07:57:54 (GMT)
committerStefan Richter <stefanr@s5r6.in-berlin.de>2011-04-19 18:00:11 (GMT)
commitda28947e7e3602669e27d5e9ce787436ed662fa4 (patch)
tree33b3cfb25fddbe12b4f19f02ce3253872eed2436
parentecf8328e59447b83a1f79628487e0e9f8801db84 (diff)
downloadlinux-fsl-qoriq-da28947e7e3602669e27d5e9ce787436ed662fa4.tar.xz
firewire: ohci: avoid separate DMA mapping for small AT payloads
For AT packet payloads of up to eight bytes, we have enough unused space in the DMA descriptors list so that we can put a copy of the payload there and thus avoid having to create a separate streaming DMA mapping for the payload buffer. In a CPU-bound microbenchmark that just sends 8-byte packets, bandwidth was measured to increase by 5.7 %, from 1009 KB/s to 1067 KB/s. In practice, the only performance-sensitive usage of small asynchronous packets is the SBP-2 driver's write to the ORB_POINTER register during SCSI command submission. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r--drivers/firewire/ohci.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index dfb3cb7..435ed80 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1218,6 +1218,7 @@ static void context_stop(struct context *ctx)
}
struct driver_data {
+ u8 inline_data[8];
struct fw_packet *packet;
};
@@ -1301,20 +1302,28 @@ static int at_context_queue_packet(struct context *ctx,
return -1;
}
+ BUILD_BUG_ON(sizeof(struct driver_data) > sizeof(struct descriptor));
driver_data = (struct driver_data *) &d[3];
driver_data->packet = packet;
packet->driver_data = driver_data;
if (packet->payload_length > 0) {
- payload_bus =
- dma_map_single(ohci->card.device, packet->payload,
- packet->payload_length, DMA_TO_DEVICE);
- if (dma_mapping_error(ohci->card.device, payload_bus)) {
- packet->ack = RCODE_SEND_ERROR;
- return -1;
+ if (packet->payload_length > sizeof(driver_data->inline_data)) {
+ payload_bus = dma_map_single(ohci->card.device,
+ packet->payload,
+ packet->payload_length,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(ohci->card.device, payload_bus)) {
+ packet->ack = RCODE_SEND_ERROR;
+ return -1;
+ }
+ packet->payload_bus = payload_bus;
+ packet->payload_mapped = true;
+ } else {
+ memcpy(driver_data->inline_data, packet->payload,
+ packet->payload_length);
+ payload_bus = d_bus + 3 * sizeof(*d);
}
- packet->payload_bus = payload_bus;
- packet->payload_mapped = true;
d[2].req_count = cpu_to_le16(packet->payload_length);
d[2].data_address = cpu_to_le32(payload_bus);