|
4 | 4 | * Copyright (C) 2018 Marvell. |
5 | 5 | * |
6 | 6 | */ |
7 | | - |
| 7 | +#include <linux/bitfield.h> |
8 | 8 | #include <linux/module.h> |
9 | 9 | #include <linux/pci.h> |
10 | 10 |
|
@@ -42,9 +42,18 @@ static int npa_aq_enqueue_wait(struct rvu *rvu, struct rvu_block *block, |
42 | 42 | return -EBUSY; |
43 | 43 | } |
44 | 44 |
|
45 | | - if (result->compcode != NPA_AQ_COMP_GOOD) |
| 45 | + if (result->compcode != NPA_AQ_COMP_GOOD) { |
46 | 46 | /* TODO: Replace this with some error code */ |
| 47 | + if (result->compcode == NPA_AQ_COMP_CTX_FAULT || |
| 48 | + result->compcode == NPA_AQ_COMP_LOCKERR || |
| 49 | + result->compcode == NPA_AQ_COMP_CTX_POISON) { |
| 50 | + if (rvu_ndc_fix_locked_cacheline(rvu, BLKADDR_NDC_NPA0)) |
| 51 | + dev_err(rvu->dev, |
| 52 | + "%s: Not able to unlock cachelines\n", __func__); |
| 53 | + } |
| 54 | + |
47 | 55 | return -EBUSY; |
| 56 | + } |
48 | 57 |
|
49 | 58 | return 0; |
50 | 59 | } |
@@ -545,3 +554,48 @@ void rvu_npa_lf_teardown(struct rvu *rvu, u16 pcifunc, int npalf) |
545 | 554 |
|
546 | 555 | npa_ctx_free(rvu, pfvf); |
547 | 556 | } |
| 557 | + |
| 558 | +/* Due to an Hardware errata, in some corner cases, AQ context lock |
| 559 | + * operations can result in a NDC way getting into an illegal state |
| 560 | + * of not valid but locked. |
| 561 | + * |
| 562 | + * This API solves the problem by clearing the lock bit of the NDC block. |
| 563 | + * The operation needs to be done for each line of all the NDC banks. |
| 564 | + */ |
| 565 | +int rvu_ndc_fix_locked_cacheline(struct rvu *rvu, int blkaddr) |
| 566 | +{ |
| 567 | + int bank, max_bank, line, max_line, err; |
| 568 | + u64 reg, ndc_af_const; |
| 569 | + |
| 570 | + /* Set the ENABLE bit(63) to '0' */ |
| 571 | + reg = rvu_read64(rvu, blkaddr, NDC_AF_CAMS_RD_INTERVAL); |
| 572 | + rvu_write64(rvu, blkaddr, NDC_AF_CAMS_RD_INTERVAL, reg & GENMASK_ULL(62, 0)); |
| 573 | + |
| 574 | + /* Poll until the BUSY bits(47:32) are set to '0' */ |
| 575 | + err = rvu_poll_reg(rvu, blkaddr, NDC_AF_CAMS_RD_INTERVAL, GENMASK_ULL(47, 32), true); |
| 576 | + if (err) { |
| 577 | + dev_err(rvu->dev, "Timed out while polling for NDC CAM busy bits.\n"); |
| 578 | + return err; |
| 579 | + } |
| 580 | + |
| 581 | + ndc_af_const = rvu_read64(rvu, blkaddr, NDC_AF_CONST); |
| 582 | + max_bank = FIELD_GET(NDC_AF_BANK_MASK, ndc_af_const); |
| 583 | + max_line = FIELD_GET(NDC_AF_BANK_LINE_MASK, ndc_af_const); |
| 584 | + for (bank = 0; bank < max_bank; bank++) { |
| 585 | + for (line = 0; line < max_line; line++) { |
| 586 | + /* Check if 'cache line valid bit(63)' is not set |
| 587 | + * but 'cache line lock bit(60)' is set and on |
| 588 | + * success, reset the lock bit(60). |
| 589 | + */ |
| 590 | + reg = rvu_read64(rvu, blkaddr, |
| 591 | + NDC_AF_BANKX_LINEX_METADATA(bank, line)); |
| 592 | + if (!(reg & BIT_ULL(63)) && (reg & BIT_ULL(60))) { |
| 593 | + rvu_write64(rvu, blkaddr, |
| 594 | + NDC_AF_BANKX_LINEX_METADATA(bank, line), |
| 595 | + reg & ~BIT_ULL(60)); |
| 596 | + } |
| 597 | + } |
| 598 | + } |
| 599 | + |
| 600 | + return 0; |
| 601 | +} |
0 commit comments