if (!idev->port_info) {
netdev_err(netdev, "port_info not initialized\n"); return -EOPNOTSUPP;
}
/* The port_info data is found in a DMA space that the NIC keeps * up-to-date, so there's no need to request the data from the * NIC, we already have it in our memory space.
*/
switch (le16_to_cpu(idev->port_info->status.xcvr.pid)) { /* Copper */ case IONIC_XCVR_PID_QSFP_100G_CR4:
ethtool_link_ksettings_add_link_mode(ks, supported,
100000baseCR4_Full);
copper_seen++; break; case IONIC_XCVR_PID_QSFP_40GBASE_CR4:
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseCR4_Full);
copper_seen++; break; case IONIC_XCVR_PID_SFP_25GBASE_CR_S: case IONIC_XCVR_PID_SFP_25GBASE_CR_L: case IONIC_XCVR_PID_SFP_25GBASE_CR_N:
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseCR_Full);
copper_seen++; break; case IONIC_XCVR_PID_QSFP_50G_CR2_FC: case IONIC_XCVR_PID_QSFP_50G_CR2:
ethtool_link_ksettings_add_link_mode(ks, supported,
50000baseCR2_Full);
copper_seen++; break; case IONIC_XCVR_PID_QSFP_200G_CR4:
ethtool_link_ksettings_add_link_mode(ks, supported, 200000baseCR4_Full);
copper_seen++; break; case IONIC_XCVR_PID_QSFP_400G_CR4:
ethtool_link_ksettings_add_link_mode(ks, supported, 400000baseCR4_Full);
copper_seen++; break; case IONIC_XCVR_PID_SFP_10GBASE_AOC: case IONIC_XCVR_PID_SFP_10GBASE_CU:
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseCR_Full);
copper_seen++; break;
/* Fibre */ case IONIC_XCVR_PID_QSFP_100G_SR4: case IONIC_XCVR_PID_QSFP_100G_AOC:
ethtool_link_ksettings_add_link_mode(ks, supported,
100000baseSR4_Full); break; case IONIC_XCVR_PID_QSFP_100G_CWDM4: case IONIC_XCVR_PID_QSFP_100G_PSM4: case IONIC_XCVR_PID_QSFP_100G_LR4:
ethtool_link_ksettings_add_link_mode(ks, supported,
100000baseLR4_ER4_Full); break; case IONIC_XCVR_PID_QSFP_100G_ER4:
ethtool_link_ksettings_add_link_mode(ks, supported,
100000baseLR4_ER4_Full); break; case IONIC_XCVR_PID_QSFP_40GBASE_SR4: case IONIC_XCVR_PID_QSFP_40GBASE_AOC:
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseSR4_Full); break; case IONIC_XCVR_PID_QSFP_40GBASE_LR4:
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseLR4_Full); break; case IONIC_XCVR_PID_SFP_25GBASE_SR: case IONIC_XCVR_PID_SFP_25GBASE_AOC: case IONIC_XCVR_PID_SFP_25GBASE_ACC:
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseSR_Full); break; case IONIC_XCVR_PID_QSFP_200G_AOC: case IONIC_XCVR_PID_QSFP_200G_SR4:
ethtool_link_ksettings_add_link_mode(ks, supported,
200000baseSR4_Full); break; case IONIC_XCVR_PID_QSFP_200G_FR4:
ethtool_link_ksettings_add_link_mode(ks, supported,
200000baseLR4_ER4_FR4_Full); break; case IONIC_XCVR_PID_QSFP_200G_DR4:
ethtool_link_ksettings_add_link_mode(ks, supported,
200000baseDR4_Full); break; case IONIC_XCVR_PID_QSFP_400G_FR4:
ethtool_link_ksettings_add_link_mode(ks, supported,
400000baseLR4_ER4_FR4_Full); break; case IONIC_XCVR_PID_QSFP_400G_DR4:
ethtool_link_ksettings_add_link_mode(ks, supported,
400000baseDR4_Full); break; case IONIC_XCVR_PID_QSFP_400G_SR4:
ethtool_link_ksettings_add_link_mode(ks, supported,
400000baseSR4_Full); break; case IONIC_XCVR_PID_SFP_10GBASE_SR:
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseSR_Full); break; case IONIC_XCVR_PID_SFP_10GBASE_LR:
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseLR_Full); break; case IONIC_XCVR_PID_SFP_10GBASE_LRM:
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseLRM_Full); break; case IONIC_XCVR_PID_SFP_10GBASE_ER:
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseER_Full); break; case IONIC_XCVR_PID_SFP_10GBASE_T:
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseT_Full); break; case IONIC_XCVR_PID_SFP_1000BASE_T:
ethtool_link_ksettings_add_link_mode(ks, supported,
1000baseT_Full); break; case IONIC_XCVR_PID_UNKNOWN: /* This means there's no module plugged in */ break; default:
dev_info(lif->ionic->dev, "unknown xcvr type pid=%d / 0x%x\n",
idev->port_info->status.xcvr.pid,
idev->port_info->status.xcvr.pid); break;
}
if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) return -EBUSY;
if (pause->autoneg) return -EOPNOTSUPP;
/* change both at the same time */
requested_pause = IONIC_PORT_PAUSE_TYPE_LINK; if (pause->rx_pause)
requested_pause |= IONIC_PAUSE_F_RX; if (pause->tx_pause)
requested_pause |= IONIC_PAUSE_F_TX;
if (requested_pause == lif->ionic->idev.port_info->config.pause_type) return 0;
ident = &lif->ionic->ident; if (ident->dev.intr_coal_div == 0) {
netdev_warn(netdev, "bad HW value in dev.intr_coal_div = %d\n",
ident->dev.intr_coal_div); return -EIO;
}
/* Tx normally shares Rx interrupt, so only change Rx if not split */ if (!test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state) &&
(coalesce->tx_coalesce_usecs != lif->rx_coalesce_usecs ||
coalesce->use_adaptive_tx_coalesce)) {
netdev_warn(netdev, "only rx parameters can be changed\n"); return -EINVAL;
}
/* Convert the usec request to a HW usable value. If they asked * for non-zero and it resolved to zero, bump it up
*/
rx_coal = ionic_coal_usec_to_hw(lif->ionic, coalesce->rx_coalesce_usecs); if (!rx_coal && coalesce->rx_coalesce_usecs)
rx_coal = 1;
tx_coal = ionic_coal_usec_to_hw(lif->ionic, coalesce->tx_coalesce_usecs); if (!tx_coal && coalesce->tx_coalesce_usecs)
tx_coal = 1;
if (rx_coal > IONIC_INTR_CTRL_COAL_MAX ||
tx_coal > IONIC_INTR_CTRL_COAL_MAX) return -ERANGE;
/* Save the new values */
lif->rx_coalesce_usecs = coalesce->rx_coalesce_usecs;
lif->rx_coalesce_hw = rx_coal;
if (test_bit(IONIC_LIF_F_UP, lif->state)) { for (i = 0; i < lif->nxqs; i++) { if (lif->rxqcqs[i]->flags & IONIC_QCQ_F_INTR) {
ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
lif->rxqcqs[i]->intr.index,
lif->rx_coalesce_hw);
lif->rxqcqs[i]->intr.dim_coal_hw = rx_dim;
}
if (!lif->ionic->idev.cmb_inuse &&
(qparam->cmb_tx || qparam->cmb_rx)) {
netdev_info(lif->netdev, "CMB rings are not supported on this device\n"); return -EOPNOTSUPP;
}
if (qparam->cmb_tx) { if (!(lif->qtype_info[IONIC_QTYPE_TXQ].features & IONIC_QIDENT_F_CMB)) {
netdev_info(lif->netdev, "CMB rings for tx-push are not supported on this device\n"); return -EOPNOTSUPP;
}
if (qparam->cmb_rx) { if (!(lif->qtype_info[IONIC_QTYPE_RXQ].features & IONIC_QIDENT_F_CMB)) {
netdev_info(lif->netdev, "CMB rings for rx-push are not supported on this device\n"); return -EOPNOTSUPP;
}
pages_have = lif->ionic->bars[IONIC_PCI_BAR_CMB].len / PAGE_SIZE; if (pages_required > pages_have) {
netdev_info(lif->netdev, "Not enough CMB pages for number of queues and size of descriptor rings, need %d have %d",
pages_required, pages_have); return -ENOMEM;
}
if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) return -EBUSY;
ionic_init_queue_params(lif, &qparam);
if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
netdev_info(netdev, "Changing jumbo or mini descriptors not supported\n"); return -EINVAL;
}
if (!is_power_of_2(ring->tx_pending) ||
!is_power_of_2(ring->rx_pending)) {
netdev_info(netdev, "Descriptor count must be a power of 2\n"); return -EINVAL;
}
/* if nothing to do return success */ if (ring->tx_pending == lif->ntxq_descs &&
ring->rx_pending == lif->nrxq_descs &&
kernel_ring->tx_push == test_bit(IONIC_LIF_F_CMB_TX_RINGS, lif->state) &&
kernel_ring->rx_push == test_bit(IONIC_LIF_F_CMB_RX_RINGS, lif->state)) return 0;
if (ring->tx_pending != lif->ntxq_descs)
netdev_info(netdev, "Changing Tx ring size from %d to %d\n",
lif->ntxq_descs, ring->tx_pending);
if (ring->rx_pending != lif->nrxq_descs)
netdev_info(netdev, "Changing Rx ring size from %d to %d\n",
lif->nrxq_descs, ring->rx_pending);
/* if we're not running, just set the values and return */ if (!netif_running(lif->netdev)) {
lif->ntxq_descs = ring->tx_pending;
lif->nrxq_descs = ring->rx_pending; return 0;
}
staticint ionic_set_channels(struct net_device *netdev, struct ethtool_channels *ch)
{ struct ionic_lif *lif = netdev_priv(netdev); struct ionic_queue_params qparam; int max_cnt; int err;
if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) return -EBUSY;
ionic_init_queue_params(lif, &qparam);
if ((ch->rx_count || ch->tx_count) && lif->xdp_prog) {
netdev_info(lif->netdev, "Split Tx/Rx interrupts not available when using XDP\n"); return -EOPNOTSUPP;
}
if (ch->rx_count != ch->tx_count) {
netdev_info(netdev, "The rx and tx count must be equal\n"); return -EINVAL;
}
if (ch->combined_count && ch->rx_count) {
netdev_info(netdev, "Use either combined or rx and tx, not both\n"); return -EINVAL;
}
max_cnt = lif->ionic->ntxqs_per_lif; if (ch->combined_count) { if (ch->combined_count > max_cnt) return -EINVAL;
if (rxfh->indir) {
tbl_sz = le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz); for (i = 0; i < tbl_sz; i++)
rxfh->indir[i] = lif->rss_ind_tbl[i];
}
if (rxfh->key)
memcpy(rxfh->key, lif->rss_hash_key, IONIC_RSS_HASH_KEY_SIZE);
/* The NIC keeps the module prom up-to-date in the DMA space * so we can simply copy the module bytes into the data buffer.
*/ do {
memcpy(dst, src, len);
memcpy(tbuf, src, len);
/* Let's make sure we got a consistent copy */ if (!memcmp(dst, tbuf, len)) break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.