Commit 1f6d768a authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parents df428e40 e982ae6a
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -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;
}

+86 −42
Original line number Diff line number Diff line
@@ -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 > 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 (coal > IONIC_INTR_CTRL_COAL_MAX)
		return -ERANGE;

	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,
};

+24 −8
Original line number Diff line number Diff line
@@ -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);

+5 −8
Original line number Diff line number Diff line
@@ -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)