|
@@ -2541,6 +2541,26 @@ static int xhci_endpoint_message ( struct usb_endpoint *ep,
|
2541
|
2541
|
return 0;
|
2542
|
2542
|
}
|
2543
|
2543
|
|
|
2544
|
+/**
|
|
2545
|
+ * Calculate number of TRBs
|
|
2546
|
+ *
|
|
2547
|
+ * @v len Length of data
|
|
2548
|
+ * @v zlp Append a zero-length packet
|
|
2549
|
+ * @ret count Number of transfer descriptors
|
|
2550
|
+ */
|
|
2551
|
+static unsigned int xhci_endpoint_count ( size_t len, int zlp ) {
|
|
2552
|
+ unsigned int count;
|
|
2553
|
+
|
|
2554
|
+ /* Split into 64kB TRBs */
|
|
2555
|
+ count = ( ( len + XHCI_MTU - 1 ) / XHCI_MTU );
|
|
2556
|
+
|
|
2557
|
+ /* Append a zero-length TRB if applicable */
|
|
2558
|
+ if ( zlp || ( count == 0 ) )
|
|
2559
|
+ count++;
|
|
2560
|
+
|
|
2561
|
+ return count;
|
|
2562
|
+}
|
|
2563
|
+
|
2544
|
2564
|
/**
|
2545
|
2565
|
* Enqueue stream transfer
|
2546
|
2566
|
*
|
|
@@ -2552,10 +2572,14 @@ static int xhci_endpoint_message ( struct usb_endpoint *ep,
|
2552
|
2572
|
static int xhci_endpoint_stream ( struct usb_endpoint *ep,
|
2553
|
2573
|
struct io_buffer *iobuf, int zlp ) {
|
2554
|
2574
|
struct xhci_endpoint *endpoint = usb_endpoint_get_hostdata ( ep );
|
2555
|
|
- union xhci_trb trbs[ 1 /* Normal */ + 1 /* Possible zero-length */ ];
|
|
2575
|
+ void *data = iobuf->data;
|
|
2576
|
+ size_t len = iob_len ( iobuf );
|
|
2577
|
+ unsigned int count = xhci_endpoint_count ( len, zlp );
|
|
2578
|
+ union xhci_trb trbs[count];
|
2556
|
2579
|
union xhci_trb *trb = trbs;
|
2557
|
2580
|
struct xhci_trb_normal *normal;
|
2558
|
|
- size_t len = iob_len ( iobuf );
|
|
2581
|
+ unsigned int i;
|
|
2582
|
+ size_t trb_len;
|
2559
|
2583
|
int rc;
|
2560
|
2584
|
|
2561
|
2585
|
/* Profile stream transfers */
|
|
@@ -2563,20 +2587,30 @@ static int xhci_endpoint_stream ( struct usb_endpoint *ep,
|
2563
|
2587
|
|
2564
|
2588
|
/* Construct normal TRBs */
|
2565
|
2589
|
memset ( &trbs, 0, sizeof ( trbs ) );
|
2566
|
|
- normal = &(trb++)->normal;
|
2567
|
|
- normal->data = cpu_to_le64 ( virt_to_phys ( iobuf->data ) );
|
2568
|
|
- normal->len = cpu_to_le32 ( len );
|
2569
|
|
- normal->type = XHCI_TRB_NORMAL;
|
2570
|
|
- if ( zlp ) {
|
2571
|
|
- normal->flags = XHCI_TRB_CH;
|
2572
|
|
- normal = &(trb++)->normal;
|
|
2590
|
+ for ( i = 0 ; i < count ; i ++ ) {
|
|
2591
|
+
|
|
2592
|
+ /* Calculate TRB length */
|
|
2593
|
+ trb_len = XHCI_MTU;
|
|
2594
|
+ if ( trb_len > len )
|
|
2595
|
+ trb_len = len;
|
|
2596
|
+
|
|
2597
|
+ /* Construct normal TRB */
|
|
2598
|
+ normal = &trb->normal;
|
|
2599
|
+ normal->data = cpu_to_le64 ( virt_to_phys ( data ) );
|
|
2600
|
+ normal->len = cpu_to_le32 ( trb_len );
|
2573
|
2601
|
normal->type = XHCI_TRB_NORMAL;
|
|
2602
|
+ normal->flags = XHCI_TRB_CH;
|
|
2603
|
+
|
|
2604
|
+ /* Move to next TRB */
|
|
2605
|
+ data += trb_len;
|
|
2606
|
+ len -= trb_len;
|
|
2607
|
+ trb++;
|
2574
|
2608
|
}
|
2575
|
|
- normal->flags = XHCI_TRB_IOC;
|
|
2609
|
+ trb[-1].normal.flags = XHCI_TRB_IOC;
|
2576
|
2610
|
|
2577
|
2611
|
/* Enqueue TRBs */
|
2578
|
2612
|
if ( ( rc = xhci_enqueue_multi ( &endpoint->ring, iobuf, trbs,
|
2579
|
|
- ( trb - trbs ) ) ) != 0 )
|
|
2613
|
+ count ) ) != 0 )
|
2580
|
2614
|
return rc;
|
2581
|
2615
|
|
2582
|
2616
|
/* Ring the doorbell */
|