]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
OvmfPkg/Virtio: Fix few typos
[mirror_edk2.git] / OvmfPkg / VirtioNetDxe / SnpSharedHelpers.c
1 /** @file
2
3 Helper functions used by at least two Simple Network Protocol methods.
4
5 Copyright (C) 2013, Red Hat, Inc.
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include <Library/MemoryAllocationLib.h>
12
13 #include "VirtioNet.h"
14
15 //
16 // The user structure for the ordered collection that will track the mapping
17 // info of the packets queued in TxRing
18 //
19 typedef struct {
20 VOID *Buffer;
21 EFI_PHYSICAL_ADDRESS DeviceAddress; // lookup key for reverse mapping
22 VOID *BufMap;
23 } TX_BUF_MAP_INFO;
24
25 /**
26 Release RX and TX resources on the boundary of the
27 EfiSimpleNetworkInitialized state.
28
29 These functions contribute to rolling back a partial, failed initialization
30 of the virtio-net SNP driver instance, or to shutting down a fully
31 initialized, running instance.
32
33 They are only callable by the VirtioNetInitialize() and the
34 VirtioNetShutdown() SNP methods. See the state diagram in "VirtioNet.h".
35
36 @param[in,out] Dev The VNET_DEV driver instance being shut down, or whose
37 partial, failed initialization is being rolled back.
38 */
39
40 VOID
41 EFIAPI
42 VirtioNetShutdownRx (
43 IN OUT VNET_DEV *Dev
44 )
45 {
46 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);
47 Dev->VirtIo->FreeSharedPages (
48 Dev->VirtIo,
49 Dev->RxBufNrPages,
50 Dev->RxBuf
51 );
52 }
53
54
55 VOID
56 EFIAPI
57 VirtioNetShutdownTx (
58 IN OUT VNET_DEV *Dev
59 )
60 {
61 ORDERED_COLLECTION_ENTRY *Entry, *Entry2;
62 TX_BUF_MAP_INFO *TxBufMapInfo;
63 VOID *UserStruct;
64
65 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->TxSharedReqMap);
66 Dev->VirtIo->FreeSharedPages (
67 Dev->VirtIo,
68 EFI_SIZE_TO_PAGES (sizeof *(Dev->TxSharedReq)),
69 Dev->TxSharedReq
70 );
71
72 for (Entry = OrderedCollectionMin (Dev->TxBufCollection);
73 Entry != NULL;
74 Entry = Entry2) {
75 Entry2 = OrderedCollectionNext (Entry);
76 OrderedCollectionDelete (Dev->TxBufCollection, Entry, &UserStruct);
77 TxBufMapInfo = UserStruct;
78 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, TxBufMapInfo->BufMap);
79 FreePool (TxBufMapInfo);
80 }
81 OrderedCollectionUninit (Dev->TxBufCollection);
82
83 FreePool (Dev->TxFreeStack);
84 }
85
86 /**
87 Release TX and RX VRING resources.
88
89 @param[in,out] Dev The VNET_DEV driver instance which was using
90 the ring.
91 @param[in,out] Ring The virtio ring to clean up.
92 @param[in] RingMap A token return from the VirtioRingMap()
93 */
94 VOID
95 EFIAPI
96 VirtioNetUninitRing (
97 IN OUT VNET_DEV *Dev,
98 IN OUT VRING *Ring,
99 IN VOID *RingMap
100 )
101 {
102 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RingMap);
103 VirtioRingUninit (Dev->VirtIo, Ring);
104 }
105
106
107 /**
108 Map Caller-supplied TxBuf buffer to the device-mapped address
109
110 @param[in] Dev The VNET_DEV driver instance which wants to
111 map the Tx packet.
112 @param[in] Buffer The system physical address of TxBuf
113 @param[in] NumberOfBytes Number of bytes to map
114 @param[out] DeviceAddress The resulting device address for the bus
115 master access.
116
117 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to
118 a lack of resources.
119 @return Status codes from
120 VirtioMapAllBytesInSharedBuffer()
121 @retval EFI_SUCCESS Caller-supplied buffer is successfully mapped.
122 */
123 EFI_STATUS
124 EFIAPI
125 VirtioNetMapTxBuf (
126 IN VNET_DEV *Dev,
127 IN VOID *Buffer,
128 IN UINTN NumberOfBytes,
129 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress
130 )
131 {
132 EFI_STATUS Status;
133 TX_BUF_MAP_INFO *TxBufMapInfo;
134 EFI_PHYSICAL_ADDRESS Address;
135 VOID *Mapping;
136
137 TxBufMapInfo = AllocatePool (sizeof (*TxBufMapInfo));
138 if (TxBufMapInfo == NULL) {
139 return EFI_OUT_OF_RESOURCES;
140 }
141
142 Status = VirtioMapAllBytesInSharedBuffer (
143 Dev->VirtIo,
144 VirtioOperationBusMasterRead,
145 Buffer,
146 NumberOfBytes,
147 &Address,
148 &Mapping
149 );
150 if (EFI_ERROR (Status)) {
151 goto FreeTxBufMapInfo;
152 }
153
154 TxBufMapInfo->Buffer = Buffer;
155 TxBufMapInfo->DeviceAddress = Address;
156 TxBufMapInfo->BufMap = Mapping;
157
158 Status = OrderedCollectionInsert (
159 Dev->TxBufCollection,
160 NULL,
161 TxBufMapInfo
162 );
163 switch (Status) {
164 case EFI_OUT_OF_RESOURCES:
165 goto UnmapTxBuf;
166 case EFI_ALREADY_STARTED:
167 //
168 // This should never happen: it implies
169 //
170 // - an identity-mapping VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer()
171 // implementation -- which is fine,
172 //
173 // - and an SNP client that queues multiple instances of the exact same
174 // buffer address with SNP.Transmit() -- which is undefined behavior,
175 // based on the TxBuf language in UEFI-2.7,
176 // EFI_SIMPLE_NETWORK.GetStatus().
177 //
178 ASSERT (FALSE);
179 Status = EFI_INVALID_PARAMETER;
180 goto UnmapTxBuf;
181 default:
182 ASSERT_EFI_ERROR (Status);
183 break;
184 }
185
186 *DeviceAddress = Address;
187 return EFI_SUCCESS;
188
189 UnmapTxBuf:
190 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
191
192 FreeTxBufMapInfo:
193 FreePool (TxBufMapInfo);
194 return Status;
195 }
196
197 /**
198 Unmap (aka reverse mapping) device mapped TxBuf buffer to the system
199 physical address
200
201 @param[in] Dev The VNET_DEV driver instance which wants to
202 reverse- and unmap the Tx packet.
203 @param[out] Buffer The system physical address of TxBuf
204 @param[in] DeviceAddress The device address for the TxBuf
205
206 @retval EFI_INVALID_PARAMETER The DeviceAddress is not mapped
207 @retval EFI_SUCCESS The TxBuf at DeviceAddress has been unmapped,
208 and Buffer has been set to TxBuf's system
209 physical address.
210
211 */
212 EFI_STATUS
213 EFIAPI
214 VirtioNetUnmapTxBuf (
215 IN VNET_DEV *Dev,
216 OUT VOID **Buffer,
217 IN EFI_PHYSICAL_ADDRESS DeviceAddress
218 )
219 {
220 ORDERED_COLLECTION_ENTRY *Entry;
221 TX_BUF_MAP_INFO *TxBufMapInfo;
222 VOID *UserStruct;
223
224 Entry = OrderedCollectionFind (Dev->TxBufCollection, &DeviceAddress);
225 if (Entry == NULL) {
226 return EFI_INVALID_PARAMETER;
227 }
228
229 OrderedCollectionDelete (Dev->TxBufCollection, Entry, &UserStruct);
230
231 TxBufMapInfo = UserStruct;
232
233 *Buffer = TxBufMapInfo->Buffer;
234 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, TxBufMapInfo->BufMap);
235 FreePool (TxBufMapInfo);
236
237 return EFI_SUCCESS;
238 }
239
240 /**
241 Comparator function for two TX_BUF_MAP_INFO objects.
242
243 @param[in] UserStruct1 Pointer to the first TX_BUF_MAP_INFO object.
244
245 @param[in] UserStruct2 Pointer to the second TX_BUF_MAP_INFO object.
246
247 @retval <0 If UserStruct1 compares less than UserStruct2.
248
249 @retval 0 If UserStruct1 compares equal to UserStruct2.
250
251 @retval >0 If UserStruct1 compares greater than UserStruct2.
252 */
253 INTN
254 EFIAPI
255 VirtioNetTxBufMapInfoCompare (
256 IN CONST VOID *UserStruct1,
257 IN CONST VOID *UserStruct2
258 )
259 {
260 CONST TX_BUF_MAP_INFO *MapInfo1;
261 CONST TX_BUF_MAP_INFO *MapInfo2;
262
263 MapInfo1 = UserStruct1;
264 MapInfo2 = UserStruct2;
265
266 return MapInfo1->DeviceAddress < MapInfo2->DeviceAddress ? -1 :
267 MapInfo1->DeviceAddress > MapInfo2->DeviceAddress ? 1 :
268 0;
269 }
270
271 /**
272 Compare a standalone DeviceAddress against a TX_BUF_MAP_INFO object
273 containing an embedded DeviceAddress.
274
275 @param[in] StandaloneKey Pointer to DeviceAddress, which has type
276 EFI_PHYSICAL_ADDRESS.
277
278 @param[in] UserStruct Pointer to the TX_BUF_MAP_INFO object with the
279 embedded DeviceAddress.
280
281 @retval <0 If StandaloneKey compares less than UserStruct's key.
282
283 @retval 0 If StandaloneKey compares equal to UserStruct's key.
284
285 @retval >0 If StandaloneKey compares greater than UserStruct's key.
286 **/
287 INTN
288 EFIAPI
289 VirtioNetTxBufDeviceAddressCompare (
290 IN CONST VOID *StandaloneKey,
291 IN CONST VOID *UserStruct
292 )
293 {
294 CONST EFI_PHYSICAL_ADDRESS *DeviceAddress;
295 CONST TX_BUF_MAP_INFO *MapInfo;
296
297 DeviceAddress = StandaloneKey;
298 MapInfo = UserStruct;
299
300 return *DeviceAddress < MapInfo->DeviceAddress ? -1 :
301 *DeviceAddress > MapInfo->DeviceAddress ? 1 :
302 0;
303 }