misc: bcm-vk: add triggers when host panic or reboots to notify card

Pass down an interrupt to card in case of panic or reboot so
that card can take appropriate action to perform a clean reset.
Uses kernel notifier block either directly (register on panic list),
or implicitly (add shutdown method for PCI device).

Co-developed-by: Desmond Yan <desmond.yan@broadcom.com>
Acked-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Desmond Yan <desmond.yan@broadcom.com>
Signed-off-by: Scott Branden <scott.branden@broadcom.com>
Link: https://lore.kernel.org/r/20210120175827.14820-6-scott.branden@broadcom.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Scott Branden 2021-01-20 09:58:19 -08:00 committed by Greg Kroah-Hartman
parent bfc53e01d2
commit af22527e82
2 changed files with 30 additions and 1 deletions

View file

@ -223,6 +223,8 @@ struct bcm_vk {
unsigned long wq_offload[1]; /* various flags on wq requested */
void *tdma_vaddr; /* test dma segment virtual addr */
dma_addr_t tdma_addr; /* test dma segment bus addr */
struct notifier_block panic_nb;
};
/* wq offload work items bits definitions */

View file

@ -635,6 +635,16 @@ static int bcm_vk_trigger_reset(struct bcm_vk *vk)
return 0;
}
static int bcm_vk_on_panic(struct notifier_block *nb,
unsigned long e, void *p)
{
struct bcm_vk *vk = container_of(nb, struct bcm_vk, panic_nb);
bcm_to_v_reset_doorbell(vk, VK_BAR0_RESET_DB_HARD);
return 0;
}
static int bcm_vk_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int err;
@ -748,6 +758,15 @@ static int bcm_vk_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* sync other info */
bcm_vk_sync_card_info(vk);
/* register for panic notifier */
vk->panic_nb.notifier_call = bcm_vk_on_panic;
err = atomic_notifier_chain_register(&panic_notifier_list,
&vk->panic_nb);
if (err) {
dev_err(dev, "Fail to register panic notifier\n");
goto err_destroy_workqueue;
}
/*
* lets trigger an auto download. We don't want to do it serially here
* because at probing time, it is not supposed to block for a long time.
@ -756,7 +775,7 @@ static int bcm_vk_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (auto_load) {
if ((boot_status & BOOT_STATE_MASK) == BROM_RUNNING) {
if (bcm_vk_trigger_autoload(vk))
goto err_destroy_workqueue;
goto err_unregister_panic_notifier;
} else {
dev_err(dev,
"Auto-load skipped - BROM not in proper state (0x%x)\n",
@ -768,6 +787,10 @@ static int bcm_vk_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
err_unregister_panic_notifier:
atomic_notifier_chain_unregister(&panic_notifier_list,
&vk->panic_nb);
err_destroy_workqueue:
destroy_workqueue(vk->wq_thread);
@ -818,6 +841,10 @@ static void bcm_vk_remove(struct pci_dev *pdev)
bcm_vk_trigger_reset(vk);
usleep_range(BCM_VK_UCODE_BOOT_US, BCM_VK_UCODE_BOOT_MAX_US);
/* unregister panic notifier */
atomic_notifier_chain_unregister(&panic_notifier_list,
&vk->panic_nb);
if (vk->tdma_vaddr)
dma_free_coherent(&pdev->dev, nr_scratch_pages * PAGE_SIZE,
vk->tdma_vaddr, vk->tdma_addr);