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