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