]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NvmExpressDxe / NvmExpressPassthru.c
1 /** @file
2 NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
3 NVM Express specification.
4
5 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
6 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "NvmExpress.h"
12
13 /**
14 Dump the execution status from a given completion queue entry.
15
16 @param[in] Cq A pointer to the NVME_CQ item.
17
18 **/
19 VOID
20 NvmeDumpStatus (
21 IN NVME_CQ *Cq
22 )
23 {
24 DEBUG ((DEBUG_VERBOSE, "Dump NVMe Completion Entry Status from [0x%x]:\n", Cq));
25
26 DEBUG ((DEBUG_VERBOSE, " SQ Identifier : [0x%x], Phase Tag : [%d], Cmd Identifier : [0x%x]\n", Cq->Sqid, Cq->Pt, Cq->Cid));
27
28 DEBUG ((DEBUG_VERBOSE, " NVMe Cmd Execution Result - "));
29
30 switch (Cq->Sct) {
31 case 0x0:
32 switch (Cq->Sc) {
33 case 0x0:
34 DEBUG ((DEBUG_VERBOSE, "Successful Completion\n"));
35 break;
36 case 0x1:
37 DEBUG ((DEBUG_VERBOSE, "Invalid Command Opcode\n"));
38 break;
39 case 0x2:
40 DEBUG ((DEBUG_VERBOSE, "Invalid Field in Command\n"));
41 break;
42 case 0x3:
43 DEBUG ((DEBUG_VERBOSE, "Command ID Conflict\n"));
44 break;
45 case 0x4:
46 DEBUG ((DEBUG_VERBOSE, "Data Transfer Error\n"));
47 break;
48 case 0x5:
49 DEBUG ((DEBUG_VERBOSE, "Commands Aborted due to Power Loss Notification\n"));
50 break;
51 case 0x6:
52 DEBUG ((DEBUG_VERBOSE, "Internal Device Error\n"));
53 break;
54 case 0x7:
55 DEBUG ((DEBUG_VERBOSE, "Command Abort Requested\n"));
56 break;
57 case 0x8:
58 DEBUG ((DEBUG_VERBOSE, "Command Aborted due to SQ Deletion\n"));
59 break;
60 case 0x9:
61 DEBUG ((DEBUG_VERBOSE, "Command Aborted due to Failed Fused Command\n"));
62 break;
63 case 0xA:
64 DEBUG ((DEBUG_VERBOSE, "Command Aborted due to Missing Fused Command\n"));
65 break;
66 case 0xB:
67 DEBUG ((DEBUG_VERBOSE, "Invalid Namespace or Format\n"));
68 break;
69 case 0xC:
70 DEBUG ((DEBUG_VERBOSE, "Command Sequence Error\n"));
71 break;
72 case 0xD:
73 DEBUG ((DEBUG_VERBOSE, "Invalid SGL Last Segment Descriptor\n"));
74 break;
75 case 0xE:
76 DEBUG ((DEBUG_VERBOSE, "Invalid Number of SGL Descriptors\n"));
77 break;
78 case 0xF:
79 DEBUG ((DEBUG_VERBOSE, "Data SGL Length Invalid\n"));
80 break;
81 case 0x10:
82 DEBUG ((DEBUG_VERBOSE, "Metadata SGL Length Invalid\n"));
83 break;
84 case 0x11:
85 DEBUG ((DEBUG_VERBOSE, "SGL Descriptor Type Invalid\n"));
86 break;
87 case 0x80:
88 DEBUG ((DEBUG_VERBOSE, "LBA Out of Range\n"));
89 break;
90 case 0x81:
91 DEBUG ((DEBUG_VERBOSE, "Capacity Exceeded\n"));
92 break;
93 case 0x82:
94 DEBUG ((DEBUG_VERBOSE, "Namespace Not Ready\n"));
95 break;
96 case 0x83:
97 DEBUG ((DEBUG_VERBOSE, "Reservation Conflict\n"));
98 break;
99 }
100
101 break;
102
103 case 0x1:
104 switch (Cq->Sc) {
105 case 0x0:
106 DEBUG ((DEBUG_VERBOSE, "Completion Queue Invalid\n"));
107 break;
108 case 0x1:
109 DEBUG ((DEBUG_VERBOSE, "Invalid Queue Identifier\n"));
110 break;
111 case 0x2:
112 DEBUG ((DEBUG_VERBOSE, "Maximum Queue Size Exceeded\n"));
113 break;
114 case 0x3:
115 DEBUG ((DEBUG_VERBOSE, "Abort Command Limit Exceeded\n"));
116 break;
117 case 0x5:
118 DEBUG ((DEBUG_VERBOSE, "Asynchronous Event Request Limit Exceeded\n"));
119 break;
120 case 0x6:
121 DEBUG ((DEBUG_VERBOSE, "Invalid Firmware Slot\n"));
122 break;
123 case 0x7:
124 DEBUG ((DEBUG_VERBOSE, "Invalid Firmware Image\n"));
125 break;
126 case 0x8:
127 DEBUG ((DEBUG_VERBOSE, "Invalid Interrupt Vector\n"));
128 break;
129 case 0x9:
130 DEBUG ((DEBUG_VERBOSE, "Invalid Log Page\n"));
131 break;
132 case 0xA:
133 DEBUG ((DEBUG_VERBOSE, "Invalid Format\n"));
134 break;
135 case 0xB:
136 DEBUG ((DEBUG_VERBOSE, "Firmware Application Requires Conventional Reset\n"));
137 break;
138 case 0xC:
139 DEBUG ((DEBUG_VERBOSE, "Invalid Queue Deletion\n"));
140 break;
141 case 0xD:
142 DEBUG ((DEBUG_VERBOSE, "Feature Identifier Not Saveable\n"));
143 break;
144 case 0xE:
145 DEBUG ((DEBUG_VERBOSE, "Feature Not Changeable\n"));
146 break;
147 case 0xF:
148 DEBUG ((DEBUG_VERBOSE, "Feature Not Namespace Specific\n"));
149 break;
150 case 0x10:
151 DEBUG ((DEBUG_VERBOSE, "Firmware Application Requires NVM Subsystem Reset\n"));
152 break;
153 case 0x80:
154 DEBUG ((DEBUG_VERBOSE, "Conflicting Attributes\n"));
155 break;
156 case 0x81:
157 DEBUG ((DEBUG_VERBOSE, "Invalid Protection Information\n"));
158 break;
159 case 0x82:
160 DEBUG ((DEBUG_VERBOSE, "Attempted Write to Read Only Range\n"));
161 break;
162 }
163
164 break;
165
166 case 0x2:
167 switch (Cq->Sc) {
168 case 0x80:
169 DEBUG ((DEBUG_VERBOSE, "Write Fault\n"));
170 break;
171 case 0x81:
172 DEBUG ((DEBUG_VERBOSE, "Unrecovered Read Error\n"));
173 break;
174 case 0x82:
175 DEBUG ((DEBUG_VERBOSE, "End-to-end Guard Check Error\n"));
176 break;
177 case 0x83:
178 DEBUG ((DEBUG_VERBOSE, "End-to-end Application Tag Check Error\n"));
179 break;
180 case 0x84:
181 DEBUG ((DEBUG_VERBOSE, "End-to-end Reference Tag Check Error\n"));
182 break;
183 case 0x85:
184 DEBUG ((DEBUG_VERBOSE, "Compare Failure\n"));
185 break;
186 case 0x86:
187 DEBUG ((DEBUG_VERBOSE, "Access Denied\n"));
188 break;
189 }
190
191 break;
192
193 default:
194 break;
195 }
196 }
197
198 /**
199 Create PRP lists for data transfer which is larger than 2 memory pages.
200 Note here we calcuate the number of required PRP lists and allocate them at one time.
201
202 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
203 @param[in] PhysicalAddr The physical base address of data buffer.
204 @param[in] Pages The number of pages to be transfered.
205 @param[out] PrpListHost The host base address of PRP lists.
206 @param[in,out] PrpListNo The number of PRP List.
207 @param[out] Mapping The mapping value returned from PciIo.Map().
208
209 @retval The pointer to the first PRP List of the PRP lists.
210
211 **/
212 VOID *
213 NvmeCreatePrpList (
214 IN EFI_PCI_IO_PROTOCOL *PciIo,
215 IN EFI_PHYSICAL_ADDRESS PhysicalAddr,
216 IN UINTN Pages,
217 OUT VOID **PrpListHost,
218 IN OUT UINTN *PrpListNo,
219 OUT VOID **Mapping
220 )
221 {
222 UINTN PrpEntryNo;
223 UINT64 PrpListBase;
224 UINTN PrpListIndex;
225 UINTN PrpEntryIndex;
226 UINT64 Remainder;
227 EFI_PHYSICAL_ADDRESS PrpListPhyAddr;
228 UINTN Bytes;
229 EFI_STATUS Status;
230
231 //
232 // The number of Prp Entry in a memory page.
233 //
234 PrpEntryNo = EFI_PAGE_SIZE / sizeof (UINT64);
235
236 //
237 // Calculate total PrpList number.
238 //
239 *PrpListNo = (UINTN)DivU64x64Remainder ((UINT64)Pages, (UINT64)PrpEntryNo - 1, &Remainder);
240 if (*PrpListNo == 0) {
241 *PrpListNo = 1;
242 } else if ((Remainder != 0) && (Remainder != 1)) {
243 *PrpListNo += 1;
244 } else if (Remainder == 1) {
245 Remainder = PrpEntryNo;
246 } else if (Remainder == 0) {
247 Remainder = PrpEntryNo - 1;
248 }
249
250 Status = PciIo->AllocateBuffer (
251 PciIo,
252 AllocateAnyPages,
253 EfiBootServicesData,
254 *PrpListNo,
255 PrpListHost,
256 0
257 );
258
259 if (EFI_ERROR (Status)) {
260 return NULL;
261 }
262
263 Bytes = EFI_PAGES_TO_SIZE (*PrpListNo);
264 Status = PciIo->Map (
265 PciIo,
266 EfiPciIoOperationBusMasterCommonBuffer,
267 *PrpListHost,
268 &Bytes,
269 &PrpListPhyAddr,
270 Mapping
271 );
272
273 if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (*PrpListNo))) {
274 DEBUG ((DEBUG_ERROR, "NvmeCreatePrpList: create PrpList failure!\n"));
275 goto EXIT;
276 }
277
278 //
279 // Fill all PRP lists except of last one.
280 //
281 ZeroMem (*PrpListHost, Bytes);
282 for (PrpListIndex = 0; PrpListIndex < *PrpListNo - 1; ++PrpListIndex) {
283 PrpListBase = *(UINT64 *)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
284
285 for (PrpEntryIndex = 0; PrpEntryIndex < PrpEntryNo; ++PrpEntryIndex) {
286 if (PrpEntryIndex != PrpEntryNo - 1) {
287 //
288 // Fill all PRP entries except of last one.
289 //
290 *((UINT64 *)(UINTN)PrpListBase + PrpEntryIndex) = PhysicalAddr;
291 PhysicalAddr += EFI_PAGE_SIZE;
292 } else {
293 //
294 // Fill last PRP entries with next PRP List pointer.
295 //
296 *((UINT64 *)(UINTN)PrpListBase + PrpEntryIndex) = PrpListPhyAddr + (PrpListIndex + 1) * EFI_PAGE_SIZE;
297 }
298 }
299 }
300
301 //
302 // Fill last PRP list.
303 //
304 PrpListBase = *(UINT64 *)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
305 for (PrpEntryIndex = 0; PrpEntryIndex < Remainder; ++PrpEntryIndex) {
306 *((UINT64 *)(UINTN)PrpListBase + PrpEntryIndex) = PhysicalAddr;
307 PhysicalAddr += EFI_PAGE_SIZE;
308 }
309
310 return (VOID *)(UINTN)PrpListPhyAddr;
311
312 EXIT:
313 PciIo->FreeBuffer (PciIo, *PrpListNo, *PrpListHost);
314 return NULL;
315 }
316
317 /**
318 Aborts the asynchronous PassThru requests.
319
320 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA
321 data structure.
322
323 @retval EFI_SUCCESS The asynchronous PassThru requests have been aborted.
324 @return EFI_DEVICE_ERROR Fail to abort all the asynchronous PassThru requests.
325
326 **/
327 EFI_STATUS
328 AbortAsyncPassThruTasks (
329 IN NVME_CONTROLLER_PRIVATE_DATA *Private
330 )
331 {
332 EFI_PCI_IO_PROTOCOL *PciIo;
333 LIST_ENTRY *Link;
334 LIST_ENTRY *NextLink;
335 NVME_BLKIO2_SUBTASK *Subtask;
336 NVME_BLKIO2_REQUEST *BlkIo2Request;
337 NVME_PASS_THRU_ASYNC_REQ *AsyncRequest;
338 EFI_BLOCK_IO2_TOKEN *Token;
339 EFI_TPL OldTpl;
340 EFI_STATUS Status;
341
342 PciIo = Private->PciIo;
343 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
344
345 //
346 // Cancel the unsubmitted subtasks.
347 //
348 for (Link = GetFirstNode (&Private->UnsubmittedSubtasks);
349 !IsNull (&Private->UnsubmittedSubtasks, Link);
350 Link = NextLink)
351 {
352 NextLink = GetNextNode (&Private->UnsubmittedSubtasks, Link);
353 Subtask = NVME_BLKIO2_SUBTASK_FROM_LINK (Link);
354 BlkIo2Request = Subtask->BlockIo2Request;
355 Token = BlkIo2Request->Token;
356
357 BlkIo2Request->UnsubmittedSubtaskNum--;
358 if (Subtask->IsLast) {
359 BlkIo2Request->LastSubtaskSubmitted = TRUE;
360 }
361
362 Token->TransactionStatus = EFI_ABORTED;
363
364 RemoveEntryList (Link);
365 InsertTailList (&BlkIo2Request->SubtasksQueue, Link);
366 gBS->SignalEvent (Subtask->Event);
367 }
368
369 //
370 // Cleanup the resources for the asynchronous PassThru requests.
371 //
372 for (Link = GetFirstNode (&Private->AsyncPassThruQueue);
373 !IsNull (&Private->AsyncPassThruQueue, Link);
374 Link = NextLink)
375 {
376 NextLink = GetNextNode (&Private->AsyncPassThruQueue, Link);
377 AsyncRequest = NVME_PASS_THRU_ASYNC_REQ_FROM_THIS (Link);
378
379 if (AsyncRequest->MapData != NULL) {
380 PciIo->Unmap (PciIo, AsyncRequest->MapData);
381 }
382
383 if (AsyncRequest->MapMeta != NULL) {
384 PciIo->Unmap (PciIo, AsyncRequest->MapMeta);
385 }
386
387 if (AsyncRequest->MapPrpList != NULL) {
388 PciIo->Unmap (PciIo, AsyncRequest->MapPrpList);
389 }
390
391 if (AsyncRequest->PrpListHost != NULL) {
392 PciIo->FreeBuffer (
393 PciIo,
394 AsyncRequest->PrpListNo,
395 AsyncRequest->PrpListHost
396 );
397 }
398
399 RemoveEntryList (Link);
400 gBS->SignalEvent (AsyncRequest->CallerEvent);
401 FreePool (AsyncRequest);
402 }
403
404 if (IsListEmpty (&Private->AsyncPassThruQueue) &&
405 IsListEmpty (&Private->UnsubmittedSubtasks))
406 {
407 Status = EFI_SUCCESS;
408 } else {
409 Status = EFI_DEVICE_ERROR;
410 }
411
412 gBS->RestoreTPL (OldTpl);
413
414 return Status;
415 }
416
417 /**
418 Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports
419 both blocking I/O and non-blocking I/O. The blocking I/O functionality is required, and the non-blocking
420 I/O functionality is optional.
421
422
423 @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
424 @param[in] NamespaceId A 32 bit namespace ID as defined in the NVMe specification to which the NVM Express Command
425 Packet will be sent. A value of 0 denotes the NVM Express controller, a value of all 0xFF's
426 (all bytes are 0xFF) in the namespace ID specifies that the command packet should be sent to
427 all valid namespaces.
428 @param[in,out] Packet A pointer to the NVM Express Command Packet.
429 @param[in] Event If non-blocking I/O is not supported then Event is ignored, and blocking I/O is performed.
430 If Event is NULL, then blocking I/O is performed. If Event is not NULL and non-blocking I/O
431 is supported, then non-blocking I/O is performed, and Event will be signaled when the NVM
432 Express Command Packet completes.
433
434 @retval EFI_SUCCESS The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred
435 to, or from DataBuffer.
436 @retval EFI_BAD_BUFFER_SIZE The NVM Express Command Packet was not executed. The number of bytes that could be transferred
437 is returned in TransferLength.
438 @retval EFI_NOT_READY The NVM Express Command Packet could not be sent because the controller is not ready. The caller
439 may retry again later.
440 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the NVM Express Command Packet.
441 @retval EFI_INVALID_PARAMETER NamespaceId or the contents of EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
442 Express Command Packet was not sent, so no additional status information is available.
443 @retval EFI_UNSUPPORTED The command described by the NVM Express Command Packet is not supported by the NVM Express
444 controller. The NVM Express Command Packet was not sent so no additional status information
445 is available.
446 @retval EFI_TIMEOUT A timeout occurred while waiting for the NVM Express Command Packet to execute.
447
448 **/
449 EFI_STATUS
450 EFIAPI
451 NvmExpressPassThru (
452 IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
453 IN UINT32 NamespaceId,
454 IN OUT EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet,
455 IN EFI_EVENT Event OPTIONAL
456 )
457 {
458 NVME_CONTROLLER_PRIVATE_DATA *Private;
459 EFI_STATUS Status;
460 EFI_STATUS PreviousStatus;
461 EFI_PCI_IO_PROTOCOL *PciIo;
462 NVME_SQ *Sq;
463 NVME_CQ *Cq;
464 UINT16 QueueId;
465 UINT16 QueueSize;
466 UINT32 Bytes;
467 UINT16 Offset;
468 EFI_EVENT TimerEvent;
469 EFI_PCI_IO_PROTOCOL_OPERATION Flag;
470 EFI_PHYSICAL_ADDRESS PhyAddr;
471 VOID *MapData;
472 VOID *MapMeta;
473 VOID *MapPrpList;
474 UINTN MapLength;
475 UINT64 *Prp;
476 VOID *PrpListHost;
477 UINTN PrpListNo;
478 UINT32 Attributes;
479 UINT32 IoAlign;
480 UINT32 MaxTransLen;
481 UINT32 Data;
482 NVME_PASS_THRU_ASYNC_REQ *AsyncRequest;
483 EFI_TPL OldTpl;
484
485 //
486 // check the data fields in Packet parameter.
487 //
488 if ((This == NULL) || (Packet == NULL)) {
489 return EFI_INVALID_PARAMETER;
490 }
491
492 if ((Packet->NvmeCmd == NULL) || (Packet->NvmeCompletion == NULL)) {
493 return EFI_INVALID_PARAMETER;
494 }
495
496 if ((Packet->QueueType != NVME_ADMIN_QUEUE) && (Packet->QueueType != NVME_IO_QUEUE)) {
497 return EFI_INVALID_PARAMETER;
498 }
499
500 //
501 // 'Attributes' with neither EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL nor
502 // EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL set is an illegal
503 // configuration.
504 //
505 Attributes = This->Mode->Attributes;
506 if ((Attributes & (EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
507 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL)) == 0)
508 {
509 return EFI_INVALID_PARAMETER;
510 }
511
512 //
513 // Buffer alignment check for TransferBuffer & MetadataBuffer.
514 //
515 IoAlign = This->Mode->IoAlign;
516 if ((IoAlign > 0) && (((UINTN)Packet->TransferBuffer & (IoAlign - 1)) != 0)) {
517 return EFI_INVALID_PARAMETER;
518 }
519
520 if ((IoAlign > 0) && (((UINTN)Packet->MetadataBuffer & (IoAlign - 1)) != 0)) {
521 return EFI_INVALID_PARAMETER;
522 }
523
524 Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This);
525
526 //
527 // Check NamespaceId is valid or not.
528 //
529 if ((NamespaceId > Private->ControllerData->Nn) &&
530 (NamespaceId != (UINT32)-1))
531 {
532 return EFI_INVALID_PARAMETER;
533 }
534
535 //
536 // Check whether TransferLength exceeds the maximum data transfer size.
537 //
538 if (Private->ControllerData->Mdts != 0) {
539 MaxTransLen = (1 << (Private->ControllerData->Mdts)) *
540 (1 << (Private->Cap.Mpsmin + 12));
541 if (Packet->TransferLength > MaxTransLen) {
542 Packet->TransferLength = MaxTransLen;
543 return EFI_BAD_BUFFER_SIZE;
544 }
545 }
546
547 PciIo = Private->PciIo;
548 MapData = NULL;
549 MapMeta = NULL;
550 MapPrpList = NULL;
551 PrpListHost = NULL;
552 PrpListNo = 0;
553 Prp = NULL;
554 TimerEvent = NULL;
555 Status = EFI_SUCCESS;
556 QueueSize = MIN (NVME_ASYNC_CSQ_SIZE, Private->Cap.Mqes) + 1;
557
558 if (Packet->QueueType == NVME_ADMIN_QUEUE) {
559 QueueId = 0;
560 } else {
561 if (Event == NULL) {
562 QueueId = 1;
563 } else {
564 QueueId = 2;
565
566 //
567 // Submission queue full check.
568 //
569 if ((Private->SqTdbl[QueueId].Sqt + 1) % QueueSize ==
570 Private->AsyncSqHead)
571 {
572 return EFI_NOT_READY;
573 }
574 }
575 }
576
577 Sq = Private->SqBuffer[QueueId] + Private->SqTdbl[QueueId].Sqt;
578 Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh;
579
580 if (Packet->NvmeCmd->Nsid != NamespaceId) {
581 return EFI_INVALID_PARAMETER;
582 }
583
584 ZeroMem (Sq, sizeof (NVME_SQ));
585 Sq->Opc = (UINT8)Packet->NvmeCmd->Cdw0.Opcode;
586 Sq->Fuse = (UINT8)Packet->NvmeCmd->Cdw0.FusedOperation;
587 Sq->Cid = Private->Cid[QueueId]++;
588 Sq->Nsid = Packet->NvmeCmd->Nsid;
589
590 //
591 // Currently we only support PRP for data transfer, SGL is NOT supported.
592 //
593 ASSERT (Sq->Psdt == 0);
594 if (Sq->Psdt != 0) {
595 DEBUG ((DEBUG_ERROR, "NvmExpressPassThru: doesn't support SGL mechanism\n"));
596 return EFI_UNSUPPORTED;
597 }
598
599 Sq->Prp[0] = (UINT64)(UINTN)Packet->TransferBuffer;
600 if ((Packet->QueueType == NVME_ADMIN_QUEUE) &&
601 ((Sq->Opc == NVME_ADMIN_CRIOCQ_CMD) || (Sq->Opc == NVME_ADMIN_CRIOSQ_CMD)))
602 {
603 //
604 // Currently, we only use the IO Completion/Submission queues created internally
605 // by this driver during controller initialization. Any other IO queues created
606 // will not be consumed here. The value is little to accept external IO queue
607 // creation requests, so here we will return EFI_UNSUPPORTED for external IO
608 // queue creation request.
609 //
610 if (!Private->CreateIoQueue) {
611 DEBUG ((DEBUG_ERROR, "NvmExpressPassThru: Does not support external IO queues creation request.\n"));
612 return EFI_UNSUPPORTED;
613 }
614 } else if ((Sq->Opc & (BIT0 | BIT1)) != 0) {
615 //
616 // If the NVMe cmd has data in or out, then mapping the user buffer to the PCI controller specific addresses.
617 //
618 if (((Packet->TransferLength != 0) && (Packet->TransferBuffer == NULL)) ||
619 ((Packet->TransferLength == 0) && (Packet->TransferBuffer != NULL)))
620 {
621 return EFI_INVALID_PARAMETER;
622 }
623
624 if ((Sq->Opc & BIT0) != 0) {
625 Flag = EfiPciIoOperationBusMasterRead;
626 } else {
627 Flag = EfiPciIoOperationBusMasterWrite;
628 }
629
630 if ((Packet->TransferLength != 0) && (Packet->TransferBuffer != NULL)) {
631 MapLength = Packet->TransferLength;
632 Status = PciIo->Map (
633 PciIo,
634 Flag,
635 Packet->TransferBuffer,
636 &MapLength,
637 &PhyAddr,
638 &MapData
639 );
640 if (EFI_ERROR (Status) || (Packet->TransferLength != MapLength)) {
641 return EFI_OUT_OF_RESOURCES;
642 }
643
644 Sq->Prp[0] = PhyAddr;
645 Sq->Prp[1] = 0;
646 }
647
648 if ((Packet->MetadataLength != 0) && (Packet->MetadataBuffer != NULL)) {
649 MapLength = Packet->MetadataLength;
650 Status = PciIo->Map (
651 PciIo,
652 Flag,
653 Packet->MetadataBuffer,
654 &MapLength,
655 &PhyAddr,
656 &MapMeta
657 );
658 if (EFI_ERROR (Status) || (Packet->MetadataLength != MapLength)) {
659 PciIo->Unmap (
660 PciIo,
661 MapData
662 );
663
664 return EFI_OUT_OF_RESOURCES;
665 }
666
667 Sq->Mptr = PhyAddr;
668 }
669 }
670
671 //
672 // If the buffer size spans more than two memory pages (page size as defined in CC.Mps),
673 // then build a PRP list in the second PRP submission queue entry.
674 //
675 Offset = ((UINT16)Sq->Prp[0]) & (EFI_PAGE_SIZE - 1);
676 Bytes = Packet->TransferLength;
677
678 if ((Offset + Bytes) > (EFI_PAGE_SIZE * 2)) {
679 //
680 // Create PrpList for remaining data buffer.
681 //
682 PhyAddr = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
683 Prp = NvmeCreatePrpList (PciIo, PhyAddr, EFI_SIZE_TO_PAGES (Offset + Bytes) - 1, &PrpListHost, &PrpListNo, &MapPrpList);
684 if (Prp == NULL) {
685 Status = EFI_OUT_OF_RESOURCES;
686 goto EXIT;
687 }
688
689 Sq->Prp[1] = (UINT64)(UINTN)Prp;
690 } else if ((Offset + Bytes) > EFI_PAGE_SIZE) {
691 Sq->Prp[1] = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
692 }
693
694 if (Packet->NvmeCmd->Flags & CDW2_VALID) {
695 Sq->Rsvd2 = (UINT64)Packet->NvmeCmd->Cdw2;
696 }
697
698 if (Packet->NvmeCmd->Flags & CDW3_VALID) {
699 Sq->Rsvd2 |= LShiftU64 ((UINT64)Packet->NvmeCmd->Cdw3, 32);
700 }
701
702 if (Packet->NvmeCmd->Flags & CDW10_VALID) {
703 Sq->Payload.Raw.Cdw10 = Packet->NvmeCmd->Cdw10;
704 }
705
706 if (Packet->NvmeCmd->Flags & CDW11_VALID) {
707 Sq->Payload.Raw.Cdw11 = Packet->NvmeCmd->Cdw11;
708 }
709
710 if (Packet->NvmeCmd->Flags & CDW12_VALID) {
711 Sq->Payload.Raw.Cdw12 = Packet->NvmeCmd->Cdw12;
712 }
713
714 if (Packet->NvmeCmd->Flags & CDW13_VALID) {
715 Sq->Payload.Raw.Cdw13 = Packet->NvmeCmd->Cdw13;
716 }
717
718 if (Packet->NvmeCmd->Flags & CDW14_VALID) {
719 Sq->Payload.Raw.Cdw14 = Packet->NvmeCmd->Cdw14;
720 }
721
722 if (Packet->NvmeCmd->Flags & CDW15_VALID) {
723 Sq->Payload.Raw.Cdw15 = Packet->NvmeCmd->Cdw15;
724 }
725
726 //
727 // Ring the submission queue doorbell.
728 //
729 if ((Event != NULL) && (QueueId != 0)) {
730 Private->SqTdbl[QueueId].Sqt =
731 (Private->SqTdbl[QueueId].Sqt + 1) % QueueSize;
732 } else {
733 Private->SqTdbl[QueueId].Sqt ^= 1;
734 }
735
736 Data = ReadUnaligned32 ((UINT32 *)&Private->SqTdbl[QueueId]);
737 Status = PciIo->Mem.Write (
738 PciIo,
739 EfiPciIoWidthUint32,
740 NVME_BAR,
741 NVME_SQTDBL_OFFSET (QueueId, Private->Cap.Dstrd),
742 1,
743 &Data
744 );
745
746 if (EFI_ERROR (Status)) {
747 goto EXIT;
748 }
749
750 //
751 // For non-blocking requests, return directly if the command is placed
752 // in the submission queue.
753 //
754 if ((Event != NULL) && (QueueId != 0)) {
755 AsyncRequest = AllocateZeroPool (sizeof (NVME_PASS_THRU_ASYNC_REQ));
756 if (AsyncRequest == NULL) {
757 Status = EFI_DEVICE_ERROR;
758 goto EXIT;
759 }
760
761 AsyncRequest->Signature = NVME_PASS_THRU_ASYNC_REQ_SIG;
762 AsyncRequest->Packet = Packet;
763 AsyncRequest->CommandId = Sq->Cid;
764 AsyncRequest->CallerEvent = Event;
765 AsyncRequest->MapData = MapData;
766 AsyncRequest->MapMeta = MapMeta;
767 AsyncRequest->MapPrpList = MapPrpList;
768 AsyncRequest->PrpListNo = PrpListNo;
769 AsyncRequest->PrpListHost = PrpListHost;
770
771 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
772 InsertTailList (&Private->AsyncPassThruQueue, &AsyncRequest->Link);
773 gBS->RestoreTPL (OldTpl);
774
775 return EFI_SUCCESS;
776 }
777
778 Status = gBS->CreateEvent (
779 EVT_TIMER,
780 TPL_CALLBACK,
781 NULL,
782 NULL,
783 &TimerEvent
784 );
785 if (EFI_ERROR (Status)) {
786 goto EXIT;
787 }
788
789 Status = gBS->SetTimer (TimerEvent, TimerRelative, Packet->CommandTimeout);
790
791 if (EFI_ERROR (Status)) {
792 goto EXIT;
793 }
794
795 //
796 // Wait for completion queue to get filled in.
797 //
798 Status = EFI_TIMEOUT;
799 while (EFI_ERROR (gBS->CheckEvent (TimerEvent))) {
800 if (Cq->Pt != Private->Pt[QueueId]) {
801 Status = EFI_SUCCESS;
802 break;
803 }
804 }
805
806 //
807 // Check the NVMe cmd execution result
808 //
809 if (Status != EFI_TIMEOUT) {
810 if ((Cq->Sct == 0) && (Cq->Sc == 0)) {
811 Status = EFI_SUCCESS;
812 } else {
813 Status = EFI_DEVICE_ERROR;
814 //
815 // Dump every completion entry status for debugging.
816 //
817 DEBUG_CODE_BEGIN ();
818 NvmeDumpStatus (Cq);
819 DEBUG_CODE_END ();
820 }
821
822 //
823 // Copy the Respose Queue entry for this command to the callers response buffer
824 //
825 CopyMem (Packet->NvmeCompletion, Cq, sizeof (EFI_NVM_EXPRESS_COMPLETION));
826 } else {
827 //
828 // Timeout occurs for an NVMe command. Reset the controller to abort the
829 // outstanding commands.
830 //
831 DEBUG ((DEBUG_ERROR, "NvmExpressPassThru: Timeout occurs for an NVMe command.\n"));
832
833 //
834 // Disable the timer to trigger the process of async transfers temporarily.
835 //
836 Status = gBS->SetTimer (Private->TimerEvent, TimerCancel, 0);
837 if (EFI_ERROR (Status)) {
838 goto EXIT;
839 }
840
841 //
842 // Reset the NVMe controller.
843 //
844 Status = NvmeControllerInit (Private);
845 if (!EFI_ERROR (Status)) {
846 Status = AbortAsyncPassThruTasks (Private);
847 if (!EFI_ERROR (Status)) {
848 //
849 // Re-enable the timer to trigger the process of async transfers.
850 //
851 Status = gBS->SetTimer (Private->TimerEvent, TimerPeriodic, NVME_HC_ASYNC_TIMER);
852 if (!EFI_ERROR (Status)) {
853 //
854 // Return EFI_TIMEOUT to indicate a timeout occurs for NVMe PassThru command.
855 //
856 Status = EFI_TIMEOUT;
857 }
858 }
859 } else {
860 Status = EFI_DEVICE_ERROR;
861 }
862
863 goto EXIT;
864 }
865
866 if ((Private->CqHdbl[QueueId].Cqh ^= 1) == 0) {
867 Private->Pt[QueueId] ^= 1;
868 }
869
870 Data = ReadUnaligned32 ((UINT32 *)&Private->CqHdbl[QueueId]);
871 PreviousStatus = Status;
872 Status = PciIo->Mem.Write (
873 PciIo,
874 EfiPciIoWidthUint32,
875 NVME_BAR,
876 NVME_CQHDBL_OFFSET (QueueId, Private->Cap.Dstrd),
877 1,
878 &Data
879 );
880 // The return status of PciIo->Mem.Write should not override
881 // previous status if previous status contains error.
882 Status = EFI_ERROR (PreviousStatus) ? PreviousStatus : Status;
883
884 //
885 // For now, the code does not support the non-blocking feature for admin queue.
886 // If Event is not NULL for admin queue, signal the caller's event here.
887 //
888 if (Event != NULL) {
889 ASSERT (QueueId == 0);
890 gBS->SignalEvent (Event);
891 }
892
893 EXIT:
894 if (MapData != NULL) {
895 PciIo->Unmap (
896 PciIo,
897 MapData
898 );
899 }
900
901 if (MapMeta != NULL) {
902 PciIo->Unmap (
903 PciIo,
904 MapMeta
905 );
906 }
907
908 if (MapPrpList != NULL) {
909 PciIo->Unmap (
910 PciIo,
911 MapPrpList
912 );
913 }
914
915 if (Prp != NULL) {
916 PciIo->FreeBuffer (PciIo, PrpListNo, PrpListHost);
917 }
918
919 if (TimerEvent != NULL) {
920 gBS->CloseEvent (TimerEvent);
921 }
922
923 return Status;
924 }
925
926 /**
927 Used to retrieve the next namespace ID for this NVM Express controller.
928
929 The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNextNamespace() function retrieves the next valid
930 namespace ID on this NVM Express controller.
931
932 If on input the value pointed to by NamespaceId is 0xFFFFFFFF, then the first valid namespace
933 ID defined on the NVM Express controller is returned in the location pointed to by NamespaceId
934 and a status of EFI_SUCCESS is returned.
935
936 If on input the value pointed to by NamespaceId is an invalid namespace ID other than 0xFFFFFFFF,
937 then EFI_INVALID_PARAMETER is returned.
938
939 If on input the value pointed to by NamespaceId is a valid namespace ID, then the next valid
940 namespace ID on the NVM Express controller is returned in the location pointed to by NamespaceId,
941 and EFI_SUCCESS is returned.
942
943 If the value pointed to by NamespaceId is the namespace ID of the last namespace on the NVM
944 Express controller, then EFI_NOT_FOUND is returned.
945
946 @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
947 @param[in,out] NamespaceId On input, a pointer to a legal NamespaceId for an NVM Express
948 namespace present on the NVM Express controller. On output, a
949 pointer to the next NamespaceId of an NVM Express namespace on
950 an NVM Express controller. An input value of 0xFFFFFFFF retrieves
951 the first NamespaceId for an NVM Express namespace present on an
952 NVM Express controller.
953
954 @retval EFI_SUCCESS The Namespace ID of the next Namespace was returned.
955 @retval EFI_NOT_FOUND There are no more namespaces defined on this controller.
956 @retval EFI_INVALID_PARAMETER NamespaceId is an invalid value other than 0xFFFFFFFF.
957
958 **/
959 EFI_STATUS
960 EFIAPI
961 NvmExpressGetNextNamespace (
962 IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
963 IN OUT UINT32 *NamespaceId
964 )
965 {
966 NVME_CONTROLLER_PRIVATE_DATA *Private;
967 NVME_ADMIN_NAMESPACE_DATA *NamespaceData;
968 UINT32 NextNamespaceId;
969 EFI_STATUS Status;
970
971 if ((This == NULL) || (NamespaceId == NULL)) {
972 return EFI_INVALID_PARAMETER;
973 }
974
975 NamespaceData = NULL;
976 Status = EFI_NOT_FOUND;
977
978 Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This);
979 //
980 // If the NamespaceId input value is 0xFFFFFFFF, then get the first valid namespace ID
981 //
982 if (*NamespaceId == 0xFFFFFFFF) {
983 //
984 // Start with the first namespace ID
985 //
986 NextNamespaceId = 1;
987 //
988 // Allocate buffer for Identify Namespace data.
989 //
990 NamespaceData = (NVME_ADMIN_NAMESPACE_DATA *)AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA));
991
992 if (NamespaceData == NULL) {
993 return EFI_NOT_FOUND;
994 }
995
996 Status = NvmeIdentifyNamespace (Private, NextNamespaceId, NamespaceData);
997 if (EFI_ERROR (Status)) {
998 goto Done;
999 }
1000
1001 *NamespaceId = NextNamespaceId;
1002 } else {
1003 if (*NamespaceId > Private->ControllerData->Nn) {
1004 return EFI_INVALID_PARAMETER;
1005 }
1006
1007 NextNamespaceId = *NamespaceId + 1;
1008 if (NextNamespaceId > Private->ControllerData->Nn) {
1009 return EFI_NOT_FOUND;
1010 }
1011
1012 //
1013 // Allocate buffer for Identify Namespace data.
1014 //
1015 NamespaceData = (NVME_ADMIN_NAMESPACE_DATA *)AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA));
1016 if (NamespaceData == NULL) {
1017 return EFI_NOT_FOUND;
1018 }
1019
1020 Status = NvmeIdentifyNamespace (Private, NextNamespaceId, NamespaceData);
1021 if (EFI_ERROR (Status)) {
1022 goto Done;
1023 }
1024
1025 *NamespaceId = NextNamespaceId;
1026 }
1027
1028 Done:
1029 if (NamespaceData != NULL) {
1030 FreePool (NamespaceData);
1031 }
1032
1033 return Status;
1034 }
1035
1036 /**
1037 Used to translate a device path node to a namespace ID.
1038
1039 The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNamespace() function determines the namespace ID associated with the
1040 namespace described by DevicePath.
1041
1042 If DevicePath is a device path node type that the NVM Express Pass Thru driver supports, then the NVM Express
1043 Pass Thru driver will attempt to translate the contents DevicePath into a namespace ID.
1044
1045 If this translation is successful, then that namespace ID is returned in NamespaceId, and EFI_SUCCESS is returned
1046
1047 @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
1048 @param[in] DevicePath A pointer to the device path node that describes an NVM Express namespace on
1049 the NVM Express controller.
1050 @param[out] NamespaceId The NVM Express namespace ID contained in the device path node.
1051
1052 @retval EFI_SUCCESS DevicePath was successfully translated to NamespaceId.
1053 @retval EFI_INVALID_PARAMETER If DevicePath or NamespaceId are NULL, then EFI_INVALID_PARAMETER is returned.
1054 @retval EFI_UNSUPPORTED If DevicePath is not a device path node type that the NVM Express Pass Thru driver
1055 supports, then EFI_UNSUPPORTED is returned.
1056 @retval EFI_NOT_FOUND If DevicePath is a device path node type that the NVM Express Pass Thru driver
1057 supports, but there is not a valid translation from DevicePath to a namespace ID,
1058 then EFI_NOT_FOUND is returned.
1059 **/
1060 EFI_STATUS
1061 EFIAPI
1062 NvmExpressGetNamespace (
1063 IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
1064 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1065 OUT UINT32 *NamespaceId
1066 )
1067 {
1068 NVME_NAMESPACE_DEVICE_PATH *Node;
1069 NVME_CONTROLLER_PRIVATE_DATA *Private;
1070
1071 if ((This == NULL) || (DevicePath == NULL) || (NamespaceId == NULL)) {
1072 return EFI_INVALID_PARAMETER;
1073 }
1074
1075 if (DevicePath->Type != MESSAGING_DEVICE_PATH) {
1076 return EFI_UNSUPPORTED;
1077 }
1078
1079 Node = (NVME_NAMESPACE_DEVICE_PATH *)DevicePath;
1080 Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This);
1081
1082 if (DevicePath->SubType == MSG_NVME_NAMESPACE_DP) {
1083 if (DevicePathNodeLength (DevicePath) != sizeof (NVME_NAMESPACE_DEVICE_PATH)) {
1084 return EFI_NOT_FOUND;
1085 }
1086
1087 //
1088 // Check NamespaceId in the device path node is valid or not.
1089 //
1090 if ((Node->NamespaceId == 0) ||
1091 (Node->NamespaceId > Private->ControllerData->Nn))
1092 {
1093 return EFI_NOT_FOUND;
1094 }
1095
1096 *NamespaceId = Node->NamespaceId;
1097
1098 return EFI_SUCCESS;
1099 } else {
1100 return EFI_UNSUPPORTED;
1101 }
1102 }
1103
1104 /**
1105 Used to allocate and build a device path node for an NVM Express namespace on an NVM Express controller.
1106
1107 The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.BuildDevicePath() function allocates and builds a single device
1108 path node for the NVM Express namespace specified by NamespaceId.
1109
1110 If the NamespaceId is not valid, then EFI_NOT_FOUND is returned.
1111
1112 If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned.
1113
1114 If there are not enough resources to allocate the device path node, then EFI_OUT_OF_RESOURCES is returned.
1115
1116 Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of DevicePath are
1117 initialized to describe the NVM Express namespace specified by NamespaceId, and EFI_SUCCESS is returned.
1118
1119 @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
1120 @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
1121 allocated and built. Caller must set the NamespaceId to zero if the
1122 device path node will contain a valid UUID.
1123 @param[in,out] DevicePath A pointer to a single device path node that describes the NVM Express
1124 namespace specified by NamespaceId. This function is responsible for
1125 allocating the buffer DevicePath with the boot service AllocatePool().
1126 It is the caller's responsibility to free DevicePath when the caller
1127 is finished with DevicePath.
1128 @retval EFI_SUCCESS The device path node that describes the NVM Express namespace specified
1129 by NamespaceId was allocated and returned in DevicePath.
1130 @retval EFI_NOT_FOUND The NamespaceId is not valid.
1131 @retval EFI_INVALID_PARAMETER DevicePath is NULL.
1132 @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the DevicePath node.
1133
1134 **/
1135 EFI_STATUS
1136 EFIAPI
1137 NvmExpressBuildDevicePath (
1138 IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
1139 IN UINT32 NamespaceId,
1140 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
1141 )
1142 {
1143 NVME_NAMESPACE_DEVICE_PATH *Node;
1144 NVME_CONTROLLER_PRIVATE_DATA *Private;
1145 EFI_STATUS Status;
1146 NVME_ADMIN_NAMESPACE_DATA *NamespaceData;
1147
1148 //
1149 // Validate parameters
1150 //
1151 if ((This == NULL) || (DevicePath == NULL)) {
1152 return EFI_INVALID_PARAMETER;
1153 }
1154
1155 Status = EFI_SUCCESS;
1156 Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This);
1157
1158 //
1159 // Check NamespaceId is valid or not.
1160 //
1161 if ((NamespaceId == 0) ||
1162 (NamespaceId > Private->ControllerData->Nn))
1163 {
1164 return EFI_NOT_FOUND;
1165 }
1166
1167 Node = (NVME_NAMESPACE_DEVICE_PATH *)AllocateZeroPool (sizeof (NVME_NAMESPACE_DEVICE_PATH));
1168 if (Node == NULL) {
1169 return EFI_OUT_OF_RESOURCES;
1170 }
1171
1172 Node->Header.Type = MESSAGING_DEVICE_PATH;
1173 Node->Header.SubType = MSG_NVME_NAMESPACE_DP;
1174 SetDevicePathNodeLength (&Node->Header, sizeof (NVME_NAMESPACE_DEVICE_PATH));
1175 Node->NamespaceId = NamespaceId;
1176
1177 //
1178 // Allocate a buffer for Identify Namespace data.
1179 //
1180 NamespaceData = NULL;
1181 NamespaceData = AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA));
1182 if (NamespaceData == NULL) {
1183 Status = EFI_OUT_OF_RESOURCES;
1184 goto Exit;
1185 }
1186
1187 //
1188 // Get UUID from specified Identify Namespace data.
1189 //
1190 Status = NvmeIdentifyNamespace (
1191 Private,
1192 NamespaceId,
1193 (VOID *)NamespaceData
1194 );
1195
1196 if (EFI_ERROR (Status)) {
1197 goto Exit;
1198 }
1199
1200 Node->NamespaceUuid = NamespaceData->Eui64;
1201
1202 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)Node;
1203
1204 Exit:
1205 if (NamespaceData != NULL) {
1206 FreePool (NamespaceData);
1207 }
1208
1209 if (EFI_ERROR (Status)) {
1210 FreePool (Node);
1211 }
1212
1213 return Status;
1214 }