diff options
Diffstat (limited to 'drivers/net/ethernet/marvell/octeontx2/af/cgx.c')
-rw-r--r-- | drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 69 |
1 files changed, 59 insertions, 10 deletions
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c index 25491edc35ce..c8724bfa86b0 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -498,6 +498,32 @@ static u8 cgx_get_lmac_type(void *cgxd, int lmac_id) return (cfg >> CGX_LMAC_TYPE_SHIFT) & CGX_LMAC_TYPE_MASK; } +static u32 cgx_get_lmac_fifo_len(void *cgxd, int lmac_id) +{ + struct cgx *cgx = cgxd; + u8 num_lmacs; + u32 fifo_len; + + fifo_len = cgx->mac_ops->fifo_len; + num_lmacs = cgx->mac_ops->get_nr_lmacs(cgx); + + switch (num_lmacs) { + case 1: + return fifo_len; + case 2: + return fifo_len / 2; + case 3: + /* LMAC0 gets half of the FIFO, reset 1/4th */ + if (lmac_id == 0) + return fifo_len / 2; + return fifo_len / 4; + case 4: + default: + return fifo_len / 4; + } + return 0; +} + /* Configure CGX LMAC in internal loopback mode */ int cgx_lmac_internal_loopback(void *cgxd, int lmac_id, bool enable) { @@ -847,6 +873,11 @@ static void cgx_lmac_pause_frm_config(void *cgxd, int lmac_id, bool enable) cfg |= CGX_CMR_RX_OVR_BP_EN(lmac_id); cfg &= ~CGX_CMR_RX_OVR_BP_BP(lmac_id); cgx_write(cgx, 0, CGXX_CMR_RX_OVR_BP, cfg); + + /* Disable all PFC classes by default */ + cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_CBFC_CTL); + cfg = FIELD_SET(CGX_PFC_CLASS_MASK, 0, cfg); + cgx_write(cgx, lmac_id, CGXX_SMUX_CBFC_CTL, cfg); } int verify_lmac_fc_cfg(void *cgxd, int lmac_id, u8 tx_pause, u8 rx_pause, @@ -899,6 +930,7 @@ int cgx_lmac_pfc_config(void *cgxd, int lmac_id, u8 tx_pause, return 0; cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_CBFC_CTL); + pfc_en |= FIELD_GET(CGX_PFC_CLASS_MASK, cfg); if (rx_pause) { cfg |= (CGXX_SMUX_CBFC_CTL_RX_EN | @@ -910,12 +942,13 @@ int cgx_lmac_pfc_config(void *cgxd, int lmac_id, u8 tx_pause, CGXX_SMUX_CBFC_CTL_DRP_EN); } - if (tx_pause) + if (tx_pause) { cfg |= CGXX_SMUX_CBFC_CTL_TX_EN; - else + cfg = FIELD_SET(CGX_PFC_CLASS_MASK, pfc_en, cfg); + } else { cfg &= ~CGXX_SMUX_CBFC_CTL_TX_EN; - - cfg = FIELD_SET(CGX_PFC_CLASS_MASK, pfc_en, cfg); + cfg = FIELD_SET(CGX_PFC_CLASS_MASK, 0, cfg); + } cgx_write(cgx, lmac_id, CGXX_SMUX_CBFC_CTL, cfg); @@ -1005,9 +1038,9 @@ int cgx_fwi_cmd_send(u64 req, u64 *resp, struct lmac *lmac) if (!wait_event_timeout(lmac->wq_cmd_cmplt, !lmac->cmd_pend, msecs_to_jiffies(CGX_CMD_TIMEOUT))) { dev = &cgx->pdev->dev; - dev_err(dev, "cgx port %d:%d cmd timeout\n", - cgx->cgx_id, lmac->lmac_id); - err = -EIO; + dev_err(dev, "cgx port %d:%d cmd %lld timeout\n", + cgx->cgx_id, lmac->lmac_id, FIELD_GET(CMDREG_ID, req)); + err = LMAC_AF_ERR_CMD_TIMEOUT; goto unlock; } @@ -1433,11 +1466,19 @@ static int cgx_fwi_link_change(struct cgx *cgx, int lmac_id, bool enable) u64 req = 0; u64 resp; - if (enable) + if (enable) { req = FIELD_SET(CMDREG_ID, CGX_CMD_LINK_BRING_UP, req); - else - req = FIELD_SET(CMDREG_ID, CGX_CMD_LINK_BRING_DOWN, req); + /* On CN10K firmware offloads link bring up/down operations to ECP + * On Octeontx2 link operations are handled by firmware itself + * which can cause mbox errors so configure maximum time firmware + * poll for Link as 1000 ms + */ + if (!is_dev_rpm(cgx)) + req = FIELD_SET(LINKCFG_TIMEOUT, 1000, req); + } else { + req = FIELD_SET(CMDREG_ID, CGX_CMD_LINK_BRING_DOWN, req); + } return cgx_fwi_cmd_generic(req, &resp, cgx, lmac_id); } @@ -1689,6 +1730,7 @@ static struct mac_ops cgx_mac_ops = { .tx_stats_cnt = 18, .get_nr_lmacs = cgx_get_nr_lmacs, .get_lmac_type = cgx_get_lmac_type, + .lmac_fifo_len = cgx_get_lmac_fifo_len, .mac_lmac_intl_lbk = cgx_lmac_internal_loopback, .mac_get_rx_stats = cgx_get_rx_stats, .mac_get_tx_stats = cgx_get_tx_stats, @@ -1743,6 +1785,13 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_release_regions; } + cgx->lmac_count = cgx->mac_ops->get_nr_lmacs(cgx); + if (!cgx->lmac_count) { + dev_notice(dev, "CGX %d LMAC count is zero, skipping probe\n", cgx->cgx_id); + err = -EOPNOTSUPP; + goto err_release_regions; + } + nvec = pci_msix_vec_count(cgx->pdev); err = pci_alloc_irq_vectors(pdev, nvec, nvec, PCI_IRQ_MSIX); if (err < 0 || err != nvec) { |