]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
OvmfPkg: Apply uncrustify changes
[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 VOID
40 EFIAPI
41 VirtioNetShutdownRx (
42 IN OUT VNET_DEV *Dev
43 )
44 {
45 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);
46 Dev->VirtIo->FreeSharedPages (
47 Dev->VirtIo,
48 Dev->RxBufNrPages,
49 Dev->RxBuf
50 );
51 }
52
53 VOID
54 EFIAPI
55 VirtioNetShutdownTx (
56 IN OUT VNET_DEV *Dev
57 )
58 {
59 ORDERED_COLLECTION_ENTRY *Entry, *Entry2;
60 TX_BUF_MAP_INFO *TxBufMapInfo;
61 VOID *UserStruct;
62
63 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->TxSharedReqMap);
64 Dev->VirtIo->FreeSharedPages (
65 Dev->VirtIo,
66 EFI_SIZE_TO_PAGES (sizeof *(Dev->TxSharedReq)),
67 Dev->TxSharedReq
68 );
69
70 for (Entry = OrderedCollectionMin (Dev->TxBufCollection);
71 Entry != NULL;
72 Entry = Entry2)
73 {
74 Entry2 = OrderedCollectionNext (Entry);
75 OrderedCollectionDelete (Dev->TxBufCollection, Entry, &UserStruct);
76 TxBufMapInfo = UserStruct;
77 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, TxBufMapInfo->BufMap);
78 FreePool (TxBufMapInfo);
79 }
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 Map Caller-supplied TxBuf buffer to the device-mapped address
108
109 @param[in] Dev The VNET_DEV driver instance which wants to
110 map the Tx packet.
111 @param[in] Buffer The system physical address of TxBuf
112 @param[in] NumberOfBytes Number of bytes to map
113 @param[out] DeviceAddress The resulting device address for the bus
114 master access.
115
116 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to
117 a lack of resources.
118 @return Status codes from
119 VirtioMapAllBytesInSharedBuffer()
120 @retval EFI_SUCCESS Caller-supplied buffer is successfully mapped.
121 */
122 EFI_STATUS
123 EFIAPI
124 VirtioNetMapTxBuf (
125 IN VNET_DEV *Dev,
126 IN VOID *Buffer,
127 IN UINTN NumberOfBytes,
128 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress
129 )
130 {
131 EFI_STATUS Status;
132 TX_BUF_MAP_INFO *TxBufMapInfo;
133 EFI_PHYSICAL_ADDRESS Address;
134 VOID *Mapping;
135
136 TxBufMapInfo = AllocatePool (sizeof (*TxBufMapInfo));
137 if (TxBufMapInfo == NULL) {
138 return EFI_OUT_OF_RESOURCES;
139 }
140
141 Status = VirtioMapAllBytesInSharedBuffer (
142 Dev->VirtIo,
143 VirtioOperationBusMasterRead,
144 Buffer,
145 NumberOfBytes,
146 &Address,
147 &Mapping
148 );
149 if (EFI_ERROR (Status)) {
150 goto FreeTxBufMapInfo;
151 }
152
153 TxBufMapInfo->Buffer = Buffer;
154 TxBufMapInfo->DeviceAddress = Address;
155 TxBufMapInfo->BufMap = Mapping;
156
157 Status = OrderedCollectionInsert (
158 Dev->TxBufCollection,
159 NULL,
160 TxBufMapInfo
161 );
162 switch (Status) {
163 case EFI_OUT_OF_RESOURCES:
164 goto UnmapTxBuf;
165 case EFI_ALREADY_STARTED:
166 //
167 // This should never happen: it implies
168 //
169 // - an identity-mapping VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer()
170 // implementation -- which is fine,
171 //
172 // - and an SNP client that queues multiple instances of the exact same
173 // buffer address with SNP.Transmit() -- which is undefined behavior,
174 // based on the TxBuf language in UEFI-2.7,
175 // EFI_SIMPLE_NETWORK.GetStatus().
176 //
177 ASSERT (FALSE);
178 Status = EFI_INVALID_PARAMETER;
179 goto UnmapTxBuf;
180 default:
181 ASSERT_EFI_ERROR (Status);
182 break;
183 }
184
185 *DeviceAddress = Address;
186 return EFI_SUCCESS;
187
188 UnmapTxBuf:
189 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
190
191 FreeTxBufMapInfo:
192 FreePool (TxBufMapInfo);
193 return Status;
194 }
195
196 /**
197 Unmap (aka reverse mapping) device mapped TxBuf buffer to the system
198 physical address
199
200 @param[in] Dev The VNET_DEV driver instance which wants to
201 reverse- and unmap the Tx packet.
202 @param[out] Buffer The system physical address of TxBuf
203 @param[in] DeviceAddress The device address for the TxBuf
204
205 @retval EFI_INVALID_PARAMETER The DeviceAddress is not mapped
206 @retval EFI_SUCCESS The TxBuf at DeviceAddress has been unmapped,
207 and Buffer has been set to TxBuf's system
208 physical address.
209
210 */
211 EFI_STATUS
212 EFIAPI
213 VirtioNetUnmapTxBuf (
214 IN VNET_DEV *Dev,
215 OUT VOID **Buffer,
216 IN EFI_PHYSICAL_ADDRESS DeviceAddress
217 )
218 {
219 ORDERED_COLLECTION_ENTRY *Entry;
220 TX_BUF_MAP_INFO *TxBufMapInfo;
221 VOID *UserStruct;
222
223 Entry = OrderedCollectionFind (Dev->TxBufCollection, &DeviceAddress);
224 if (Entry == NULL) {
225 return EFI_INVALID_PARAMETER;
226 }
227
228 OrderedCollectionDelete (Dev->TxBufCollection, Entry, &UserStruct);
229
230 TxBufMapInfo = UserStruct;
231
232 *Buffer = TxBufMapInfo->Buffer;
233 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, TxBufMapInfo->BufMap);
234 FreePool (TxBufMapInfo);
235
236 return EFI_SUCCESS;
237 }
238
239 /**
240 Comparator function for two TX_BUF_MAP_INFO objects.
241
242 @param[in] UserStruct1 Pointer to the first TX_BUF_MAP_INFO object.
243
244 @param[in] UserStruct2 Pointer to the second TX_BUF_MAP_INFO object.
245
246 @retval <0 If UserStruct1 compares less than UserStruct2.
247
248 @retval 0 If UserStruct1 compares equal to UserStruct2.
249
250 @retval >0 If UserStruct1 compares greater than UserStruct2.
251 */
252 INTN
253 EFIAPI
254 VirtioNetTxBufMapInfoCompare (
255 IN CONST VOID *UserStruct1,
256 IN CONST VOID *UserStruct2
257 )
258 {
259 CONST TX_BUF_MAP_INFO *MapInfo1;
260 CONST TX_BUF_MAP_INFO *MapInfo2;
261
262 MapInfo1 = UserStruct1;
263 MapInfo2 = UserStruct2;
264
265 return MapInfo1->DeviceAddress < MapInfo2->DeviceAddress ? -1 :
266 MapInfo1->DeviceAddress > MapInfo2->DeviceAddress ? 1 :
267 0;
268 }
269
270 /**
271 Compare a standalone DeviceAddress against a TX_BUF_MAP_INFO object
272 containing an embedded DeviceAddress.
273
274 @param[in] StandaloneKey Pointer to DeviceAddress, which has type
275 EFI_PHYSICAL_ADDRESS.
276
277 @param[in] UserStruct Pointer to the TX_BUF_MAP_INFO object with the
278 embedded DeviceAddress.
279
280 @retval <0 If StandaloneKey compares less than UserStruct's key.
281
282 @retval 0 If StandaloneKey compares equal to UserStruct's key.
283
284 @retval >0 If StandaloneKey compares greater than UserStruct's key.
285 **/
286 INTN
287 EFIAPI
288 VirtioNetTxBufDeviceAddressCompare (
289 IN CONST VOID *StandaloneKey,
290 IN CONST VOID *UserStruct
291 )
292 {
293 CONST EFI_PHYSICAL_ADDRESS *DeviceAddress;
294 CONST TX_BUF_MAP_INFO *MapInfo;
295
296 DeviceAddress = StandaloneKey;
297 MapInfo = UserStruct;
298
299 return *DeviceAddress < MapInfo->DeviceAddress ? -1 :
300 *DeviceAddress > MapInfo->DeviceAddress ? 1 :
301 0;
302 }