diff options
Diffstat (limited to 'drivers/net/ethernet/marvell/octeontx2/af/cgx.c')
-rw-r--r-- | drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 78 |
1 files changed, 58 insertions, 20 deletions
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c index 971993586fb4..4ff19a04b23e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -1182,17 +1182,25 @@ static int cgx_link_usertable_index_map(int speed) static void set_mod_args(struct cgx_set_link_mode_args *args, u32 speed, u8 duplex, u8 autoneg, u64 mode) { - /* Fill default values incase of user did not pass - * valid parameters + int mode_baseidx; + u8 cgx_mode; + + if (args->multimode) { + args->mode |= mode; + return; + } + + /* Derive mode_base_idx and mode fields based + * on cgx_mode value */ - if (args->duplex == DUPLEX_UNKNOWN) - args->duplex = duplex; - if (args->speed == SPEED_UNKNOWN) - args->speed = speed; - if (args->an == AUTONEG_UNKNOWN) - args->an = autoneg; + cgx_mode = find_first_bit((unsigned long *)&mode, + CGX_MODE_MAX); args->mode = mode; - args->ports = 0; + mode_baseidx = cgx_mode - 41; + if (mode_baseidx > 0) { + args->mode_baseidx = 1; + args->mode = BIT_ULL(mode_baseidx); + } } static void otx2_map_ethtool_link_modes(u64 bitmask, @@ -1200,16 +1208,16 @@ static void otx2_map_ethtool_link_modes(u64 bitmask, { switch (bitmask) { case ETHTOOL_LINK_MODE_10baseT_Half_BIT: - set_mod_args(args, 10, 1, 1, BIT_ULL(CGX_MODE_SGMII)); + set_mod_args(args, 10, 1, 1, BIT_ULL(CGX_MODE_SGMII_10M_BIT)); break; case ETHTOOL_LINK_MODE_10baseT_Full_BIT: - set_mod_args(args, 10, 0, 1, BIT_ULL(CGX_MODE_SGMII)); + set_mod_args(args, 10, 0, 1, BIT_ULL(CGX_MODE_SGMII_10M_BIT)); break; case ETHTOOL_LINK_MODE_100baseT_Half_BIT: - set_mod_args(args, 100, 1, 1, BIT_ULL(CGX_MODE_SGMII)); + set_mod_args(args, 100, 1, 1, BIT_ULL(CGX_MODE_SGMII_100M_BIT)); break; case ETHTOOL_LINK_MODE_100baseT_Full_BIT: - set_mod_args(args, 100, 0, 1, BIT_ULL(CGX_MODE_SGMII)); + set_mod_args(args, 100, 0, 1, BIT_ULL(CGX_MODE_SGMII_100M_BIT)); break; case ETHTOOL_LINK_MODE_1000baseT_Half_BIT: set_mod_args(args, 1000, 1, 1, BIT_ULL(CGX_MODE_SGMII)); @@ -1481,25 +1489,36 @@ int cgx_get_fwdata_base(u64 *base) } int cgx_set_link_mode(void *cgxd, struct cgx_set_link_mode_args args, + struct cgx_lmac_fwdata_s *linkmodes, int cgx_id, int lmac_id) { struct cgx *cgx = cgxd; u64 req = 0, resp; + u8 bit; if (!cgx) return -ENODEV; - if (args.mode) - otx2_map_ethtool_link_modes(args.mode, &args); - if (!args.speed && args.duplex && !args.an) - return -EINVAL; + for_each_set_bit(bit, args.advertising, + __ETHTOOL_LINK_MODE_MASK_NBITS) + otx2_map_ethtool_link_modes(bit, &args); + + if (args.multimode) { + if (linkmodes->advertised_link_modes_own != CGX_CMD_OWN_NS) + return -EBUSY; + + linkmodes->advertised_link_modes = args.mode; + /* Update ownership */ + linkmodes->advertised_link_modes_own = CGX_CMD_OWN_FIRMWARE; + args.mode = GENMASK_ULL(41, 0); + } req = FIELD_SET(CMDREG_ID, CGX_CMD_MODE_CHANGE, req); req = FIELD_SET(CMDMODECHANGE_SPEED, cgx_link_usertable_index_map(args.speed), req); req = FIELD_SET(CMDMODECHANGE_DUPLEX, args.duplex, req); req = FIELD_SET(CMDMODECHANGE_AN, args.an, req); - req = FIELD_SET(CMDMODECHANGE_PORT, args.ports, req); + req = FIELD_SET(CMDMODECHANGE_MODE_BASEIDX, args.mode_baseidx, req); req = FIELD_SET(CMDMODECHANGE_FLAGS, args.mode, req); return cgx_fwi_cmd_generic(req, &resp, cgx, lmac_id); @@ -1685,9 +1704,11 @@ unsigned long cgx_get_lmac_bmap(void *cgxd) static int cgx_lmac_init(struct cgx *cgx) { + u8 max_dmac_filters; struct lmac *lmac; + int err, filter; + unsigned int i; u64 lmac_list; - int i, err; /* lmac_list specifies which lmacs are enabled * when bit n is set to 1, LMAC[n] is enabled @@ -1713,7 +1734,7 @@ static int cgx_lmac_init(struct cgx *cgx) err = -ENOMEM; goto err_lmac_free; } - sprintf(lmac->name, "cgx_fwi_%d_%d", cgx->cgx_id, i); + sprintf(lmac->name, "cgx_fwi_%u_%u", cgx->cgx_id, i); if (cgx->mac_ops->non_contiguous_serdes_lane) { lmac->lmac_id = __ffs64(lmac_list); lmac_list &= ~BIT_ULL(lmac->lmac_id); @@ -1726,6 +1747,8 @@ static int cgx_lmac_init(struct cgx *cgx) cgx->mac_ops->dmac_filter_count / cgx->lmac_count; + max_dmac_filters = lmac->mac_to_index_bmap.max; + err = rvu_alloc_bitmap(&lmac->mac_to_index_bmap); if (err) goto err_name_free; @@ -1755,6 +1778,15 @@ static int cgx_lmac_init(struct cgx *cgx) set_bit(lmac->lmac_id, &cgx->lmac_bmap); cgx->mac_ops->mac_pause_frm_config(cgx, lmac->lmac_id, true); lmac->lmac_type = cgx->mac_ops->get_lmac_type(cgx, lmac->lmac_id); + + /* Disable stale DMAC filters for sane state */ + for (filter = 0; filter < max_dmac_filters; filter++) + cgx_lmac_addr_del(cgx->cgx_id, lmac->lmac_id, filter); + + /* As cgx_lmac_addr_del does not clear entry for index 0 + * so it needs to be done explicitly + */ + cgx_lmac_addr_reset(cgx->cgx_id, lmac->lmac_id); } /* Start X2P reset on given MAC block */ @@ -1932,6 +1964,12 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_disable_device; } + err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48)); + if (err) { + dev_err(dev, "DMA mask config failed, abort\n"); + goto err_release_regions; + } + /* MAP configuration registers */ cgx->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0); if (!cgx->reg_base) { |