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

Merge branch 'ionic-memory-usage-rework'

Shannon Nelson says:

====================
ionic memory usage rework

Previous review comments have suggested [1],[2] that this driver
needs to rework how queue resources are managed and reconfigured
so that we don't do a full driver reset and to better handle
potential allocation failures.  This patchset is intended to
address those comments.

The first few patches clean some general issues and
simplify some of the memory structures.  The last 4 patches
specifically address queue parameter changes without a full
ionic_stop()/ionic_open().

[1] https://lore.kernel.org/netdev/20200706103305.182bd727@kicinski-fedora-pc1c0hjn.dhcp.thefacebook.com/
[2] https://lore.kernel.org/netdev/20200724.194417.2151242753657227232.davem@davemloft.net/



v3: use PTR_ALIGN without typecast
    fix up Neel's attribution

v2: use PTR_ALIGN
    recovery if netif_set_real_num_tx/rx_queues fails
    less racy queue bring up after reconfig
    common-ize the reconfig queue stop and start
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 161e3106 6f7d6f0f
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -42,13 +42,11 @@ struct ionic {
	struct ionic_dev_bar bars[IONIC_BARS_MAX];
	unsigned int num_bars;
	struct ionic_identity ident;
	struct list_head lifs;
	struct ionic_lif *master_lif;
	struct ionic_lif *lif;
	unsigned int nnqs_per_lif;
	unsigned int neqs_per_lif;
	unsigned int ntxqs_per_lif;
	unsigned int nrxqs_per_lif;
	DECLARE_BITMAP(lifbits, IONIC_LIFS_MAX);
	unsigned int nintrs;
	DECLARE_BITMAP(intrs, IONIC_INTR_CTRL_REGS_MAX);
	struct work_struct nb_work;
+17 −15
Original line number Diff line number Diff line
@@ -294,21 +294,21 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
		goto err_out_port_reset;
	}

	err = ionic_lifs_size(ionic);
	err = ionic_lif_size(ionic);
	if (err) {
		dev_err(dev, "Cannot size LIFs: %d, aborting\n", err);
		dev_err(dev, "Cannot size LIF: %d, aborting\n", err);
		goto err_out_port_reset;
	}

	err = ionic_lifs_alloc(ionic);
	err = ionic_lif_alloc(ionic);
	if (err) {
		dev_err(dev, "Cannot allocate LIFs: %d, aborting\n", err);
		dev_err(dev, "Cannot allocate LIF: %d, aborting\n", err);
		goto err_out_free_irqs;
	}

	err = ionic_lifs_init(ionic);
	err = ionic_lif_init(ionic->lif);
	if (err) {
		dev_err(dev, "Cannot init LIFs: %d, aborting\n", err);
		dev_err(dev, "Cannot init LIF: %d, aborting\n", err);
		goto err_out_free_lifs;
	}

@@ -321,9 +321,9 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
			dev_err(dev, "Cannot enable existing VFs: %d\n", err);
	}

	err = ionic_lifs_register(ionic);
	err = ionic_lif_register(ionic->lif);
	if (err) {
		dev_err(dev, "Cannot register LIFs: %d, aborting\n", err);
		dev_err(dev, "Cannot register LIF: %d, aborting\n", err);
		goto err_out_deinit_lifs;
	}

@@ -336,12 +336,13 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	return 0;

err_out_deregister_lifs:
	ionic_lifs_unregister(ionic);
	ionic_lif_unregister(ionic->lif);
err_out_deinit_lifs:
	ionic_vf_dealloc(ionic);
	ionic_lifs_deinit(ionic);
	ionic_lif_deinit(ionic->lif);
err_out_free_lifs:
	ionic_lifs_free(ionic);
	ionic_lif_free(ionic->lif);
	ionic->lif = NULL;
err_out_free_irqs:
	ionic_bus_free_irq_vectors(ionic);
