Skip to content

Commit

Permalink
Merge branch 'ionic-memory-usage-rework'
Browse files Browse the repository at this point in the history
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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 28, 2020
2 parents 161e310 + 6f7d6f0 commit f3fb15b
Show file tree
Hide file tree
Showing 12 changed files with 790 additions and 534 deletions.
4 changes: 1 addition & 3 deletions drivers/net/ethernet/pensando/ionic/ionic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
32 changes: 17 additions & 15 deletions drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -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:
Expand Down Expand Up @@ -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);
}

Expand Down
29 changes: 15 additions & 14 deletions drivers/net/ethernet/pensando/ionic/ionic_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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);
Expand Down
46 changes: 26 additions & 20 deletions drivers/net/ethernet/pensando/ionic/ionic_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -614,28 +617,31 @@ 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)
{
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);
}
Expand All @@ -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;
Expand Down
49 changes: 37 additions & 12 deletions drivers/net/ethernet/pensando/ionic/ionic_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,13 @@ struct ionic_dev {
};

struct ionic_cq_info {
void *cq_desc;
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;
Expand All @@ -169,8 +175,17 @@ struct ionic_page_info {
};

struct ionic_desc_info {
void *desc;
void *sg_desc;
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;
Expand All @@ -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;
void *base;
void *sg_base;
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;
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/pensando/ionic/ionic_devlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ int ionic_devlink_register(struct ionic *ionic)
dev_err(ionic->dev, "devlink_port_register failed: %d\n", err);
else
devlink_port_type_eth_set(&ionic->dl_port,
ionic->master_lif->netdev);
ionic->lif->netdev);

return err;
}
Expand Down
Loading

0 comments on commit f3fb15b

Please sign in to comment.