diff --git a/drivers/net/ethernet/pensando/ionic/ionic.h b/drivers/net/ethernet/pensando/ionic/ionic.h index 723b2ba6874e2806a4c604b6febf0bb3819048ee..affd7a88b58bef31a3e6332c17bd119df2ac82a0 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic.h +++ b/drivers/net/ethernet/pensando/ionic/ionic.h @@ -4,6 +4,8 @@ #ifndef _IONIC_H_ #define _IONIC_H_ +struct ionic_lif; + #include "ionic_if.h" #include "ionic_dev.h" #include "ionic_devlink.h" @@ -39,6 +41,7 @@ struct ionic { unsigned int nrxqs_per_lif; DECLARE_BITMAP(lifbits, IONIC_LIFS_MAX); unsigned int nintrs; + DECLARE_BITMAP(intrs, IONIC_INTR_CTRL_REGS_MAX); }; int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_wait); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus.h b/drivers/net/ethernet/pensando/ionic/ionic_bus.h index 3b1e2d0ebf8f1686e434920777a9503a363fbe1c..6b29e94f81d6897447b339f342050baf005d17c3 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_bus.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_bus.h @@ -9,5 +9,7 @@ int ionic_bus_alloc_irq_vectors(struct ionic *ionic, unsigned int nintrs); void ionic_bus_free_irq_vectors(struct ionic *ionic); int ionic_bus_register_driver(void); void ionic_bus_unregister_driver(void); +void __iomem *ionic_bus_map_dbpage(struct ionic *ionic, int page_num); +void ionic_bus_unmap_dbpage(struct ionic *ionic, void __iomem *page); #endif /* _IONIC_BUS_H_ */ diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c index f0e0daee45bcb0ccc3205bc7727d09a77f598757..4f08d915c3d2148235ccdf00d6d05926be5622ee 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c @@ -87,6 +87,18 @@ static void ionic_unmap_bars(struct ionic *ionic) } } +void __iomem *ionic_bus_map_dbpage(struct ionic *ionic, int page_num) +{ + return pci_iomap_range(ionic->pdev, + ionic->bars[IONIC_PCI_BAR_DBELL].res_index, + (u64)page_num << PAGE_SHIFT, PAGE_SIZE); +} + +void ionic_bus_unmap_dbpage(struct ionic *ionic, void __iomem *page) +{ + iounmap(page); +} + static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct device *dev = &pdev->dev; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.c b/drivers/net/ethernet/pensando/ionic/ionic_dev.c index 01e922fa9366c0faebea58eb4c3580458f932382..dbdde548848e6ee3dcc93b6df43a6d4468072bc4 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_dev.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.c @@ -9,6 +9,7 @@ #include <linux/etherdevice.h> #include "ionic.h" #include "ionic_dev.h" +#include "ionic_lif.h" void ionic_init_devinfo(struct ionic *ionic) { @@ -260,3 +261,8 @@ void ionic_dev_cmd_lif_reset(struct ionic_dev *idev, u16 lif_index) ionic_dev_cmd_go(idev, &cmd); } + +int ionic_db_page_num(struct ionic_lif *lif, int pid) +{ + return (lif->hw_index * lif->dbid_count) + pid; +} diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h index e8d4fc888333804b4243257150f0d7db63f70ca2..2252fa9ad0e37681d392ef8cf92a0289afe2cf64 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h @@ -126,8 +126,28 @@ struct ionic_dev { struct ionic_devinfo dev_info; }; +#define INTR_INDEX_NOT_ASSIGNED -1 +#define INTR_NAME_MAX_SZ 32 + +struct ionic_intr_info { + char name[INTR_NAME_MAX_SZ]; + unsigned int index; + unsigned int vector; + u64 rearm_count; + unsigned int cpu; + cpumask_t affinity_mask; +}; + struct ionic; +static inline void ionic_intr_init(struct ionic_dev *idev, + struct ionic_intr_info *intr, + unsigned long index) +{ + ionic_intr_clean(idev->intr_ctrl, index); + intr->index = index; +} + void ionic_init_devinfo(struct ionic *ionic); int ionic_dev_setup(struct ionic *ionic); void ionic_dev_teardown(struct ionic *ionic); @@ -155,4 +175,6 @@ void ionic_dev_cmd_lif_init(struct ionic_dev *idev, u16 lif_index, dma_addr_t addr); void ionic_dev_cmd_lif_reset(struct ionic_dev *idev, u16 lif_index); +int ionic_db_page_num(struct ionic_lif *lif, int pid); + #endif /* _IONIC_DEV_H_ */ diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index 5528043095d80458b4707dd1b2339badb82336ff..e9dc97b968b5d96a580d8f11a1b144fab27f4901 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -94,6 +94,12 @@ static void ionic_lif_free(struct ionic_lif *lif) lif->info = NULL; lif->info_pa = 0; + /* unmap doorbell page */ + ionic_bus_unmap_dbpage(lif->ionic, lif->kern_dbpage); + lif->kern_dbpage = NULL; + kfree(lif->dbid_inuse); + lif->dbid_inuse = NULL; + /* free netdev & lif */ ionic_debugfs_del_lif(lif); list_del(&lif->list); @@ -136,7 +142,9 @@ void ionic_lifs_deinit(struct ionic *ionic) static int ionic_lif_init(struct ionic_lif *lif) { struct ionic_dev *idev = &lif->ionic->idev; + struct device *dev = lif->ionic->dev; struct ionic_lif_init_comp comp; + int dbpage_num; int err; ionic_debugfs_add_lif(lif); @@ -151,9 +159,40 @@ static int ionic_lif_init(struct ionic_lif *lif) lif->hw_index = le16_to_cpu(comp.hw_index); + /* now that we have the hw_index we can figure out our doorbell page */ + lif->dbid_count = le32_to_cpu(lif->ionic->ident.dev.ndbpgs_per_lif); + if (!lif->dbid_count) { + dev_err(dev, "No doorbell pages, aborting\n"); + return -EINVAL; + } + + lif->dbid_inuse = bitmap_alloc(lif->dbid_count, GFP_KERNEL); + if (!lif->dbid_inuse) { + dev_err(dev, "Failed alloc doorbell id bitmap, aborting\n"); + return -ENOMEM; + } + + /* first doorbell id reserved for kernel (dbid aka pid == zero) */ + set_bit(0, lif->dbid_inuse); + lif->kern_pid = 0; + + dbpage_num = ionic_db_page_num(lif, lif->kern_pid); + lif->kern_dbpage = ionic_bus_map_dbpage(lif->ionic, dbpage_num); + if (!lif->kern_dbpage) { + dev_err(dev, "Cannot map dbpage, aborting\n"); + err = -ENOMEM; + goto err_out_free_dbid; + } + set_bit(IONIC_LIF_INITED, lif->state); return 0; + +err_out_free_dbid: + kfree(lif->dbid_inuse); + lif->dbid_inuse = NULL; + + return err; } int ionic_lifs_init(struct ionic *ionic) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h index fff4fc287b8915391d9ee065f54c44d5ebbcceb3..ec8d06ad4192e64871ac918291b4240b52386dc5 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h @@ -23,6 +23,8 @@ struct ionic_lif { bool registered; unsigned int index; unsigned int hw_index; + unsigned int kern_pid; + u64 __iomem *kern_dbpage; unsigned int neqs; unsigned int nxqs; @@ -30,6 +32,8 @@ struct ionic_lif { dma_addr_t info_pa; u32 info_sz; + unsigned long *dbid_inuse; + unsigned int dbid_count; struct dentry *dentry; u32 flags; }; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_regs.h b/drivers/net/ethernet/pensando/ionic/ionic_regs.h index 3523915061ed4a81556ac6ce3e2a11641ae11c43..03ee5a36472b63d8e58138e255697925a2a400c4 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_regs.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_regs.h @@ -22,6 +22,9 @@ struct ionic_intr { u32 rsvd[3]; }; +#define IONIC_INTR_CTRL_REGS_MAX 2048 +#define IONIC_INTR_CTRL_COAL_MAX 0x3F + /** enum ionic_intr_mask_vals - valid values for mask and mask_assert. * @IONIC_INTR_MASK_CLEAR: unmask interrupt. * @IONIC_INTR_MASK_SET: mask interrupt.