mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-20 16:40:16 +07:00
Merge branch 'ionic-driver-updates'
Shannon Nelson says: ==================== ionic: driver updates These patches are a few updates to clean up some code issues and add an ethtool feature. v3: drop the Fixes tags as they really aren't fixing bugs simplify ionic_lif_quiesce() as no return is necessary v2: add cover letter edit a couple of patch descriptions for clarity and add Fixes: tags ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
1f6d768a09
@ -19,31 +19,30 @@ static int ionic_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
|
||||
|
||||
err = devlink_info_driver_name_put(req, IONIC_DRV_NAME);
|
||||
if (err)
|
||||
goto info_out;
|
||||
return err;
|
||||
|
||||
err = devlink_info_version_running_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW,
|
||||
idev->dev_info.fw_version);
|
||||
if (err)
|
||||
goto info_out;
|
||||
return err;
|
||||
|
||||
snprintf(buf, sizeof(buf), "0x%x", idev->dev_info.asic_type);
|
||||
err = devlink_info_version_fixed_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_ASIC_ID,
|
||||
buf);
|
||||
if (err)
|
||||
goto info_out;
|
||||
return err;
|
||||
|
||||
snprintf(buf, sizeof(buf), "0x%x", idev->dev_info.asic_rev);
|
||||
err = devlink_info_version_fixed_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_ASIC_REV,
|
||||
buf);
|
||||
if (err)
|
||||
goto info_out;
|
||||
return err;
|
||||
|
||||
err = devlink_info_serial_number_put(req, idev->dev_info.serial_num);
|
||||
|
||||
info_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -254,12 +254,9 @@ static int ionic_set_link_ksettings(struct net_device *netdev,
|
||||
struct ionic_lif *lif = netdev_priv(netdev);
|
||||
struct ionic *ionic = lif->ionic;
|
||||
struct ionic_dev *idev;
|
||||
u32 req_rs, req_fc;
|
||||
u8 fec_type;
|
||||
int err = 0;
|
||||
|
||||
idev = &lif->ionic->idev;
|
||||
fec_type = IONIC_PORT_FEC_TYPE_NONE;
|
||||
|
||||
/* set autoneg */
|
||||
if (ks->base.autoneg != idev->port_info->config.an_enable) {
|
||||
@ -281,29 +278,6 @@ static int ionic_set_link_ksettings(struct net_device *netdev,
|
||||
return err;
|
||||
}
|
||||
|
||||
/* set FEC */
|
||||
req_rs = ethtool_link_ksettings_test_link_mode(ks, advertising, FEC_RS);
|
||||
req_fc = ethtool_link_ksettings_test_link_mode(ks, advertising, FEC_BASER);
|
||||
if (req_rs && req_fc) {
|
||||
netdev_info(netdev, "Only select one FEC mode at a time\n");
|
||||
return -EINVAL;
|
||||
} else if (req_fc) {
|
||||
fec_type = IONIC_PORT_FEC_TYPE_FC;
|
||||
} else if (req_rs) {
|
||||
fec_type = IONIC_PORT_FEC_TYPE_RS;
|
||||
} else if (!(req_rs | req_fc)) {
|
||||
fec_type = IONIC_PORT_FEC_TYPE_NONE;
|
||||
}
|
||||
|
||||
if (fec_type != idev->port_info->config.fec_type) {
|
||||
mutex_lock(&ionic->dev_cmd_lock);
|
||||
ionic_dev_cmd_port_fec(idev, fec_type);
|
||||
err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
|
||||
mutex_unlock(&ionic->dev_cmd_lock);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -353,6 +327,70 @@ static int ionic_set_pauseparam(struct net_device *netdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ionic_get_fecparam(struct net_device *netdev,
|
||||
struct ethtool_fecparam *fec)
|
||||
{
|
||||
struct ionic_lif *lif = netdev_priv(netdev);
|
||||
|
||||
switch (lif->ionic->idev.port_info->config.fec_type) {
|
||||
case IONIC_PORT_FEC_TYPE_NONE:
|
||||
fec->active_fec = ETHTOOL_FEC_OFF;
|
||||
break;
|
||||
case IONIC_PORT_FEC_TYPE_RS:
|
||||
fec->active_fec = ETHTOOL_FEC_RS;
|
||||
break;
|
||||
case IONIC_PORT_FEC_TYPE_FC:
|
||||
fec->active_fec = ETHTOOL_FEC_BASER;
|
||||
break;
|
||||
}
|
||||
|
||||
fec->fec = ETHTOOL_FEC_OFF | ETHTOOL_FEC_RS | ETHTOOL_FEC_BASER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ionic_set_fecparam(struct net_device *netdev,
|
||||
struct ethtool_fecparam *fec)
|
||||
{
|
||||
struct ionic_lif *lif = netdev_priv(netdev);
|
||||
u8 fec_type;
|
||||
int ret = 0;
|
||||
|
||||
if (lif->ionic->idev.port_info->config.an_enable) {
|
||||
netdev_err(netdev, "FEC request not allowed while autoneg is enabled\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fec->fec) {
|
||||
case ETHTOOL_FEC_NONE:
|
||||
fec_type = IONIC_PORT_FEC_TYPE_NONE;
|
||||
break;
|
||||
case ETHTOOL_FEC_OFF:
|
||||
fec_type = IONIC_PORT_FEC_TYPE_NONE;
|
||||
break;
|
||||
case ETHTOOL_FEC_RS:
|
||||
fec_type = IONIC_PORT_FEC_TYPE_RS;
|
||||
break;
|
||||
case ETHTOOL_FEC_BASER:
|
||||
fec_type = IONIC_PORT_FEC_TYPE_FC;
|
||||
break;
|
||||
case ETHTOOL_FEC_AUTO:
|
||||
default:
|
||||
netdev_err(netdev, "FEC request 0x%04x not supported\n",
|
||||
fec->fec);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fec_type != lif->ionic->idev.port_info->config.fec_type) {
|
||||
mutex_lock(&lif->ionic->dev_cmd_lock);
|
||||
ionic_dev_cmd_port_fec(&lif->ionic->idev, fec_type);
|
||||
ret = ionic_dev_cmd_wait(lif->ionic, DEVCMD_TIMEOUT);
|
||||
mutex_unlock(&lif->ionic->dev_cmd_lock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ionic_get_coalesce(struct net_device *netdev,
|
||||
struct ethtool_coalesce *coalesce)
|
||||
{
|
||||
@ -372,7 +410,6 @@ static int ionic_set_coalesce(struct net_device *netdev,
|
||||
struct ionic_identity *ident;
|
||||
struct ionic_qcq *qcq;
|
||||
unsigned int i;
|
||||
u32 usecs;
|
||||
u32 coal;
|
||||
|
||||
if (coalesce->rx_max_coalesced_frames ||
|
||||
@ -410,26 +447,27 @@ static int ionic_set_coalesce(struct net_device *netdev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Convert the usec request to a HW useable value. If they asked
|
||||
* for non-zero and it resolved to zero, bump it up
|
||||
*/
|
||||
coal = ionic_coal_usec_to_hw(lif->ionic, coalesce->rx_coalesce_usecs);
|
||||
if (!coal && coalesce->rx_coalesce_usecs)
|
||||
coal = 1;
|
||||
|
||||
if (coal > IONIC_INTR_CTRL_COAL_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
/* If they asked for non-zero and it resolved to zero, bump it up */
|
||||
if (!coal && coalesce->rx_coalesce_usecs)
|
||||
coal = 1;
|
||||
|
||||
/* Convert it back to get device resolution */
|
||||
usecs = ionic_coal_hw_to_usec(lif->ionic, coal);
|
||||
|
||||
if (usecs != lif->rx_coalesce_usecs) {
|
||||
lif->rx_coalesce_usecs = usecs;
|
||||
/* Save the new value */
|
||||
lif->rx_coalesce_usecs = coalesce->rx_coalesce_usecs;
|
||||
if (coal != lif->rx_coalesce_hw) {
|
||||
lif->rx_coalesce_hw = coal;
|
||||
|
||||
if (test_bit(IONIC_LIF_UP, lif->state)) {
|
||||
for (i = 0; i < lif->nxqs; i++) {
|
||||
qcq = lif->rxqcqs[i].qcq;
|
||||
ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
|
||||
qcq->intr.index, coal);
|
||||
qcq->intr.index,
|
||||
lif->rx_coalesce_hw);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -453,6 +491,7 @@ static int ionic_set_ringparam(struct net_device *netdev,
|
||||
{
|
||||
struct ionic_lif *lif = netdev_priv(netdev);
|
||||
bool running;
|
||||
int err;
|
||||
|
||||
if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
|
||||
netdev_info(netdev, "Changing jumbo or mini descriptors not supported\n");
|
||||
@ -470,8 +509,9 @@ static int ionic_set_ringparam(struct net_device *netdev,
|
||||
ring->rx_pending == lif->nrxq_descs)
|
||||
return 0;
|
||||
|
||||
if (!ionic_wait_for_bit(lif, IONIC_LIF_QUEUE_RESET))
|
||||
return -EBUSY;
|
||||
err = ionic_wait_for_bit(lif, IONIC_LIF_QUEUE_RESET);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
running = test_bit(IONIC_LIF_UP, lif->state);
|
||||
if (running)
|
||||
@ -504,6 +544,7 @@ static int ionic_set_channels(struct net_device *netdev,
|
||||
{
|
||||
struct ionic_lif *lif = netdev_priv(netdev);
|
||||
bool running;
|
||||
int err;
|
||||
|
||||
if (!ch->combined_count || ch->other_count ||
|
||||
ch->rx_count || ch->tx_count)
|
||||
@ -512,8 +553,9 @@ static int ionic_set_channels(struct net_device *netdev,
|
||||
if (ch->combined_count == lif->nxqs)
|
||||
return 0;
|
||||
|
||||
if (!ionic_wait_for_bit(lif, IONIC_LIF_QUEUE_RESET))
|
||||
return -EBUSY;
|
||||
err = ionic_wait_for_bit(lif, IONIC_LIF_QUEUE_RESET);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
running = test_bit(IONIC_LIF_UP, lif->state);
|
||||
if (running)
|
||||
@ -747,6 +789,7 @@ static const struct ethtool_ops ionic_ethtool_ops = {
|
||||
.get_regs = ionic_get_regs,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_link_ksettings = ionic_get_link_ksettings,
|
||||
.set_link_ksettings = ionic_set_link_ksettings,
|
||||
.get_coalesce = ionic_get_coalesce,
|
||||
.set_coalesce = ionic_set_coalesce,
|
||||
.get_ringparam = ionic_get_ringparam,
|
||||
@ -769,7 +812,8 @@ static const struct ethtool_ops ionic_ethtool_ops = {
|
||||
.get_module_eeprom = ionic_get_module_eeprom,
|
||||
.get_pauseparam = ionic_get_pauseparam,
|
||||
.set_pauseparam = ionic_set_pauseparam,
|
||||
.set_link_ksettings = ionic_set_link_ksettings,
|
||||
.get_fecparam = ionic_get_fecparam,
|
||||
.set_fecparam = ionic_set_fecparam,
|
||||
.nway_reset = ionic_nway_reset,
|
||||
};
|
||||
|
||||
|
@ -242,6 +242,21 @@ static int ionic_qcq_disable(struct ionic_qcq *qcq)
|
||||
return ionic_adminq_post_wait(lif, &ctx);
|
||||
}
|
||||
|
||||
static void ionic_lif_quiesce(struct ionic_lif *lif)
|
||||
{
|
||||
struct ionic_admin_ctx ctx = {
|
||||
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
|
||||
.cmd.lif_setattr = {
|
||||
.opcode = IONIC_CMD_LIF_SETATTR,
|
||||
.attr = IONIC_LIF_ATTR_STATE,
|
||||
.index = lif->index,
|
||||
.state = IONIC_LIF_DISABLE
|
||||
},
|
||||
};
|
||||
|
||||
ionic_adminq_post_wait(lif, &ctx);
|
||||
}
|
||||
|
||||
static void ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)
|
||||
{
|
||||
struct ionic_dev *idev = &lif->ionic->idev;
|
||||
@ -1430,7 +1445,6 @@ static int ionic_txrx_alloc(struct ionic_lif *lif)
|
||||
unsigned int flags;
|
||||
unsigned int i;
|
||||
int err = 0;
|
||||
u32 coal;
|
||||
|
||||
flags = IONIC_QCQ_F_TX_STATS | IONIC_QCQ_F_SG;
|
||||
for (i = 0; i < lif->nxqs; i++) {
|
||||
@ -1447,7 +1461,6 @@ static int ionic_txrx_alloc(struct ionic_lif *lif)
|
||||
}
|
||||
|
||||
flags = IONIC_QCQ_F_RX_STATS | IONIC_QCQ_F_INTR;
|
||||
coal = ionic_coal_usec_to_hw(lif->ionic, lif->rx_coalesce_usecs);
|
||||
for (i = 0; i < lif->nxqs; i++) {
|
||||
err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags,
|
||||
lif->nrxq_descs,
|
||||
@ -1460,7 +1473,8 @@ static int ionic_txrx_alloc(struct ionic_lif *lif)
|
||||
lif->rxqcqs[i].qcq->stats = lif->rxqcqs[i].stats;
|
||||
|
||||
ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
|
||||
lif->rxqcqs[i].qcq->intr.index, coal);
|
||||
lif->rxqcqs[i].qcq->intr.index,
|
||||
lif->rx_coalesce_hw);
|
||||
ionic_link_qcq_interrupts(lif->rxqcqs[i].qcq,
|
||||
lif->txqcqs[i].qcq);
|
||||
}
|
||||
@ -1590,6 +1604,7 @@ int ionic_stop(struct net_device *netdev)
|
||||
netif_tx_disable(netdev);
|
||||
|
||||
ionic_txrx_disable(lif);
|
||||
ionic_lif_quiesce(lif);
|
||||
ionic_txrx_deinit(lif);
|
||||
ionic_txrx_free(lif);
|
||||
|
||||
@ -1619,8 +1634,9 @@ int ionic_reset_queues(struct ionic_lif *lif)
|
||||
/* Put off the next watchdog timeout */
|
||||
netif_trans_update(lif->netdev);
|
||||
|
||||
if (!ionic_wait_for_bit(lif, IONIC_LIF_QUEUE_RESET))
|
||||
return -EBUSY;
|
||||
err = ionic_wait_for_bit(lif, IONIC_LIF_QUEUE_RESET);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
running = netif_running(lif->netdev);
|
||||
if (running)
|
||||
@ -1639,7 +1655,6 @@ static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index
|
||||
struct net_device *netdev;
|
||||
struct ionic_lif *lif;
|
||||
int tbl_sz;
|
||||
u32 coal;
|
||||
int err;
|
||||
|
||||
netdev = alloc_etherdev_mqs(sizeof(*lif),
|
||||
@ -1670,8 +1685,9 @@ static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index
|
||||
lif->nrxq_descs = IONIC_DEF_TXRX_DESC;
|
||||
|
||||
/* Convert the default coalesce value to actual hw resolution */
|
||||
coal = ionic_coal_usec_to_hw(lif->ionic, IONIC_ITR_COAL_USEC_DEFAULT);
|
||||
lif->rx_coalesce_usecs = ionic_coal_hw_to_usec(lif->ionic, coal);
|
||||
lif->rx_coalesce_usecs = IONIC_ITR_COAL_USEC_DEFAULT;
|
||||
lif->rx_coalesce_hw = ionic_coal_hw_to_usec(lif->ionic,
|
||||
lif->rx_coalesce_usecs);
|
||||
|
||||
snprintf(lif->name, sizeof(lif->name), "lif%u", index);
|
||||
|
||||
|
@ -175,7 +175,9 @@ struct ionic_lif {
|
||||
unsigned long *dbid_inuse;
|
||||
unsigned int dbid_count;
|
||||
struct dentry *dentry;
|
||||
u32 rx_coalesce_usecs;
|
||||
u32 rx_coalesce_usecs; /* what the user asked for */
|
||||
u32 rx_coalesce_hw; /* what the hw is using */
|
||||
|
||||
u32 flags;
|
||||
struct work_struct tx_timeout_work;
|
||||
};
|
||||
@ -185,15 +187,10 @@ struct ionic_lif {
|
||||
#define lif_to_txq(lif, i) (&lif_to_txqcq((lif), i)->q)
|
||||
#define lif_to_rxq(lif, i) (&lif_to_txqcq((lif), i)->q)
|
||||
|
||||
/* return 0 if successfully set the bit, else non-zero */
|
||||
static inline int ionic_wait_for_bit(struct ionic_lif *lif, int bitname)
|
||||
{
|
||||
unsigned long tlimit = jiffies + HZ;
|
||||
|
||||
while (test_and_set_bit(bitname, lif->state) &&
|
||||
time_before(jiffies, tlimit))
|
||||
usleep_range(100, 200);
|
||||
|
||||
return test_bit(bitname, lif->state);
|
||||
return wait_on_bit_lock(lif->state, bitname, TASK_INTERRUPTIBLE);
|
||||
}
|
||||
|
||||
static inline u32 ionic_coal_usec_to_hw(struct ionic *ionic, u32 usecs)
|
||||
|
Loading…
Reference in New Issue
Block a user