Skip to content

Commit

Permalink
ionic: Add hardware init and device commands
Browse files Browse the repository at this point in the history
The ionic device has a small set of PCI registers, including a
device control and data space, and a large set of message
commands.

Also adds new DEVLINK_INFO_VERSION_GENERIC tags for
ASIC_ID, ASIC_REV, and FW.

Signed-off-by: Shannon Nelson <snelson@pensando.io>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Shannon Nelson authored and David S. Miller committed Sep 5, 2019
1 parent df69ba4 commit fbfb803
Show file tree
Hide file tree
Showing 13 changed files with 3,481 additions and 2 deletions.
3 changes: 2 additions & 1 deletion drivers/net/ethernet/pensando/ionic/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@

obj-$(CONFIG_IONIC) := ionic.o

ionic-y := ionic_main.o ionic_bus_pci.o ionic_devlink.o
ionic-y := ionic_main.o ionic_bus_pci.o ionic_devlink.o ionic_dev.o \
ionic_debugfs.o
18 changes: 18 additions & 0 deletions drivers/net/ethernet/pensando/ionic/ionic.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef _IONIC_H_
#define _IONIC_H_

#include "ionic_if.h"
#include "ionic_dev.h"
#include "ionic_devlink.h"

#define IONIC_DRV_NAME "ionic"
Expand All @@ -19,9 +21,25 @@
#define IONIC_SUBDEV_ID_NAPLES_100_4 0x4001
#define IONIC_SUBDEV_ID_NAPLES_100_8 0x4002

#define DEVCMD_TIMEOUT 10

struct ionic {
struct pci_dev *pdev;
struct device *dev;
struct ionic_dev idev;
struct mutex dev_cmd_lock; /* lock for dev_cmd operations */
struct dentry *dentry;
struct ionic_dev_bar bars[IONIC_BARS_MAX];
unsigned int num_bars;
struct ionic_identity ident;
};

int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_wait);
int ionic_set_dma_mask(struct ionic *ionic);
int ionic_setup(struct ionic *ionic);

int ionic_identify(struct ionic *ionic);
int ionic_init(struct ionic *ionic);
int ionic_reset(struct ionic *ionic);

#endif /* _IONIC_H_ */
1 change: 1 addition & 0 deletions drivers/net/ethernet/pensando/ionic/ionic_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#ifndef _IONIC_BUS_H_
#define _IONIC_BUS_H_

const char *ionic_bus_info(struct ionic *ionic);
int ionic_bus_register_driver(void);
void ionic_bus_unregister_driver(void);

Expand Down
141 changes: 141 additions & 0 deletions drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "ionic.h"
#include "ionic_bus.h"
#include "ionic_debugfs.h"

/* Supported devices */
static const struct pci_device_id ionic_id_table[] = {
Expand All @@ -17,10 +18,68 @@ static const struct pci_device_id ionic_id_table[] = {
};
MODULE_DEVICE_TABLE(pci, ionic_id_table);

const char *ionic_bus_info(struct ionic *ionic)
{
return pci_name(ionic->pdev);
}

static int ionic_map_bars(struct ionic *ionic)
{
struct pci_dev *pdev = ionic->pdev;
struct device *dev = ionic->dev;
struct ionic_dev_bar *bars;
unsigned int i, j;

bars = ionic->bars;
ionic->num_bars = 0;

for (i = 0, j = 0; i < IONIC_BARS_MAX; i++) {
if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
continue;
bars[j].len = pci_resource_len(pdev, i);

/* only map the whole bar 0 */
if (j > 0) {
bars[j].vaddr = NULL;
} else {
bars[j].vaddr = pci_iomap(pdev, i, bars[j].len);
if (!bars[j].vaddr) {
dev_err(dev,
"Cannot memory-map BAR %d, aborting\n",
i);
return -ENODEV;
}
}

bars[j].bus_addr = pci_resource_start(pdev, i);
bars[j].res_index = i;
ionic->num_bars++;
j++;
}

return 0;
}

static void ionic_unmap_bars(struct ionic *ionic)
{
struct ionic_dev_bar *bars = ionic->bars;
unsigned int i;

for (i = 0; i < IONIC_BARS_MAX; i++) {
if (bars[i].vaddr) {
iounmap(bars[i].vaddr);
bars[i].bus_addr = 0;
bars[i].vaddr = NULL;
bars[i].len = 0;
}
}
}

static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct device *dev = &pdev->dev;
struct ionic *ionic;
int err;

ionic = ionic_devlink_alloc(dev);
if (!ionic)
Expand All @@ -29,14 +88,96 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ionic->pdev = pdev;
ionic->dev = dev;
pci_set_drvdata(pdev, ionic);
mutex_init(&ionic->dev_cmd_lock);

/* Query system for DMA addressing limitation for the device. */
err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(IONIC_ADDR_LEN));
if (err) {
dev_err(dev, "Unable to obtain 64-bit DMA for consistent allocations, aborting. err=%d\n",
err);
goto err_out_clear_drvdata;
}

ionic_debugfs_add_dev(ionic);

/* Setup PCI device */
err = pci_enable_device_mem(pdev);
if (err) {
dev_err(dev, "Cannot enable PCI device: %d, aborting\n", err);
goto err_out_debugfs_del_dev;
}