err_out_port_reset:
@@ -377,11 +378,12 @@ static void ionic_remove(struct pci_dev *pdev)
	if (!ionic)
		return;

	if (ionic->master_lif) {
	if (ionic->lif) {
		ionic_devlink_unregister(ionic);
		ionic_lifs_unregister(ionic);
		ionic_lifs_deinit(ionic);
		ionic_lifs_free(ionic);
		ionic_lif_unregister(ionic->lif);
		ionic_lif_deinit(ionic->lif);
		ionic_lif_free(ionic->lif);
		ionic->lif = NULL;
		ionic_bus_free_irq_vectors(ionic);
	}

+15 −14
Original line number Diff line number Diff line
@@ -76,7 +76,7 @@ static int q_tail_show(struct seq_file *seq, void *v)
{
	struct ionic_queue *q = seq->private;

	seq_printf(seq, "%d\n", q->tail->index);
	seq_printf(seq, "%d\n", q->tail_idx);

	return 0;
}
@@ -86,7 +86,7 @@ static int q_head_show(struct seq_file *seq, void *v)
{
	struct ionic_queue *q = seq->private;

	seq_printf(seq, "%d\n", q->head->index);
	seq_printf(seq, "%d\n", q->head_idx);

	return 0;
}
@@ -96,7 +96,7 @@ static int cq_tail_show(struct seq_file *seq, void *v)
{
	struct ionic_cq *cq = seq->private;

	seq_printf(seq, "%d\n", cq->tail->index);
	seq_printf(seq, "%d\n", cq->tail_idx);

	return 0;
}
@@ -112,7 +112,8 @@ static const struct debugfs_reg32 intr_ctrl_regs[] = {

void ionic_debugfs_add_qcq(struct ionic_lif *lif, struct ionic_qcq *qcq)
{
	struct dentry *q_dentry, *cq_dentry, *intr_dentry, *stats_dentry;
	struct dentry *qcq_dentry, *q_dentry, *cq_dentry;
	struct dentry *intr_dentry, *stats_dentry;
	struct ionic_dev *idev = &lif->ionic->idev;
	struct debugfs_regset32 *intr_ctrl_regset;
	struct ionic_intr_info *intr = &qcq->intr;
@@ -121,21 +122,21 @@ void ionic_debugfs_add_qcq(struct ionic_lif *lif, struct ionic_qcq *qcq)
	struct ionic_queue *q = &qcq->q;
	struct ionic_cq *cq = &qcq->cq;

	qcq->dentry = debugfs_create_dir(q->name, lif->dentry);
	qcq_dentry = debugfs_create_dir(q->name, lif->dentry);
	if (IS_ERR_OR_NULL(qcq_dentry))
		return;
	qcq->dentry = qcq_dentry;

	debugfs_create_x32("total_size", 0400, qcq->dentry, &qcq->total_size);
	debugfs_create_x64("base_pa", 0400, qcq->dentry, &qcq->base_pa);
	debugfs_create_x64("q_base_pa", 0400, qcq_dentry, &qcq->q_base_pa);
	debugfs_create_x32("q_size", 0400, qcq_dentry, &qcq->q_size);
	debugfs_create_x64("cq_base_pa", 0400, qcq_dentry, &qcq->cq_base_pa);
	debugfs_create_x32("cq_size", 0400, qcq_dentry, &qcq->cq_size);
	debugfs_create_x64("sg_base_pa", 0400, qcq_dentry, &qcq->sg_base_pa);
	debugfs_create_x32("sg_size", 0400, qcq_dentry, &qcq->sg_size);

	q_dentry = debugfs_create_dir("q", qcq->dentry);

	debugfs_create_u32("index", 0400, q_dentry, &q->index);
	debugfs_create_x64("base_pa", 0400, q_dentry, &q->base_pa);
	if (qcq->flags & IONIC_QCQ_F_SG) {
		debugfs_create_x64("sg_base_pa", 0400, q_dentry,
				   &q->sg_base_pa);
		debugfs_create_u32("sg_desc_size", 0400, q_dentry,
				   &q->sg_desc_size);
	}
	debugfs_create_u32("num_descs", 0400, q_dentry, &q->num_descs);
	debugfs_create_u32("desc_size", 0400, q_dentry, &q->desc_size);
	debugfs_create_u32("pid", 0400, q_dentry, &q->pid);
+26 −20
Original line number Diff line number Diff line
@@ -21,8 +21,8 @@ static void ionic_watchdog_cb(struct timer_list *t)

	hb = ionic_heartbeat_check(ionic);

	if (hb >= 0 && ionic->master_lif)
		ionic_link_status_check_request(ionic->master_lif);
	if (hb >= 0 && ionic->lif)
		ionic_link_status_check_request(ionic->lif);
}

void ionic_init_devinfo(struct ionic *ionic)
@@ -126,7 +126,7 @@ int ionic_heartbeat_check(struct ionic *ionic)
	/* is this a transition? */
	if (fw_status != idev->last_fw_status &&
	    idev->last_fw_status != 0xff) {
		struct ionic_lif *lif = ionic->master_lif;
		struct ionic_lif *lif = ionic->lif;
		bool trigger = false;

		if (!fw_status || fw_status == 0xff) {
@@ -482,7 +482,7 @@ int ionic_cq_init(struct ionic_lif *lif, struct ionic_cq *cq,
	cq->bound_intr = intr;
	cq->num_descs = num_descs;
	cq->desc_size = desc_size;
	cq->tail = cq->info;
	cq->tail_idx = 0;
	cq->done_color = 1;

	cur = cq->info;
@@ -522,15 +522,18 @@ unsigned int ionic_cq_service(struct ionic_cq *cq, unsigned int work_to_do,
			      ionic_cq_cb cb, ionic_cq_done_cb done_cb,
			      void *done_arg)
{
	struct ionic_cq_info *cq_info;
	unsigned int work_done = 0;

	if (work_to_do == 0)
		return 0;

	while (cb(cq, cq->tail)) {
		if (cq->tail->last)
	cq_info = &cq->info[cq->tail_idx];
	while (cb(cq, cq_info)) {
		if (cq->tail_idx == cq->num_descs - 1)
			cq->done_color = !cq->done_color;
		cq->tail = cq->tail->next;
		cq->tail_idx = (cq->tail_idx + 1) & (cq->num_descs - 1);
		cq_info = &cq->info[cq->tail_idx];
		DEBUG_STATS_CQE_CNT(cq);

		if (++work_done >= work_to_do)
@@ -565,8 +568,8 @@ int ionic_q_init(struct ionic_lif *lif, struct ionic_dev *idev,
	q->num_descs = num_descs;
	q->desc_size = desc_size;
	q->sg_desc_size = sg_desc_size;
	q->tail = q->info;
	q->head = q->tail;
	q->tail_idx = 0;
	q->head_idx = 0;
	q->pid = pid;

	snprintf(q->name, sizeof(q->name), "L%d-%s%u", lif->index, name, index);
@@ -614,19 +617,22 @@ void ionic_q_post(struct ionic_queue *q, bool ring_doorbell, ionic_desc_cb cb,
		  void *cb_arg)
{
	struct device *dev = q->lif->ionic->dev;
	struct ionic_desc_info *desc_info;
	struct ionic_lif *lif = q->lif;

	q->head->cb = cb;
	q->head->cb_arg = cb_arg;
	q->head = q->head->next;
	desc_info = &q->info[q->head_idx];
	desc_info->cb = cb;
	desc_info->cb_arg = cb_arg;

	q->head_idx = (q->head_idx + 1) & (q->num_descs - 1);

	dev_dbg(dev, "lif=%d qname=%s qid=%d qtype=%d p_index=%d ringdb=%d\n",
		q->lif->index, q->name, q->hw_type, q->hw_index,
		q->head->index, ring_doorbell);
		q->head_idx, ring_doorbell);

	if (ring_doorbell)
		ionic_dbell_ring(lif->kern_dbpage, q->hw_type,
				 q->dbval | q->head->index);
				 q->dbval | q->head_idx);
}

static bool ionic_q_is_posted(struct ionic_queue *q, unsigned int pos)
@@ -634,8 +640,8 @@ static bool ionic_q_is_posted(struct ionic_queue *q, unsigned int pos)
	unsigned int mask, tail, head;

	mask = q->num_descs - 1;
	tail = q->tail->index;
	head = q->head->index;
	tail = q->tail_idx;
	head = q->head_idx;

	return ((pos - tail) & mask) < ((head - tail) & mask);
}
@@ -648,18 +654,18 @@ void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info,
	void *cb_arg;

	/* check for empty queue */
	if (q->tail->index == q->head->index)
	if (q->tail_idx == q->head_idx)
		return;

	/* stop index must be for a descriptor that is not yet completed */
	if (unlikely(!ionic_q_is_posted(q, stop_index)))
		dev_err(q->lif->ionic->dev,
			"ionic stop is not posted %s stop %u tail %u head %u\n",
			q->name, stop_index, q->tail->index, q->head->index);
			q->name, stop_index, q->tail_idx, q->head_idx);

	do {
		desc_info = q->tail;
		q->tail = desc_info->next;
		desc_info = &q->info[q->tail_idx];
		q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);

		cb = desc_info->cb;
		cb_arg = desc_info->cb_arg;
+37 −12
Original line number Diff line number Diff line
@@ -149,7 +149,13 @@ struct ionic_dev {
};

struct ionic_cq_info {
	union {
		void *cq_desc;
		struct ionic_txq_comp *txcq;
		struct ionic_rxq_comp *rxcq;
		struct ionic_admin_comp *admincq;
		struct ionic_notifyq_event *notifyq;
	};
	struct ionic_cq_info *next;
	unsigned int index;
	bool last;
@@ -169,8 +175,17 @@ struct ionic_page_info {
};

struct ionic_desc_info {
	union {
		void *desc;
		struct ionic_txq_desc *txq_desc;
		struct ionic_rxq_desc *rxq_desc;
		struct ionic_admin_cmd *adminq_desc;
	};
	union {
		void *sg_desc;
		struct ionic_txq_sg_desc *txq_sg_desc;
		struct ionic_rxq_sg_desc *rxq_sgl_desc;
	};
	struct ionic_desc_info *next;
	unsigned int index;
	unsigned int left;
@@ -183,22 +198,32 @@ struct ionic_desc_info {
#define IONIC_QUEUE_NAME_MAX_SZ		32

struct ionic_queue {
	struct device *dev;
	u64 dbell_count;
	u64 drop;
	u64 stop;
	u64 wake;
	struct ionic_lif *lif;
	struct ionic_desc_info *info;
	struct ionic_desc_info *tail;
	struct ionic_desc_info *head;
	struct ionic_dev *idev;
	u16 head_idx;
	u16 tail_idx;
	unsigned int index;
	unsigned int type;
	unsigned int hw_index;
	unsigned int hw_type;
	u64 dbval;
	union {
		void *base;
		struct ionic_txq_desc *txq;
		struct ionic_rxq_desc *rxq;
		struct ionic_admin_cmd *adminq;
	};
	union {
		void *sg_base;
		struct ionic_txq_sg_desc *txq_sgl;
		struct ionic_rxq_sg_desc *rxq_sgl;
	};
	dma_addr_t base_pa;
	dma_addr_t sg_base_pa;
	unsigned int num_descs;
@@ -225,9 +250,9 @@ struct ionic_cq {
	dma_addr_t base_pa;
	struct ionic_lif *lif;
	struct ionic_cq_info *info;
	struct ionic_cq_info *tail;
	struct ionic_queue *bound_q;
	struct ionic_intr_info *bound_intr;
	u16 tail_idx;
	bool done_color;
	unsigned int num_descs;
	u64 compl_count;
@@ -246,12 +271,12 @@ static inline void ionic_intr_init(struct ionic_dev *idev,

static inline unsigned int ionic_q_space_avail(struct ionic_queue *q)
{
	unsigned int avail = q->tail->index;
	unsigned int avail = q->tail_idx;

	if (q->head->index >= avail)
		avail += q->head->left - 1;
	if (q->head_idx >= avail)
		avail += q->num_descs - q->head_idx - 1;
	else
		avail -= q->head->index + 1;
		avail -= q->head_idx + 1;

	return avail;
}
Loading