Skip to content

Commit 40bc471

Browse files
emuslndavem330
authored andcommitted
ionic: add tx/rx-push support with device Component Memory Buffers
The ionic device has on-board memory (CMB) that can be used for descriptors as a way to speed descriptor access for faster packet processing. It is rumored to improve latency and/or packets-per-second for some profiles of small packet traffic, although your mileage may vary. Signed-off-by: Shannon Nelson <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5b4e9a7 commit 40bc471

File tree

8 files changed

+404
-21
lines changed

8 files changed

+404
-21
lines changed

drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
352352
err_out_reset:
353353
ionic_reset(ionic);
354354
err_out_teardown:
355+
ionic_dev_teardown(ionic);
355356
pci_clear_master(pdev);
356357
/* Don't fail the probe for these errors, keep
357358
* the hw interface around for inspection
@@ -390,6 +391,7 @@ static void ionic_remove(struct pci_dev *pdev)
390391

391392
ionic_port_reset(ionic);
392393
ionic_reset(ionic);
394+
ionic_dev_teardown(ionic);
393395
pci_clear_master(pdev);
394396
ionic_unmap_bars(ionic);
395397
pci_release_regions(pdev);

drivers/net/ethernet/pensando/ionic/ionic_dev.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ int ionic_dev_setup(struct ionic *ionic)
9292
unsigned int num_bars = ionic->num_bars;
9393
struct ionic_dev *idev = &ionic->idev;
9494
struct device *dev = ionic->dev;
95+
int size;
9596
u32 sig;
9697

9798
/* BAR0: dev_cmd and interrupts */
@@ -133,9 +134,36 @@ int ionic_dev_setup(struct ionic *ionic)
133134
idev->db_pages = bar->vaddr;
134135
idev->phy_db_pages = bar->bus_addr;
135136

137+
/* BAR2: optional controller memory mapping */
138+
bar++;
139+
mutex_init(&idev->cmb_inuse_lock);
140+
if (num_bars < 3 || !ionic->bars[IONIC_PCI_BAR_CMB].len) {
141+
idev->cmb_inuse = NULL;
142+
return 0;
143+
}
144+
145+
idev->phy_cmb_pages = bar->bus_addr;
146+
idev->cmb_npages = bar->len / PAGE_SIZE;
147+
size = BITS_TO_LONGS(idev->cmb_npages) * sizeof(long);
148+
idev->cmb_inuse = kzalloc(size, GFP_KERNEL);
149+
if (!idev->cmb_inuse)
150+
dev_warn(dev, "No memory for CMB, disabling\n");
151+
136152
return 0;
137153
}
138154

155+
void ionic_dev_teardown(struct ionic *ionic)
156+
{
157+
struct ionic_dev *idev = &ionic->idev;
158+
159+
kfree(idev->cmb_inuse);
160+
idev->cmb_inuse = NULL;
161+
idev->phy_cmb_pages = 0;
162+
idev->cmb_npages = 0;
163+
164+
mutex_destroy(&idev->cmb_inuse_lock);
165+
}
166+
139167
/* Devcmd Interface */
140168
bool ionic_is_fw_running(struct ionic_dev *idev)
141169
{
@@ -571,6 +599,33 @@ int ionic_db_page_num(struct ionic_lif *lif, int pid)
571599
return (lif->hw_index * lif->dbid_count) + pid;
572600
}
573601

602+
int ionic_get_cmb(struct ionic_lif *lif, u32 *pgid, phys_addr_t *pgaddr, int order)
603+
{
604+
struct ionic_dev *idev = &lif->ionic->idev;
605+
int ret;
606+
607+
mutex_lock(&idev->cmb_inuse_lock);
608+
ret = bitmap_find_free_region(idev->cmb_inuse, idev->cmb_npages, order);
609+
mutex_unlock(&idev->cmb_inuse_lock);
610+
611+
if (ret < 0)
612+
return ret;
613+
614+
*pgid = ret;
615+
*pgaddr = idev->phy_cmb_pages + ret * PAGE_SIZE;
616+
617+
return 0;
618+
}
619+
620+
void ionic_put_cmb(struct ionic_lif *lif, u32 pgid, int order)
621+
{
622+
struct ionic_dev *idev = &lif->ionic->idev;
623+
624+
mutex_lock(&idev->cmb_inuse_lock);
625+
bitmap_release_region(idev->cmb_inuse, pgid, order);
626+
mutex_unlock(&idev->cmb_inuse_lock);
627+
}
628+
574629
int ionic_cq_init(struct ionic_lif *lif, struct ionic_cq *cq,
575630
struct ionic_intr_info *intr,
576631
unsigned int num_descs, size_t desc_size)
@@ -679,6 +734,18 @@ void ionic_q_map(struct ionic_queue *q, void *base, dma_addr_t base_pa)
679734
cur->desc = base + (i * q->desc_size);
680735
}
681736

