libpayload/nvme: Fix error paths of nvme_init()
We mustn't try to release resources that we haven't acquired yet. Also, sending commands to the NVMe device is futile if we already timed out. Fixes hangs after a failed init noticed in QEMU and on siemens/chili. Change-Id: Ib83c7785d6e0dc3c44fbd50a30694c74932750d6 Signed-off-by: Nico Huber <nico.h@gmx.de> Reviewed-on: https://review.coreboot.org/c/coreboot/+/63933 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Thomas Heijligen <src@posteo.de> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
parent
507b0746d6
commit
2b986700c9
|
@ -341,7 +341,7 @@ static void nvme_init(pcidev_t dev)
|
||||||
|
|
||||||
if (!nvme->prp_list) {
|
if (!nvme->prp_list) {
|
||||||
printf("NVMe ERROR: Failed to allocate buffer for PRP list\n");
|
printf("NVMe ERROR: Failed to allocate buffer for PRP list\n");
|
||||||
goto abort;
|
goto _free_abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t cc = NVME_CC_EN | NVME_CC_CSS | NVME_CC_MPS | NVME_CC_AMS | NVME_CC_SHN
|
const uint32_t cc = NVME_CC_EN | NVME_CC_CSS | NVME_CC_MPS | NVME_CC_AMS | NVME_CC_SHN
|
||||||
|
@ -354,26 +354,26 @@ static void nvme_init(pcidev_t dev)
|
||||||
status = read32(nvme->config + 0x1c) & 0x3;
|
status = read32(nvme->config + 0x1c) & 0x3;
|
||||||
if (status == 0x2) {
|
if (status == 0x2) {
|
||||||
printf("NVMe ERROR: Failed to disable controller. FATAL ERROR\n");
|
printf("NVMe ERROR: Failed to disable controller. FATAL ERROR\n");
|
||||||
goto abort;
|
goto _free_abort;
|
||||||
}
|
}
|
||||||
if (timeout < 0) {
|
if (timeout < 0) {
|
||||||
printf("NVMe ERROR: Failed to disable controller. Timeout.\n");
|
printf("NVMe ERROR: Failed to disable controller. Timeout.\n");
|
||||||
goto abort;
|
goto _free_abort;
|
||||||
}
|
}
|
||||||
timeout -= 10;
|
timeout -= 10;
|
||||||
mdelay(10);
|
mdelay(10);
|
||||||
} while (status != 0x0);
|
} while (status != 0x0);
|
||||||
if (create_admin_queues(nvme))
|
if (create_admin_queues(nvme))
|
||||||
goto abort;
|
goto _free_abort;
|
||||||
write32(nvme->config + 0x14, cc);
|
write32(nvme->config + 0x14, cc);
|
||||||
|
|
||||||
timeout = (read64(nvme->config) >> 24 & 0xff) * 500;
|
timeout = (read64(nvme->config) >> 24 & 0xff) * 500;
|
||||||
do {
|
do {
|
||||||
status = read32(nvme->config + 0x1c) & 0x3;
|
status = read32(nvme->config + 0x1c) & 0x3;
|
||||||
if (status == 0x2)
|
if (status == 0x2)
|
||||||
goto abort;
|
goto _delete_admin_abort;
|
||||||
if (timeout < 0)
|
if (timeout < 0)
|
||||||
goto abort;
|
goto _delete_admin_abort;
|
||||||
timeout -= 10;
|
timeout -= 10;
|
||||||
mdelay(10);
|
mdelay(10);
|
||||||
} while (status != 0x1);
|
} while (status != 0x1);
|
||||||
|
@ -381,20 +381,21 @@ static void nvme_init(pcidev_t dev)
|
||||||
uint16_t command = pci_read_config16(dev, PCI_COMMAND);
|
uint16_t command = pci_read_config16(dev, PCI_COMMAND);
|
||||||
pci_write_config16(dev, PCI_COMMAND, command | PCI_COMMAND_MASTER);
|
pci_write_config16(dev, PCI_COMMAND, command | PCI_COMMAND_MASTER);
|
||||||
if (create_io_completion_queue(nvme))
|
if (create_io_completion_queue(nvme))
|
||||||
goto abort;
|
goto _delete_admin_abort;
|
||||||
if (create_io_submission_queue(nvme))
|
if (create_io_submission_queue(nvme))
|
||||||
goto abort;
|
goto _delete_completion_abort;
|
||||||
storage_attach_device((storage_dev_t *)nvme);
|
storage_attach_device((storage_dev_t *)nvme);
|
||||||
printf("NVMe init done.\n");
|
printf("NVMe init done.\n");
|
||||||
return;
|
return;
|
||||||
|
|
||||||
abort:
|
_delete_completion_abort:
|
||||||
printf("NVMe init failed.\n");
|
|
||||||
delete_io_submission_queue(nvme);
|
|
||||||
delete_io_completion_queue(nvme);
|
delete_io_completion_queue(nvme);
|
||||||
|
_delete_admin_abort:
|
||||||
delete_admin_queues(nvme);
|
delete_admin_queues(nvme);
|
||||||
|
_free_abort:
|
||||||
free(nvme->prp_list);
|
free(nvme->prp_list);
|
||||||
free(nvme);
|
free(nvme);
|
||||||
|
printf("NVMe init failed.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvme_initialize(struct pci_dev *dev)
|
void nvme_initialize(struct pci_dev *dev)
|
||||||
|
|
Loading…
Reference in New Issue