diff options
Diffstat (limited to 'drivers/net/ethernet/cavium/thunder/thunder_bgx.c')
-rw-r--r-- | drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 74 |
1 files changed, 71 insertions, 3 deletions
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index 050e21fbb147..9211c750e064 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -161,6 +161,7 @@ void bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status) return; lmac = &bgx->lmac[lmacid]; + link->mac_type = lmac->lmac_type; link->link_up = lmac->link_up; link->duplex = lmac->last_duplex; link->speed = lmac->last_speed; @@ -211,6 +212,47 @@ void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable) } EXPORT_SYMBOL(bgx_lmac_rx_tx_enable); +void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause) +{ + struct pfc *pfc = (struct pfc *)pause; + struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx]; + struct lmac *lmac; + u64 cfg; + + if (!bgx) + return; + lmac = &bgx->lmac[lmacid]; + if (lmac->is_sgmii) + return; + + cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_CBFC_CTL); + pfc->fc_rx = cfg & RX_EN; + pfc->fc_tx = cfg & TX_EN; + pfc->autoneg = 0; +} +EXPORT_SYMBOL(bgx_lmac_get_pfc); + +void bgx_lmac_set_pfc(int node, int bgx_idx, int lmacid, void *pause) +{ + struct pfc *pfc = (struct pfc *)pause; + struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx]; + struct lmac *lmac; + u64 cfg; + + if (!bgx) + return; + lmac = &bgx->lmac[lmacid]; + if (lmac->is_sgmii) + return; + + cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_CBFC_CTL); + cfg &= ~(RX_EN | TX_EN); + cfg |= (pfc->fc_rx ? RX_EN : 0x00); + cfg |= (pfc->fc_tx ? TX_EN : 0x00); + bgx_reg_write(bgx, lmacid, BGX_SMUX_CBFC_CTL, cfg); +} +EXPORT_SYMBOL(bgx_lmac_set_pfc); + static void bgx_sgmii_change_link_state(struct lmac *lmac) { struct bgx *bgx = lmac->bgx; @@ -524,6 +566,18 @@ static int bgx_lmac_xaui_init(struct bgx *bgx, struct lmac *lmac) cfg |= SMU_TX_CTL_DIC_EN; bgx_reg_write(bgx, lmacid, BGX_SMUX_TX_CTL, cfg); + /* Enable receive and transmission of pause frames */ + bgx_reg_write(bgx, lmacid, BGX_SMUX_CBFC_CTL, ((0xffffULL << 32) | + BCK_EN | DRP_EN | TX_EN | RX_EN)); + /* Configure pause time and interval */ + bgx_reg_write(bgx, lmacid, + BGX_SMUX_TX_PAUSE_PKT_TIME, DEFAULT_PAUSE_TIME); + cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_TX_PAUSE_PKT_INTERVAL); + cfg &= ~0xFFFFull; + bgx_reg_write(bgx, lmacid, BGX_SMUX_TX_PAUSE_PKT_INTERVAL, + cfg | (DEFAULT_PAUSE_TIME - 0x1000)); + bgx_reg_write(bgx, lmacid, BGX_SMUX_TX_PAUSE_ZERO, 0x01); + /* take lmac_count into account */ bgx_reg_modify(bgx, lmacid, BGX_SMUX_TX_THRESH, (0x100 - 1)); /* max packet size */ @@ -970,11 +1024,25 @@ static void bgx_set_lmac_config(struct bgx *bgx, u8 idx) lmac_set_training(bgx, lmac, lmac->lmacid); lmac_set_lane2sds(bgx, lmac); - /* Set LMAC type of other lmac on same DLM i.e LMAC 1/3 */ olmac = &bgx->lmac[idx + 1]; - olmac->lmac_type = lmac->lmac_type; + /* Check if other LMAC on the same DLM is already configured by + * firmware, if so use the same config or else set as same, as + * that of LMAC 0/2. + * This check is needed as on 80xx only one lane of each of the + * DLM of BGX0 is used, so have to rely on firmware for + * distingushing 80xx from 81xx. + */ + cmr_cfg = bgx_reg_read(bgx, idx + 1, BGX_CMRX_CFG); + lmac_type = (u8)((cmr_cfg >> 8) & 0x07); + lane_to_sds = (u8)(cmr_cfg & 0xFF); + if ((lmac_type == 0) && (lane_to_sds == 0xE4)) { + olmac->lmac_type = lmac->lmac_type; + lmac_set_lane2sds(bgx, olmac); + } else { + olmac->lmac_type = lmac_type; + olmac->lane_to_sds = lane_to_sds; + } lmac_set_training(bgx, olmac, olmac->lmacid); - lmac_set_lane2sds(bgx, olmac); } } |