err = pci_request_regions(pdev, IONIC_DRV_NAME);
if (err) {
dev_err(dev, "Cannot request PCI regions: %d, aborting\n", err);
goto err_out_pci_disable_device;
}

pci_set_master(pdev);

err = ionic_map_bars(ionic);
if (err)
goto err_out_pci_clear_master;

/* Configure the device */
err = ionic_setup(ionic);
if (err) {
dev_err(dev, "Cannot setup device: %d, aborting\n", err);
goto err_out_unmap_bars;
}

err = ionic_identify(ionic);
if (err) {
dev_err(dev, "Cannot identify device: %d, aborting\n", err);
goto err_out_teardown;
}

err = ionic_init(ionic);
if (err) {
dev_err(dev, "Cannot init device: %d, aborting\n", err);
goto err_out_teardown;
}

err = ionic_devlink_register(ionic);
if (err)
dev_err(dev, "Cannot register devlink: %d\n", err);

return 0;

err_out_teardown:
ionic_dev_teardown(ionic);
err_out_unmap_bars:
ionic_unmap_bars(ionic);
pci_release_regions(pdev);
err_out_pci_clear_master:
pci_clear_master(pdev);
err_out_pci_disable_device:
pci_disable_device(pdev);
err_out_debugfs_del_dev:
ionic_debugfs_del_dev(ionic);
err_out_clear_drvdata:
mutex_destroy(&ionic->dev_cmd_lock);
ionic_devlink_free(ionic);

return err;
}

static void ionic_remove(struct pci_dev *pdev)
{
struct ionic *ionic = pci_get_drvdata(pdev);

if (!ionic)
return;

ionic_devlink_unregister(ionic);
ionic_reset(ionic);
ionic_dev_teardown(ionic);
ionic_unmap_bars(ionic);
pci_release_regions(pdev);
pci_clear_master(pdev);
pci_disable_device(pdev);
ionic_debugfs_del_dev(ionic);
mutex_destroy(&ionic->dev_cmd_lock);
ionic_devlink_free(ionic);
}

Expand Down
61 changes: 61 additions & 0 deletions drivers/net/ethernet/pensando/ionic/ionic_debugfs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2017 - 2019 Pensando Systems, Inc */

#include <linux/netdevice.h>

#include "ionic.h"
#include "ionic_bus.h"
#include "ionic_debugfs.h"

#ifdef CONFIG_DEBUG_FS

static struct dentry *ionic_dir;

void ionic_debugfs_create(void)
{
ionic_dir = debugfs_create_dir(IONIC_DRV_NAME, NULL);
}

void ionic_debugfs_destroy(void)
{
debugfs_remove_recursive(ionic_dir);
}

void ionic_debugfs_add_dev(struct ionic *ionic)
{
ionic->dentry = debugfs_create_dir(ionic_bus_info(ionic), ionic_dir);
}

void ionic_debugfs_del_dev(struct ionic *ionic)
{
debugfs_remove_recursive(ionic->dentry);
ionic->dentry = NULL;
}

static int identity_show(struct seq_file *seq, void *v)
{
struct ionic *ionic = seq->private;
struct ionic_identity *ident;

ident = &ionic->ident;

seq_printf(seq, "nlifs: %d\n", ident->dev.nlifs);
seq_printf(seq, "nintrs: %d\n", ident->dev.nintrs);
seq_printf(seq, "ndbpgs_per_lif: %d\n", ident->dev.ndbpgs_per_lif);
seq_printf(seq, "intr_coal_mult: %d\n", ident->dev.intr_coal_mult);
seq_printf(seq, "intr_coal_div: %d\n", ident->dev.intr_coal_div);

seq_printf(seq, "max_ucast_filters: %d\n", ident->lif.eth.max_ucast_filters);
seq_printf(seq, "max_mcast_filters: %d\n", ident->lif.eth.max_mcast_filters);

return 0;
}
DEFINE_SHOW_ATTRIBUTE(identity);

void ionic_debugfs_add_ident(struct ionic *ionic)
{
debugfs_create_file("identity", 0400, ionic->dentry,
ionic, &identity_fops) ? 0 : -EOPNOTSUPP;
}

#endif
24 changes: 24 additions & 0 deletions drivers/net/ethernet/pensando/ionic/ionic_debugfs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2017 - 2019 Pensando Systems, Inc */

#ifndef _IONIC_DEBUGFS_H_
#define _IONIC_DEBUGFS_H_

#include <linux/debugfs.h>

#ifdef CONFIG_DEBUG_FS

void ionic_debugfs_create(void);
void ionic_debugfs_destroy(void);
void ionic_debugfs_add_dev(struct ionic *ionic);
void ionic_debugfs_del_dev(struct ionic *ionic);
void ionic_debugfs_add_ident(struct ionic *ionic);
#else
static inline void ionic_debugfs_create(void) { }
static inline void ionic_debugfs_destroy(void) { }
static inline void ionic_debugfs_add_dev(struct ionic *ionic) { }
static inline void ionic_debugfs_del_dev(struct ionic *ionic) { }
static inline void ionic_debugfs_add_ident(struct ionic *ionic) { }
#endif

#endif /* _IONIC_DEBUGFS_H_ */
Loading

0 comments on commit fbfb803

Please sign in to comment.