source: mainline/uspace/lib/usbhost/src/bandwidth.c@ b357377

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b357377 was b357377, checked in by Ondřej Hlavatý <aearsis@…>, 7 years ago

usbhost: make bandwidth accounting a usb2_bus-thing

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 * Copyright (c) 2011 Jan Vesely
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28/** @addtogroup libusbhost
29 * @{
30 */
31/** @file
32 *
33 * Bandwidth calculation functions. Shared among uhci, ohci and ehci drivers.
34 */
35
36#include <assert.h>
37#include <stdlib.h>
38
39#include "endpoint.h"
40#include "bus.h"
41
42#include "bandwidth.h"
43
44/** Bytes per second in FULL SPEED */
45#define BANDWIDTH_TOTAL_USB11 (12000000 / 8)
46/** 90% of total bandwidth is available for periodic transfers */
47#define BANDWIDTH_AVAILABLE_USB11 ((BANDWIDTH_TOTAL_USB11 * 9) / 10)
48
49/**
50 * Calculate bandwidth that needs to be reserved for communication with EP.
51 * Calculation follows USB 1.1 specification.
52 *
53 * @param ep An endpoint for which the bandwidth is to be counted
54 */
55static size_t bandwidth_count_usb11(endpoint_t *ep)
56{
57 assert(ep);
58 assert(ep->device);
59
60 const usb_transfer_type_t type = ep->transfer_type;
61
62 /* We care about bandwidth only for interrupt and isochronous. */
63 if ((type != USB_TRANSFER_INTERRUPT)
64 && (type != USB_TRANSFER_ISOCHRONOUS)) {
65 return 0;
66 }
67
68 const size_t max_packet_size = ep->max_packet_size;
69 const size_t packet_count = ep->packets_per_uframe;
70
71 /* TODO: It may be that ISO and INT transfers use only one packet per
72 * transaction, but I did not find text in USB spec to confirm this */
73 /* NOTE: All data packets will be considered to be max_packet_size */
74 switch (ep->device->speed)
75 {
76 case USB_SPEED_LOW:
77 assert(type == USB_TRANSFER_INTERRUPT);
78 /* Protocol overhead 13B
79 * (3 SYNC bytes, 3 PID bytes, 2 Endpoint + CRC bytes, 2
80 * CRC bytes, and a 3-byte interpacket delay)
81 * see USB spec page 45-46. */
82 /* Speed penalty 8: low speed is 8-times slower*/
83 return packet_count * (13 + max_packet_size) * 8;
84 case USB_SPEED_FULL:
85 /* Interrupt transfer overhead see above
86 * or page 45 of USB spec */
87 if (type == USB_TRANSFER_INTERRUPT)
88 return packet_count * (13 + max_packet_size);
89
90 assert(type == USB_TRANSFER_ISOCHRONOUS);
91 /* Protocol overhead 9B
92 * (2 SYNC bytes, 2 PID bytes, 2 Endpoint + CRC bytes, 2 CRC
93 * bytes, and a 1-byte interpacket delay)
94 * see USB spec page 42 */
95 return packet_count * (9 + max_packet_size);
96 default:
97 return 0;
98 }
99}
100
101const bandwidth_accounting_t bandwidth_accounting_usb11 = {
102 .available_bandwidth = BANDWIDTH_AVAILABLE_USB11,
103 .count_bw = &bandwidth_count_usb11,
104};
105
106/** Number of nanoseconds in one microframe */
107#define BANDWIDTH_TOTAL_USB2 (125000)
108/** 90% of total bandwidth is available for periodic transfers */
109#define BANDWIDTH_AVAILABLE_USB2 ((BANDWIDTH_TOTAL_USB2 * 9) / 10)
110
111/**
112 * Calculate bandwidth that needs to be reserved for communication with EP.
113 * Calculation follows USB 2.0 specification, chapter 5.11.3.
114 *
115 * FIXME: Interrupt transfers shall be probably divided by their polling interval.
116 *
117 * @param ep An endpoint for which the bandwidth is to be counted
118 * @return Number of nanoseconds transaction with @c size bytes payload will
119 * take.
120 */
121static size_t bandwidth_count_usb2(endpoint_t *ep)
122{
123 assert(ep);
124 assert(ep->device);
125
126 const usb_transfer_type_t type = ep->transfer_type;
127
128 /* We care about bandwidth only for interrupt and isochronous. */
129 if ((type != USB_TRANSFER_INTERRUPT)
130 && (type != USB_TRANSFER_ISOCHRONOUS)) {
131 return 0;
132 }
133
134 // FIXME: Come up with some upper bound for these (in ns).
135 const size_t host_delay = 0;
136 const size_t hub_ls_setup = 0;
137
138 // Approx. Floor(3.167 + BitStuffTime(Data_bc))
139 const size_t base_time = (ep->max_transfer_size * 8 + 19) / 6;
140
141 switch (ep->device->speed) {
142 case USB_SPEED_LOW:
143 if (ep->direction == USB_DIRECTION_IN)
144 return 64060 + (2 * hub_ls_setup) + (677 * base_time) + host_delay;
145 else
146 return 64107 + (2 * hub_ls_setup) + (667 * base_time) + host_delay;
147
148 case USB_SPEED_FULL:
149 if (ep->transfer_type == USB_TRANSFER_INTERRUPT)
150 return 9107 + 84 * base_time + host_delay;
151
152 if (ep->direction == USB_DIRECTION_IN)
153 return 7268 + 84 * base_time + host_delay;
154 else
155 return 6265 + 84 * base_time + host_delay;
156
157 case USB_SPEED_HIGH:
158 if (ep->transfer_type == USB_TRANSFER_INTERRUPT)
159 return (3648 + 25 * base_time + 11) / 12 + host_delay;
160 else
161 return (5280 + 25 * base_time + 11) / 12 + host_delay;
162
163 default:
164 return 0;
165 }
166}
167
168const bandwidth_accounting_t bandwidth_accounting_usb2 = {
169 .available_bandwidth = BANDWIDTH_AVAILABLE_USB2,
170 .count_bw = &bandwidth_count_usb2,
171};
Note: See TracBrowser for help on using the repository browser.