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