737+
void ionic_q_cmb_map(struct ionic_queue *q, void __iomem *base, dma_addr_t base_pa)
738+
{
739+
struct ionic_desc_info *cur;
740+
unsigned int i;
741+
742+
q->cmb_base = base;
743+
q->cmb_base_pa = base_pa;
744+
745+
for (i = 0, cur = q->info; i < q->num_descs; i++, cur++)
746+
cur->cmb_desc = base + (i * q->desc_size);
747+
}
748+
682749
void ionic_q_sg_map(struct ionic_queue *q, void *base, dma_addr_t base_pa)
683750
{
684751
struct ionic_desc_info *cur;

drivers/net/ethernet/pensando/ionic/ionic_dev.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ struct ionic_dev {
159159
struct ionic_intr __iomem *intr_ctrl;
160160
u64 __iomem *intr_status;
161161

162+
struct mutex cmb_inuse_lock; /* for cmb_inuse */
163+
unsigned long *cmb_inuse;
164+
dma_addr_t phy_cmb_pages;
165+
u32 cmb_npages;
166+
162167
u32 port_info_sz;
163168
struct ionic_port_info *port_info;
164169
dma_addr_t port_info_pa;
@@ -203,6 +208,7 @@ struct ionic_desc_info {
203208
struct ionic_rxq_desc *rxq_desc;
204209
struct ionic_admin_cmd *adminq_desc;
205210
};
211+
void __iomem *cmb_desc;
206212
union {
207213
void *sg_desc;
208214
struct ionic_txq_sg_desc *txq_sg_desc;
@@ -241,12 +247,14 @@ struct ionic_queue {
241247
struct ionic_rxq_desc *rxq;
242248
struct ionic_admin_cmd *adminq;
243249
};
250+
void __iomem *cmb_base;
244251
union {
245252
void *sg_base;
246253
struct ionic_txq_sg_desc *txq_sgl;
247254
struct ionic_rxq_sg_desc *rxq_sgl;
248255
};
249256
dma_addr_t base_pa;
257+
dma_addr_t cmb_base_pa;
250258
dma_addr_t sg_base_pa;
251259
unsigned int desc_size;
252260
unsigned int sg_desc_size;
@@ -309,6 +317,7 @@ static inline bool ionic_q_has_space(struct ionic_queue *q, unsigned int want)
309317

310318
void ionic_init_devinfo(struct ionic *ionic);
311319
int ionic_dev_setup(struct ionic *ionic);
320+
void ionic_dev_teardown(struct ionic *ionic);
312321

313322
void ionic_dev_cmd_go(struct ionic_dev *idev, union ionic_dev_cmd *cmd);
314323
u8 ionic_dev_cmd_status(struct ionic_dev *idev);
@@ -344,6 +353,9 @@ void ionic_dev_cmd_adminq_init(struct ionic_dev *idev, struct ionic_qcq *qcq,
344353

345354
int ionic_db_page_num(struct ionic_lif *lif, int pid);
346355

356+
int ionic_get_cmb(struct ionic_lif *lif, u32 *pgid, phys_addr_t *pgaddr, int order);
357+
void ionic_put_cmb(struct ionic_lif *lif, u32 pgid, int order);
358+
347359
int ionic_cq_init(struct ionic_lif *lif, struct ionic_cq *cq,
348360
struct ionic_intr_info *intr,
349361
unsigned int num_descs, size_t desc_size);
@@ -360,6 +372,7 @@ int ionic_q_init(struct ionic_lif *lif, struct ionic_dev *idev,
360372
unsigned int num_descs, size_t desc_size,
361373
size_t sg_desc_size, unsigned int pid);
362374
void ionic_q_map(struct ionic_queue *q, void *base, dma_addr_t base_pa);
375+
void ionic_q_cmb_map(struct ionic_queue *q, void __iomem *base, dma_addr_t base_pa);
363376
void ionic_q_sg_map(struct ionic_queue *q, void *base, dma_addr_t base_pa);
364377
void ionic_q_post(struct ionic_queue *q, bool ring_doorbell, ionic_desc_cb cb,
365378
void *cb_arg);

drivers/net/ethernet/pensando/ionic/ionic_ethtool.c

Lines changed: 111 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,87 @@ static int ionic_set_coalesce(struct net_device *netdev,
511511
return 0;
512512
}
513513

514+
static int ionic_validate_cmb_config(struct ionic_lif *lif,
515+
struct ionic_queue_params *qparam)
516+
{
517+
int pages_have, pages_required = 0;
518+
unsigned long sz;
519+
520+
if (!lif->ionic->idev.cmb_inuse &&
521+
(qparam->cmb_tx || qparam->cmb_rx)) {
522+
netdev_info(lif->netdev, "CMB rings are not supported on this device\n");
523+
return -EOPNOTSUPP;
524+
}
525+
526+
if (qparam->cmb_tx) {
527+
if (!(lif->qtype_info[IONIC_QTYPE_TXQ].features & IONIC_QIDENT_F_CMB)) {
528+
netdev_info(lif->netdev,
529+
"CMB rings for tx-push are not supported on this device\n");
530+
return -EOPNOTSUPP;
531+
}
532+
533+
sz = sizeof(struct ionic_txq_desc) * qparam->ntxq_descs * qparam->nxqs;
534+
pages_required += ALIGN(sz, PAGE_SIZE) / PAGE_SIZE;
535+
}
536+
537+
if (qparam->cmb_rx) {
538+
if (!(lif->qtype_info[IONIC_QTYPE_RXQ].features & IONIC_QIDENT_F_CMB)) {
539+
netdev_info(lif->netdev,
540+
"CMB rings for rx-push are not supported on this device\n");
541+
return -EOPNOTSUPP;
542+
}
543+
544+
sz = sizeof(struct ionic_rxq_desc) * qparam->nrxq_descs * qparam->nxqs;
545+
pages_required += ALIGN(sz, PAGE_SIZE) / PAGE_SIZE;
546+
}
547+
548+
pages_have = lif->ionic->bars[IONIC_PCI_BAR_CMB].len / PAGE_SIZE;
549+
if (pages_required > pages_have) {
550+
netdev_info(lif->netdev,
551+
"Not enough CMB pages for number of queues and size of descriptor rings, need %d have %d",
552+
pages_required, pages_have);
553+
return -ENOMEM;
554+
}
555+
556+
return pages_required;
557+
}
558+
559+
static int ionic_cmb_rings_toggle(struct ionic_lif *lif, bool cmb_tx, bool cmb_rx)
560+
{
561+
struct ionic_queue_params qparam;
562+
int pages_used;
563+
564+
if (netif_running(lif->netdev)) {
565+
netdev_info(lif->netdev, "Please stop device to toggle CMB for tx/rx-push\n");
566+
return -EBUSY;
567+
}
568+
569+
ionic_init_queue_params(lif, &qparam);
570+
qparam.cmb_tx = cmb_tx;
571+
qparam.cmb_rx = cmb_rx;
572+
pages_used = ionic_validate_cmb_config(lif, &qparam);
573+
if (pages_used < 0)
574+
return pages_used;
575+
576+
if (cmb_tx)
577+
set_bit(IONIC_LIF_F_CMB_TX_RINGS, lif->state);
578+
else
579+
clear_bit(IONIC_LIF_F_CMB_TX_RINGS, lif->state);
580+
581+
if (cmb_rx)
582+
set_bit(IONIC_LIF_F_CMB_RX_RINGS, lif->state);
583+
else
584+
clear_bit(IONIC_LIF_F_CMB_RX_RINGS, lif->state);
585+
586+
if (cmb_tx || cmb_rx)
587+
netdev_info(lif->netdev, "Enabling CMB %s %s rings - %d pages\n",
588+
cmb_tx ? "TX" : "", cmb_rx ? "RX" : "", pages_used);
589+
else
590+
netdev_info(lif->netdev, "Disabling CMB rings\n");
591+
592+
return 0;
593+
}
594+
514595
static void ionic_get_ringparam(struct net_device *netdev,
515596
struct ethtool_ringparam *ring,
516597
struct kernel_ethtool_ringparam *kernel_ring,
@@ -522,6 +603,8 @@ static void ionic_get_ringparam(struct net_device *netdev,
522603
ring->tx_pending = lif->ntxq_descs;
523604
ring->rx_max_pending = IONIC_MAX_RX_DESC;
524605
ring->rx_pending = lif->nrxq_descs;
606+
kernel_ring->tx_push = test_bit(IONIC_LIF_F_CMB_TX_RINGS, lif->state);
607+
kernel_ring->rx_push = test_bit(IONIC_LIF_F_CMB_RX_RINGS, lif->state);
525608
}
526609

527610
static int ionic_set_ringparam(struct net_device *netdev,
@@ -551,9 +634,28 @@ static int ionic_set_ringparam(struct net_device *netdev,
551634

552635
/* if nothing to do return success */
553636
if (ring->tx_pending == lif->ntxq_descs &&
554-
ring->rx_pending == lif->nrxq_descs)
637+
ring->rx_pending == lif->nrxq_descs &&
638+
kernel_ring->tx_push == test_bit(IONIC_LIF_F_CMB_TX_RINGS, lif->state) &&
639+
kernel_ring->rx_push == test_bit(IONIC_LIF_F_CMB_RX_RINGS, lif->state))
555640
return 0;
556641

642+
qparam.ntxq_descs = ring->tx_pending;
643+
qparam.nrxq_descs = ring->rx_pending;
644+
qparam.cmb_tx = kernel_ring->tx_push;
645+
qparam.cmb_rx = kernel_ring->rx_push;
646+
647+
err = ionic_validate_cmb_config(lif, &qparam);
648+
if (err < 0)
649+
return err;
650+
651+
if (kernel_ring->tx_push != test_bit(IONIC_LIF_F_CMB_TX_RINGS, lif->state) ||
652+
kernel_ring->rx_push != test_bit(IONIC_LIF_F_CMB_RX_RINGS, lif->state)) {
653+
err = ionic_cmb_rings_toggle(lif, kernel_ring->tx_push,
654+
kernel_ring->rx_push);
655+
if (err < 0)
656+
return err;
657+
}
658+
557659
if (ring->tx_pending != lif->ntxq_descs)
558660
netdev_info(netdev, "Changing Tx ring size from %d to %d\n",
559661
lif->ntxq_descs, ring->tx_pending);
@@ -569,9 +671,6 @@ static int ionic_set_ringparam(struct net_device *netdev,
569671
return 0;
570672
}
571673

572-
qparam.ntxq_descs = ring->tx_pending;
573-
qparam.nrxq_descs = ring->rx_pending;
574-
575674
mutex_lock(&lif->queue_lock);
576675
err = ionic_reconfigure_queues(lif, &qparam);
577676
mutex_unlock(&lif->queue_lock);
@@ -638,7 +737,7 @@ static int ionic_set_channels(struct net_device *netdev,
638737
lif->nxqs, ch->combined_count);
639738

640739
qparam.nxqs = ch->combined_count;
641-
qparam.intr_split = 0;
740+
qparam.intr_split = false;
642741
} else {
643742
max_cnt /= 2;
644743
if (ch->rx_count > max_cnt)
@@ -654,9 +753,13 @@ static int ionic_set_channels(struct net_device *netdev,
654753
lif->nxqs, ch->rx_count);
655754

656755
qparam.nxqs = ch->rx_count;
657-
qparam.intr_split = 1;
756+
qparam.intr_split = true;
658757
}
659758

759+
err = ionic_validate_cmb_config(lif, &qparam);
760+
if (err < 0)
761+
return err;
762+
660763
/* if we're not running, just set the values and return */
661764
if (!netif_running(lif->netdev)) {
662765
lif->nxqs = qparam.nxqs;
@@ -965,6 +1068,8 @@ static const struct ethtool_ops ionic_ethtool_ops = {
9651068
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
9661069
ETHTOOL_COALESCE_USE_ADAPTIVE_RX |
9671070
ETHTOOL_COALESCE_USE_ADAPTIVE_TX,
1071+
.supported_ring_params = ETHTOOL_RING_USE_TX_PUSH |
1072+
ETHTOOL_RING_USE_RX_PUSH,
9681073
.get_drvinfo = ionic_get_drvinfo,
9691074
.get_regs_len = ionic_get_regs_len,
9701075
.get_regs = ionic_get_regs,

drivers/net/ethernet/pensando/ionic/ionic_if.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3073,9 +3073,10 @@ union ionic_adminq_comp {
30733073

30743074
#define IONIC_BARS_MAX 6
30753075
#define IONIC_PCI_BAR_DBELL 1
3076+
#define IONIC_PCI_BAR_CMB 2
30763077

3077-
/* BAR0 */
30783078
#define IONIC_BAR0_SIZE 0x8000
3079+
#define IONIC_BAR2_SIZE 0x800000
30793080

30803081
#define IONIC_BAR0_DEV_INFO_REGS_OFFSET 0x0000
30813082
#define IONIC_BAR0_DEV_CMD_REGS_OFFSET 0x0800

0 commit comments

Comments
 (0)