[broadcom]: update saibcm-modules to sdk 6.5.14

This commit is contained in:
Shu0T1an ChenG 2019-04-15 18:05:51 -07:00 committed by Guohan Lu
parent f2b8d6d797
commit aa8fcd9924
10 changed files with 637 additions and 173 deletions

View File

@ -148,6 +148,28 @@ typedef struct ibde_s {
*/
int (*get_cmic_ver)(int d, uint32 *ver);
/*
* Probe available devices.
* Return value :
* 0: success to probe available devices
* -1: error happens during probe
*/
int (*probe)(void);
/*
* I2C operations on the Device, assuming it is connected by I2C to the CPU.
*/
/* Read from the internal device Address space using I2C */
int (*i2c_device_read)(
int dev, /* The device ID to access */
uint32 addr, /* The address to access in the internal device address space */
uint32 *value);/* the value to be read. */
/* Write to the internal device Address space using I2C */
int (*i2c_device_write)(
int dev, /* The device ID to access */
uint32 addr, /* The address to access in the internal device address space */
uint32 value); /* the value to be written. */
} ibde_t;

View File

@ -46,6 +46,7 @@
#define KCOM_M_HW_INIT 4 /* H/W initialized */
#define KCOM_M_ETH_HW_CONFIG 5 /* ETH HW config*/
#define KCOM_M_DETACH 6 /* Detach kernel module */
#define KCOM_M_REPROBE 7 /* Reprobe device */
#define KCOM_M_NETIF_CREATE 11 /* Create network interface */
#define KCOM_M_NETIF_DESTROY 12 /* Destroy network interface */
#define KCOM_M_NETIF_LIST 13 /* Get list of network interface IDs */
@ -59,7 +60,7 @@
#define KCOM_M_DBGPKT_GET 42 /* Get debug packet function info */
#define KCOM_M_WB_CLEANUP 51 /* Clean up for warmbooting */
#define KCOM_VERSION 9 /* Protocol version */
#define KCOM_VERSION 10 /* Protocol version */
/*
* Message status codes
@ -305,7 +306,7 @@ typedef struct kcom_eth_hw_config_s {
uint8 chan;
uint32 flags;
uint32 value;
} kcom_eth_hw_config_t;
} kcom_eth_hw_config_t;
/*
* Message types
@ -379,6 +380,14 @@ typedef struct kcom_msg_detach_s {
uint32 flags;
} kcom_msg_detach_t;
/*
* Reprobe switch device.
*/
typedef struct kcom_msg_reprobe_s {
kcom_msg_hdr_t hdr;
uint32 flags;
} kcom_msg_reprobe_t;
/*
* Enable/Disable debugging packet function.
*/
@ -498,6 +507,7 @@ typedef union kcom_msg_s {
kcom_msg_hw_init_t hw_init;
kcom_msg_eth_hw_config_t eth_hw_config;
kcom_msg_detach_t detach;
kcom_msg_reprobe_t reprobe;
kcom_msg_netif_create_t netif_create;
kcom_msg_netif_destroy_t netif_destroy;
kcom_msg_netif_list_t netif_list;

View File

@ -1238,6 +1238,15 @@
#define BCM56980_DEVICE_ID 0xb980
#define BCM56980_A0_REV_ID 1
#define BCM56980_B0_REV_ID 0x11
#define BCM56981_DEVICE_ID 0xb981
#define BCM56981_A0_REV_ID 1
#define BCM56982_DEVICE_ID 0xb982
#define BCM56982_A0_REV_ID 1
#define BCM56983_DEVICE_ID 0xb983
#define BCM56983_A0_REV_ID 1
#define BCM56984_DEVICE_ID 0xb984
#define BCM56984_A0_REV_ID 1
#define BCM56968_DEVICE_ID 0xb968
#define BCM56968_A0_REV_ID 1
@ -1289,15 +1298,20 @@
#define BCM56670_DEVICE_ID 0xb670
#define BCM56670_A0_REV_ID 1
#define BCM56670_B0_REV_ID 0x11
#define BCM56671_DEVICE_ID 0xb671
#define BCM56671_A0_REV_ID 1
#define BCM56671_B0_REV_ID 0x11
#define BCM56672_DEVICE_ID 0xb672
#define BCM56672_A0_REV_ID 1
#define BCM56672_B0_REV_ID 0x11
#define BCM56675_DEVICE_ID 0xb675
#define BCM56675_A0_REV_ID 1
#define BCM56675_B0_REV_ID 0x11
#define BCM56565_DEVICE_ID 0xb565
#define BCM56565_A0_REV_ID 1
@ -1317,12 +1331,19 @@
#define BCM56760_DEVICE_ID 0xb760
#define BCM56760_A0_REV_ID 1
#define BCM56760_A1_REV_ID 2
#define BCM56760_B0_REV_ID 0x11
#define BCM56761_DEVICE_ID 0xb761
#define BCM56761_A0_REV_ID 1
#define BCM56761_B0_REV_ID 0x11
#define BCM56761_DEVICE_ID 0xb761
#define BCM56761_A0_REV_ID 1
#define BCM56761_A1_REV_ID 2
#define BCM56761_B0_REV_ID 0x11
#define BCM56761_B1_REV_ID 0x12
#define BCM56762_DEVICE_ID 0xb762
#define BCM56762_A0_REV_ID 1
#define BCM56762_B0_REV_ID 0x11
@ -1347,6 +1368,11 @@
#define BCM56068_A0_REV_ID 1
#define BCM56068_B0_REV_ID 0x11
#define BCM56068_DEVICE_ID 0xb068
#define BCM56068_A0_REV_ID 1
#define BCM56068_B0_REV_ID 0x11
#define BCM56068_B1_REV_ID 0x12
#define BCM56069_DEVICE_ID 0xb069
#define BCM56069_A0_REV_ID 1
#define BCM56069_B0_REV_ID 0x11
@ -1400,6 +1426,42 @@
#define BCM56873_DEVICE_ID 0xb873
#define BCM56873_A0_REV_ID 1
#define BCM56370_DEVICE_ID 0xb370
#define BCM56370_A0_REV_ID 1
#define BCM56371_DEVICE_ID 0xb371
#define BCM56371_A0_REV_ID 1
#define BCM56372_DEVICE_ID 0xb372
#define BCM56372_A0_REV_ID 1
#define BCM56374_DEVICE_ID 0xb374
#define BCM56374_A0_REV_ID 1
#define BCM56375_DEVICE_ID 0xb375
#define BCM56375_A0_REV_ID 1
#define BCM56376_DEVICE_ID 0xb376
#define BCM56376_A0_REV_ID 1
#define BCM56377_DEVICE_ID 0xb377
#define BCM56377_A0_REV_ID 1
#define BCM56577_DEVICE_ID 0xb577
#define BCM56577_A0_REV_ID 1
#define BCM56578_DEVICE_ID 0xb578
#define BCM56578_A0_REV_ID 1
#define BCM56579_DEVICE_ID 0xb579
#define BCM56579_A0_REV_ID 1
#define BCM56770_DEVICE_ID 0xb770
#define BCM56770_A0_REV_ID 1
#define BCM56771_DEVICE_ID 0xb771
#define BCM56771_A0_REV_ID 1
#define BCM53540_DEVICE_ID 0x8540
#define BCM53540_A0_REV_ID 1
#define BCM53547_DEVICE_ID 0x8547
@ -1718,6 +1780,7 @@
#define DNXC_B0_REV_ID 0x0011
#define BCM88790_DEVICE_ID 0x8790
#define BCM88790_A0_REV_ID DNXC_A0_REV_ID
#define BCM88790_B0_REV_ID DNXC_B0_REV_ID
#define BCM88791_DEVICE_ID 0x8791
#define BCM88792_DEVICE_ID 0x8792
#define BCM88793_DEVICE_ID 0x8793

View File

@ -86,15 +86,19 @@ endif
endif
ifdef DPP_CHIPS
CFLAGS += -DDUNE_BCM -D__DUNE_GTO_BCM_CPU__ -D__DUNE_LINUX_BCM_CPU_PCIE__ -D__DUNE_LINUX_BCM_CPU_PCP_DMA__
CFLAGS += -DDUNE_BCM -D__DUNE_LINUX_BCM_CPU_PCP_DMA__
CFGFLAGS += -DSOC_CM_FUNCTION
endif
ifdef DFE_CHIPS
CFLAGS += -DDUNE_BCM -D__DUNE_GTO_BCM_CPU__ -D__DUNE_LINUX_BCM_CPU_PCIE__
CFLAGS += -DDUNE_BCM
CFGFLAGS += -DSOC_CM_FUNCTION
endif
ifdef SAND_CHIPS
CFLAGS += -D__DUNE_GTO_BCM_CPU__ -D__DUNE_LINUX_BCM_CPU_PCIE__
endif
ifdef SHADOW_PLX
CFLAGS += -DBCM_PLX9656_LOCAL_BUS -DBDE_LINUX_NON_INTERRUPTIBLE -DSHADOW_SVK
endif

View File

@ -94,6 +94,8 @@ LKM_MOD_PARAM(nodevices, "i", int, 0);
MODULE_PARM_DESC(nodevices,
"Ignore all recognized devices (default no)");
int msixcnt = 1;
/*
* This usually is defined at /usr/include/linux/pci_ids.h
* But this ID is newer.
@ -366,6 +368,12 @@ static int robo_switch = 0;
#define VALID_DEVICE(_n) ((_n >= 0) && (_n < _ndevices))
#if defined(IPROC_CMICD) && defined(CONFIG_OF)
#define ICFG_CHIP_ID_REG 0x10236000
#define IHOST_CMICX_MAX_INTRS 128
static uint32 iproc_cmicx_irqs[IHOST_CMICX_MAX_INTRS];
#endif
/* CPU MMIO area used with CPU cards provided on demo boards */
#if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)) && (defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_GTO_BCM_CPU__))
static void *cpu_address = NULL;
@ -696,9 +704,9 @@ iproc_cmicd_get_irqres(ibde_dev_t bde_dev, struct resource *res_irq)
#include <linux/platform_device.h>
#include <linux/of.h>
extern void iproc_platform_driver_register(struct platform_driver *drv);
extern int iproc_platform_driver_register(struct platform_driver *drv);
extern void iproc_platform_driver_unregister(struct platform_driver *drv);
extern void iproc_platform_device_register(struct platform_device *drv);
extern int iproc_platform_device_register(struct platform_device *drv);
extern void iproc_platform_device_unregister(struct platform_device *drv);
extern struct resource *
@ -711,13 +719,14 @@ iproc_platform_get_resource(struct platform_device *dev, unsigned int type,
#define IPROC_CMICD_INT 194
#define IPROC_CMICD_COMPATIBLE "brcm,iproc-cmicd"
#define IPROC_CMICX_COMPATIBLE "brcm,iproc-cmicx"
static int
iproc_cmicd_probe(struct platform_device *pldev)
{
bde_ctrl_t *ctrl;
uint32 size, dev_rev_id;
struct resource *memres, *irqres;
struct resource *memres, *irqres;
#ifdef CONFIG_OF
if (debug >= 1) {
gprintk("iproc_cmicd_probe %s\n", pldev->dev.of_node ? "with device node":"");
@ -725,7 +734,7 @@ iproc_cmicd_probe(struct platform_device *pldev)
#endif
memres = iproc_platform_get_resource(pldev, IORESOURCE_MEM, 0);
if (memres == NULL) {
gprintk("Unable to retrieve iProc CMIC resources");
gprintk("Unable to retrieve iProc CMIC resources");
return -1;
}
size = memres->end - memres->start + 1;
@ -739,32 +748,62 @@ iproc_cmicd_probe(struct platform_device *pldev)
/* Map CMIC block in the AXI memory space into CPU address space */
ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(memres->start, size);
if (!ctrl->bde_dev.base_address) {
gprintk("Error mapping iProc CMIC registers");
gprintk("Error mapping iProc CMIC registers");
return -1;
}
ctrl->phys_address = memres->start;
/* Read switch device ID from CMIC */
dev_rev_id = *((uint32_t*)(ctrl->bde_dev.base_address + 0x10224));
#if defined(BCM_CMICM_SUPPORT) && defined(BE_HOST)
ctrl->bde_dev.device = ( (((dev_rev_id >> 16) & 0xff) << 8) |
((dev_rev_id >> 24) & 0xff));
ctrl->bde_dev.rev = (dev_rev_id >> 8) & 0xff ;
#else
ctrl->bde_dev.device = dev_rev_id & 0xffff;
ctrl->bde_dev.rev = (dev_rev_id >> 16) & 0xff;
#ifdef CONFIG_OF
if (of_find_compatible_node(NULL, NULL, IPROC_CMICX_COMPATIBLE)) {
uint32 *icfg_chip_id;
icfg_chip_id = (uint32 *)IOREMAP(ICFG_CHIP_ID_REG, 2 * sizeof(uint32));
if (icfg_chip_id == NULL) {
gprintk("Error mapping ICFG_CHIP_ID_REG\n");
return -1;
}
ctrl->bde_dev.device = readl(icfg_chip_id) & 0xffff;
ctrl->bde_dev.rev = readl(icfg_chip_id+1) & 0xff;
iounmap(icfg_chip_id);
} else
#endif
{
/* Read switch device ID from CMIC */
dev_rev_id = *((uint32 *)(ctrl->bde_dev.base_address + 0x10224));
#if defined(BCM_CMICM_SUPPORT) && defined(BE_HOST)
ctrl->bde_dev.device = ( (((dev_rev_id >> 16) & 0xff) << 8) |
((dev_rev_id >> 24) & 0xff));
ctrl->bde_dev.rev = (dev_rev_id >> 8) & 0xff ;
#else
ctrl->bde_dev.device = dev_rev_id & 0xffff;
ctrl->bde_dev.rev = (dev_rev_id >> 16) & 0xff;
#endif
}
#ifdef CONFIG_OF
if (!pldev->dev.of_node)
#endif
{
/* Assign locally if not available from device node */
iproc_cmicd_get_irqres(ctrl->bde_dev, &pldev->resource[0]);
iproc_cmicd_get_irqres(ctrl->bde_dev, &pldev->resource[0]);
}
irqres = iproc_platform_get_resource(pldev, IORESOURCE_IRQ, 0);
ctrl->iLine = irqres->start;
#ifdef CONFIG_OF
if (of_find_compatible_node(NULL, NULL, IPROC_CMICX_COMPATIBLE)) {
int i;
for (i = 0; i < IHOST_CMICX_MAX_INTRS; i++) {
irqres = iproc_platform_get_resource(pldev, IORESOURCE_IRQ, i);
iproc_cmicx_irqs[i] = irqres->start;
if (debug >= 1) {
gprintk("iproc_cmicx_irqs[%d] = %d\n", i, iproc_cmicx_irqs[i]);
}
}
ctrl->iLine = iproc_cmicx_irqs[0];
} else
#endif
{
irqres = iproc_platform_get_resource(pldev, IORESOURCE_IRQ, 0);
ctrl->iLine = irqres->start;
}
ctrl->isr = NULL;
ctrl ->isr_data = NULL;
@ -785,14 +824,15 @@ iproc_cmicd_remove(struct platform_device *pldev)
}
#ifdef CONFIG_OF
static const struct of_device_id iproc_cmicd_of_match[] = {
{ .compatible = "brcm,iproc-cmicd" },
{ .compatible = IPROC_CMICD_COMPATIBLE },
{ .compatible = IPROC_CMICX_COMPATIBLE },
{},
};
MODULE_DEVICE_TABLE(of, iproc_cmicd_of_match);
#endif
static char iproc_cmicd_string[] = "bcmiproc-cmicd";
static struct platform_driver iproc_cmicd_driver =
static struct platform_driver iproc_cmicd_driver =
{
.probe = iproc_cmicd_probe,
.remove = iproc_cmicd_remove,
@ -995,10 +1035,10 @@ iproc_cmicd_get_memregion(struct resource *res_mem)
iounmap(erom_base);
if (debug >= 1) {
gprintk("CMICD info by %s: cmicd_mem.start=%x, cmicd_mem.end=%x\n",
gprintk("CMICD info by %s: cmicd_mem.start=%lx, cmicd_mem.end=%lx\n",
found_cmicd_dev ? "EROM" : "Default",
iproc_cmicd_resources[IPROC_CMICD_RES_MEM].start,
iproc_cmicd_resources[IPROC_CMICD_RES_MEM].end);
(unsigned long)iproc_cmicd_resources[IPROC_CMICD_RES_MEM].start,
(unsigned long)iproc_cmicd_resources[IPROC_CMICD_RES_MEM].end);
}
}
#endif /* IPROC_CMICD */
@ -1382,6 +1422,7 @@ static const struct pci_device_id _id_table[] = {
{ BROADCOM_VENDOR_ID, BCM56672_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56675_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56568_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56670_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56760_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56761_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56762_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
@ -1546,8 +1587,24 @@ static const struct pci_device_id _id_table[] = {
{ BROADCOM_VENDOR_ID, BCM56832_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56836_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56870_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56980_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56370_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56371_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56372_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56374_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56375_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56376_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56377_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56577_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56578_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56579_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56873_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56770_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56771_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56980_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56981_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56982_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56983_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM56984_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM53540_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM53547_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ BROADCOM_VENDOR_ID, BCM53548_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
@ -1981,6 +2038,7 @@ _pci_msix_table_size(struct pci_dev *dev)
if (nr_entries < 0) {
nr_entries = 0;
}
pci_disable_msix(dev);
kfree(entries);
}
}
@ -1996,45 +2054,56 @@ _pci_msix_table_size(struct pci_dev *dev)
static int
_msi_connect(bde_ctrl_t *ctrl)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84))
int ret;
if (ctrl->use_msi == PCI_USE_INT_MSIX) {
int i;
ret = _pci_msix_table_size(ctrl->pci_device);
ret = _pci_msix_table_size(ctrl->pci_device);
if (ret == 0) {
/* MSI-X failed */
gprintk("MSI-X not supported.\n");
goto er_intx;
}
ctrl->entries = kcalloc(ret, sizeof(struct msix_entry)*ret, GFP_KERNEL);
ctrl->entries = kcalloc(ret, sizeof(struct msix_entry), GFP_KERNEL);
if (!ctrl->entries) {
goto er_intx;
}
/* We need only that much interrupt vecotrs */
ctrl->msix_cnt = ret/4;
/* Only one vector is mapped by default */
/* May be more in future, can be controlled using module param */
ctrl->msix_cnt = msixcnt;
if (unlikely(debug > 1))
gprintk("MSIX Table size = %d\n", ctrl->msix_cnt);
for (i = 0; i < ctrl->msix_cnt; i++)
ctrl->entries[i].entry = i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0)
ret = pci_enable_msix_range(ctrl->pci_device,
ctrl->entries, ctrl->msix_cnt, ctrl->msix_cnt);
#else
ret = pci_enable_msix(ctrl->pci_device,
ctrl->entries, ctrl->msix_cnt);
#endif
if (ret > 0) {
/* Not enough vectors available , Retry MSI-X */
gprintk("Retrying with MSI-X interrupts = %d\n", ret);
ctrl->msix_cnt = ret;
msixcnt = ret;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0)
ret = pci_enable_msix_range(ctrl->pci_device,
ctrl->entries, ctrl->msix_cnt, ctrl->msix_cnt);
#else
ret = pci_enable_msix(ctrl->pci_device,
ctrl->entries, ctrl->msix_cnt);
#endif
if (ret != 0)
goto er_intx_free;
} else if (ret < 0) {
/* Error */
goto er_intx_free;
} else {
gprintk("Enabled MSI-X interrupts = %d\n", ctrl->msix_cnt);
gprintk("Enabled MSI-X interrupts = %d\n", ctrl->msix_cnt);
return 0;
}
}
#endif
@ -2049,7 +2118,7 @@ _msi_connect(bde_ctrl_t *ctrl)
}
} else {
/* failed */
gprintk("Not MSI/MSIC interrupt.\n");
gprintk("Not MSI/MSIX interrupt.\n");
goto er_intx;
}
return 0;
@ -2068,9 +2137,12 @@ _msi_disconnect(bde_ctrl_t *ctrl)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84))
if (ctrl->use_msi == PCI_USE_INT_MSIX) {
pci_disable_msix(ctrl->pci_device);
kfree(ctrl->entries);
ctrl->msix_cnt = 0;
if (ctrl->msix_cnt) {
pci_disable_msix(ctrl->pci_device);
kfree(ctrl->entries);
ctrl->entries = NULL;
ctrl->msix_cnt = 0;
}
}
#endif
if (ctrl->use_msi == PCI_USE_INT_MSI) {
@ -2085,16 +2157,30 @@ _msi_disconnect(bde_ctrl_t *ctrl)
static void
config_pci_intr_type(bde_ctrl_t *ctrl)
config_pci_intr_type(struct pci_dev *dev, bde_ctrl_t *ctrl, int iproc)
{
#ifdef CONFIG_PCI_MSI
int ret;
shbde_iproc_config_t icfg;
/* Each device follows global policy by default */
ctrl->use_msi = use_msi;
if (unlikely(debug > 1))
gprintk("%s: msi = %d\n", __func__, ctrl->use_msi);
/* Check IPROC version for MSIX support */
if (iproc && ctrl->bde_dev.base_address1 &&
(ctrl->use_msi == PCI_USE_INT_MSIX)) {
if (shbde_pci_iproc_version_get(&ctrl->shbde, dev, &icfg.iproc_ver,
&icfg.cmic_ver, &icfg.cmic_rev)) {
if (icfg.iproc_ver < 0xe) {
gprintk("%s: MSI-X not supported, using MSI.\n", __func__);
ctrl->use_msi = PCI_USE_INT_MSI;
}
}
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84))
if (ctrl->use_msi == PCI_USE_INT_MSIX) {
/* check for support MSIX vector */
@ -2108,10 +2194,10 @@ config_pci_intr_type(bde_ctrl_t *ctrl)
if (ctrl->use_msi == PCI_USE_INT_MSI) {
/* check for support MSI vector */
ret = pci_enable_msi(ctrl->pci_device);
ret = pci_enable_msi(ctrl->pci_device);
if (ret < 0) {
ctrl->use_msi = PCI_USE_INT_INTX;
gprintk("%s: Failed to enable MSI\n", __func__);
gprintk("%s: Failed to enable MSI, using INTx.\n", __func__);
} else {
pci_disable_msi(ctrl->pci_device);
}
@ -2268,7 +2354,7 @@ _pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
return 0;
}
if (_switch_ndevices >= LINUX_BDE_MAX_SWITCH_DEVICES) {
return 0;;
return 0;
}
if (rescan) {
@ -2550,22 +2636,8 @@ _pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
}
}
/* Each device follows global policy by default */
ctrl->use_msi = use_msi;
/* Check is MSI is properly supported in kernel for this device */
if (ctrl->use_msi) {
if (pci_enable_msi(ctrl->pci_device) == 0) {
/* Release MSI resources until interrupt_connect is called */
pci_disable_msi(ctrl->pci_device);
} else {
gprintk("Could not enable MSI interrupts\n");
ctrl->use_msi = 0;
}
}
/* configure interrupt type */
config_pci_intr_type(ctrl);
config_pci_intr_type(dev, ctrl, iproc);
/* Configure iProc PCI-AXI bridge */
if (iproc && ctrl->bde_dev.base_address1) {
@ -2580,7 +2652,7 @@ _pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
&icfg->cmic_ver, &icfg->cmic_rev);
shbde_iproc_config_init(icfg, ctrl->bde_dev.device, ctrl->bde_dev.rev);
if (debug >=2) {
if (debug >= 2) {
gprintk("iproc version = %x dma_hi_bits = %x\n", icfg->iproc_ver, icfg->dma_hi_bits);
}
icfg->use_msi = ctrl->use_msi;
@ -2734,22 +2806,22 @@ _pci_remove(struct pci_dev* dev)
if (ctrl->use_msi >= PCI_USE_INT_MSIX) {
int i;
for (i = 0; i < ctrl->msix_cnt; i++)
free_irq(ctrl->entries[i].vector, ctrl->pci_device);
free_irq(ctrl->entries[i].vector, ctrl);
}
else
#endif
{
free_irq(ctrl->iLine, ctrl);
free_irq(ctrl->iLine, ctrl);
}
}
#ifdef CONFIG_PCI_MSI
_msi_disconnect(ctrl);
#endif
ctrl->isr = NULL;
ctrl->isr_data = NULL;
ctrl->isr2 = NULL;
ctrl->isr2_data = NULL;
}
ctrl->isr = NULL;
ctrl->isr_data = NULL;
ctrl->isr2 = NULL;
ctrl->isr2_data = NULL;
}
static struct pci_driver _device_driver = {
probe: _pci_probe,
@ -3641,8 +3713,12 @@ _gmac_dev_create(void)
static int
_init(void)
{
#ifdef IPROC_CMICD
#ifdef CONFIG_OF
if (of_find_compatible_node(NULL, NULL, IPROC_CMICX_COMPATIBLE)) {
iproc_platform_driver_register(&iproc_cmicd_driver);
} else
#endif
if (iproc_has_cmicd()) {
iproc_cmicd_get_memregion(&iproc_cmicd_resources[IPROC_CMICD_RES_MEM]);
iproc_platform_driver_register(&iproc_cmicd_driver);
@ -3651,8 +3727,8 @@ _init(void)
#endif
{
/* Register platform device if no device node in dtb */
iproc_platform_device_register(&iproc_cmicd_pdev);
}
iproc_platform_device_register(&iproc_cmicd_pdev);
}
}
#endif /* IPROC_CMICD */
@ -3662,7 +3738,7 @@ _init(void)
/* Register our goodies */
_device_driver.name = LINUX_KERNEL_BDE_NAME;
#if defined(BCM_ROBO_SUPPORT)
#if defined(BCM_ROBO_SUPPORT)
#if defined(IPROC_CMICD)
if (_gmac_dev_create()) {
return -ENODEV;
@ -3771,6 +3847,11 @@ _cleanup(void)
_dma_cleanup();
#ifdef IPROC_CMICD
#ifdef CONFIG_OF
if (of_find_compatible_node(NULL, NULL, IPROC_CMICX_COMPATIBLE)) {
iproc_platform_driver_unregister(&iproc_cmicd_driver);
} else
#endif
if (iproc_has_cmicd()) {
#ifdef CONFIG_OF
if (!of_find_compatible_node(NULL, NULL, IPROC_CMICD_COMPATIBLE))
@ -4251,14 +4332,18 @@ _interrupt_connect(int d,
if (ctrl->use_msi == PCI_USE_INT_MSIX) {
int i;
for (i = 0; i < ctrl->msix_cnt; i++) {
ret = request_irq(ctrl->entries[i].vector, _isr,
irq_flags, LINUX_KERNEL_BDE_NAME, ctrl);
if (unlikely(debug >= 1)) {
gprintk("%s(%d):device# = %d, irq = %d\n",
__func__, __LINE__, d, ctrl->entries[i].vector);
}
ret = request_irq(ctrl->entries[i].vector, _isr, 0,
LINUX_KERNEL_BDE_NAME, ctrl);
if (ret < 0)
break;
}
if (ret < 0) {
while (i >= 0)
free_irq(ctrl->entries[i--].vector, ctrl->pci_device);
free_irq(ctrl->entries[i--].vector, ctrl);
goto err_disable_msi;
}
@ -4266,15 +4351,39 @@ _interrupt_connect(int d,
else
#endif
{
ret = request_irq(ctrl->iLine, _isr, irq_flags,
#if defined(IPROC_CMICD) && defined(CONFIG_OF)
if (of_find_compatible_node(NULL, NULL, IPROC_CMICX_COMPATIBLE)) {
int i, j;
for (i = 0; i < IHOST_CMICX_MAX_INTRS; i++) {
if (unlikely(debug >= 1))
gprintk("%s(%d):device# = %d, request_irq(%d)\n",
__func__, __LINE__, d, iproc_cmicx_irqs[i]);
ret = request_irq(iproc_cmicx_irqs[i], _isr,
irq_flags, LINUX_KERNEL_BDE_NAME, ctrl);
if (ret < 0) {
gprintk("request_irq(%d) failed(%d)\n", iproc_cmicx_irqs[i], ret);
break;
}
}
if (ret < 0) {
for (j = 0; j < i; j++) {
free_irq(iproc_cmicx_irqs[j], ctrl);
}
goto err_disable_msi;
}
} else
#endif
{
ret = request_irq(ctrl->iLine, _isr, irq_flags,
LINUX_KERNEL_BDE_NAME, ctrl);
if (ret < 0)
goto err_disable_msi;
if (ret < 0)
goto err_disable_msi;
if (unlikely(debug >= 1))
gprintk("%s(%d):device# = %d, irq_flags = %lu, irq = %d\n",
if (unlikely(debug >= 1))
gprintk("%s(%d):device# = %d, irq_flags = %lu, irq = %d\n",
__func__, __LINE__, d,
irq_flags, ctrl->pci_device ? ctrl->pci_device->irq : ctrl->iLine);
}
}
}
return 0;
@ -4292,7 +4401,7 @@ msi_exit:
ctrl->isr2_data = NULL;
return -1;
}
}
static int
_interrupt_disconnect(int d)
@ -4353,13 +4462,30 @@ _interrupt_disconnect(int d)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84))
if (ctrl->use_msi >= PCI_USE_INT_MSIX) {
int i;
for (i = 0; i < ctrl->msix_cnt; i++)
free_irq(ctrl->entries[i].vector, ctrl->pci_device);
for (i = 0; i < ctrl->msix_cnt; i++) {
if (unlikely(debug > 1)) {
gprintk("%s(%d):device# = %d, irq = %d\n",
__func__, __LINE__, d, ctrl->entries[i].vector);
}
free_irq(ctrl->entries[i].vector, ctrl);
}
}
else
#endif
#if defined(IPROC_CMICD) && defined(CONFIG_OF)
if (of_find_compatible_node(NULL, NULL, IPROC_CMICX_COMPATIBLE)) {
int i;
for (i = 0; i < IHOST_CMICX_MAX_INTRS; i++) {
if (unlikely(debug > 1)) {
gprintk("%s(%d):device# = %d, free_irq(%d)\n",
__func__, __LINE__, d, iproc_cmicx_irqs[i]);
}
free_irq(iproc_cmicx_irqs[i], ctrl);
}
} else
#endif
{
free_irq(ctrl->iLine, ctrl);
free_irq(ctrl->iLine, ctrl);
}
#ifdef CONFIG_PCI_MSI
if (ctrl->use_msi >= PCI_USE_INT_MSI) {

View File

@ -30,6 +30,9 @@
#include "linux-user-bde.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0)
#include <linux/uaccess.h>
#endif
#ifdef KEYSTONE
#include <shared/et/bcmdevs.h>
#endif
@ -75,21 +78,56 @@ MODULE_LICENSE("GPL");
/* CMICX defines */
#define INTC_INTR_REG_NUM (8)
#define INTC_INTR_ENABLE_REG0 (0x180130f0)
#define INTC_INTR_STATUS_REG0 (0x18013190)
#define INTC_INTR_RAW_STATUS_REG0 (0x18013140)
/*
TODO:HX5
The INTR base address values are changed for HX5,
hence making new #defines so runtime decisions can
be made.
*/
#define INTC_INTR_ENABLE_REG0 (0x180130f0)
#define INTC_INTR_STATUS_REG0 (0x18013190)
#define INTC_INTR_RAW_STATUS_REG0 (0x18013140)
#define INTC_INTR_ENABLE_BASE (INTC_INTR_ENABLE_REG0)
#define INTC_INTR_STATUS_BASE (INTC_INTR_STATUS_REG0)
#define INTC_INTR_RAW_STATUS_BASE (INTC_INTR_RAW_STATUS_REG0)
#define INTC_PDMA_INTR_REG_IND 4
#define HX5_INTC_INTR_ENABLE_REG0 (0x102310f0)
#define HX5_INTC_INTR_STATUS_REG0 (0x10231190)
#define HX5_INTC_INTR_RAW_STATUS_REG0 (0x10231140)
#define HX5_INTC_INTR_ENABLE_BASE (HX5_INTC_INTR_ENABLE_REG0)
#define HX5_INTC_INTR_STATUS_BASE (HX5_INTC_INTR_STATUS_REG0)
#define HX5_INTC_INTR_RAW_STATUS_BASE (HX5_INTC_INTR_RAW_STATUS_REG0)
#define IOREMAP(addr, size) ioremap_nocache(addr, size)
#define HX5_IHOST_GICD_ISENABLERN_0 (0x10781100)
#define HX5_IHOST_GICD_ISENABLERN_1 (0x10781104)
#define HX5_IHOST_GICD_ICENABLERN_1 (0x10781184)
#define HX5_IHOST_GICD_ICENABLERN_8 (0x107811a0)
/* Offset between ISENABLERN_1 and ICENABLERN_1 in 4-bytes */
#define HX5_IHOST_IRQ_MASK_OFFSET 0x20
#define HX5_IHOST_INTR_MAP_NUM (HX5_IHOST_GICD_ICENABLERN_8 - HX5_IHOST_GICD_ISENABLERN_0)
#define HX5_IHOST_INTR_STATUS_MAP_NUM (INTC_INTR_REG_NUM * (sizeof(uint32)))
#define IRQ_BIT(intr) (intr % (sizeof(uint32)*8))
#define IRQ_MASK_INDEX(intr) (intr / (sizeof(uint32)*8))
#define HX5_CHIP_INTR_LOW_PRIORITY 119
#define INTR_LOW_PRIORITY_BITPOS (1 << IRQ_BIT(HX5_CHIP_INTR_LOW_PRIORITY))
#define INTC_LOW_PRIORITY_INTR_REG_IND IRQ_MASK_INDEX(HX5_CHIP_INTR_LOW_PRIORITY)
#define INTC_PDMA_INTR_REG_IND 4
#define READ_INTC_INTR(d, reg, v) \
(v = user_bde->iproc_read(d, reg))
(v = user_bde->iproc_read(d, reg))
#define WRITE_INTC_INTR(d, reg, v) \
(user_bde->iproc_write(d, reg, v))
#define IHOST_READ_INTR(d, reg, v) \
(v = readl((reg)))
#define IHOST_WRITE_INTR(d, reg, v) \
(writel((v), (reg)))
/* Allow override of default CMICm CMC */
#ifndef BDE_CMICM_PCIE_CMC
#define BDE_CMICM_PCIE_CMC 0
@ -103,6 +141,9 @@ MODULE_LICENSE("GPL");
/* Defines used to distinguish CMICe from CMICm */
#define CMICE_DEV_REV_ID (0x178 / sizeof(uint32))
static uint32 *ihost_intr_status_base = NULL;
static uint32 *ihost_intr_enable_base = NULL;
static ibde_t *user_bde = NULL;
typedef void (*isr_f)(void *);
@ -225,27 +266,68 @@ _cmicx_interrupt(bde_ctrl_t *ctrl)
int d, ind;
uint32 stat, iena, mask, fmask;
bde_inst_resource_t *res;
uint32 intc_intr_status_base = 0, intc_intr_enable_base = 0;
d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t));
res = &_bde_inst_resource[ctrl->inst];
lkbde_irq_mask_get(d, &mask, &fmask);
if ((ctrl->dev_type & BDE_SWITCH_DEV_TYPE) &&
((user_bde->get_dev(d)->device == BCM56370_DEVICE_ID) ||
(user_bde->get_dev(d)->device == BCM56371_DEVICE_ID) ||
(user_bde->get_dev(d)->device == BCM56372_DEVICE_ID) ||
(user_bde->get_dev(d)->device == BCM56374_DEVICE_ID) ||
(user_bde->get_dev(d)->device == BCM56375_DEVICE_ID) ||
(user_bde->get_dev(d)->device == BCM56376_DEVICE_ID) ||
(user_bde->get_dev(d)->device == BCM56377_DEVICE_ID) ||
(user_bde->get_dev(d)->device == BCM56577_DEVICE_ID) ||
(user_bde->get_dev(d)->device == BCM56578_DEVICE_ID) ||
(user_bde->get_dev(d)->device == BCM56579_DEVICE_ID))) {
intc_intr_status_base = HX5_INTC_INTR_STATUS_BASE;
intc_intr_enable_base = HX5_INTC_INTR_ENABLE_BASE;
} else {
intc_intr_status_base = INTC_INTR_STATUS_BASE;
intc_intr_enable_base = INTC_INTR_ENABLE_BASE;
}
if (fmask) {
READ_INTC_INTR(d, INTC_INTR_STATUS_BASE + 4 * INTC_PDMA_INTR_REG_IND, stat);
READ_INTC_INTR(d, INTC_INTR_ENABLE_BASE + 4 * INTC_PDMA_INTR_REG_IND, iena);
if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
IHOST_READ_INTR(d, ihost_intr_status_base + INTC_PDMA_INTR_REG_IND, stat);
IHOST_READ_INTR(d, ihost_intr_enable_base + INTC_PDMA_INTR_REG_IND, iena);
} else {
READ_INTC_INTR(d, intc_intr_status_base + 4 * INTC_PDMA_INTR_REG_IND, stat);
READ_INTC_INTR(d, intc_intr_enable_base + 4 * INTC_PDMA_INTR_REG_IND, iena);
}
if (stat & iena) {
WRITE_INTC_INTR(d, INTC_INTR_ENABLE_BASE + 4 * INTC_PDMA_INTR_REG_IND, 0);
if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
IHOST_WRITE_INTR(d, ihost_intr_enable_base + INTC_PDMA_INTR_REG_IND +
HX5_IHOST_IRQ_MASK_OFFSET, ~0);
} else {
WRITE_INTC_INTR(d, intc_intr_enable_base + 4 * INTC_PDMA_INTR_REG_IND, 0);
}
for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) {
if (ind == INTC_PDMA_INTR_REG_IND) {
continue;
}
READ_INTC_INTR(d, INTC_INTR_STATUS_BASE + 4 * ind, stat);
READ_INTC_INTR(d, INTC_INTR_ENABLE_BASE + 4 * ind, iena);
if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
if (ind < INTC_LOW_PRIORITY_INTR_REG_IND) {
continue;
}
IHOST_READ_INTR(d, ihost_intr_status_base + ind, stat);
IHOST_READ_INTR(d, ihost_intr_enable_base + ind, iena);
if (ind == INTC_LOW_PRIORITY_INTR_REG_IND) {
stat &= INTR_LOW_PRIORITY_BITPOS;
}
} else {
READ_INTC_INTR(d, intc_intr_status_base + 4 * ind, stat);
READ_INTC_INTR(d, intc_intr_enable_base + 4 * ind, iena);
}
if (stat & iena) {
break;
}
}
if (ind >= INTC_INTR_REG_NUM) {
return;
}
@ -260,7 +342,20 @@ _cmicx_interrupt(bde_ctrl_t *ctrl)
if (fmask && ind == INTC_PDMA_INTR_REG_IND) {
continue;
}
WRITE_INTC_INTR(d, INTC_INTR_ENABLE_BASE + 4 * ind, 0);
if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
if (ind < INTC_LOW_PRIORITY_INTR_REG_IND) {
continue;
}
if (ind == INTC_LOW_PRIORITY_INTR_REG_IND) {
IHOST_WRITE_INTR(d, ihost_intr_enable_base + INTC_LOW_PRIORITY_INTR_REG_IND +
HX5_IHOST_IRQ_MASK_OFFSET, INTR_LOW_PRIORITY_BITPOS);
} else {
IHOST_WRITE_INTR(d, ihost_intr_enable_base + ind +
HX5_IHOST_IRQ_MASK_OFFSET, ~0);
}
} else {
WRITE_INTC_INTR(d, intc_intr_enable_base + 4*ind, 0);
}
}
/* Notify */
@ -750,6 +845,12 @@ _devices_init(int d)
uint32 ver;
uint16 device_id_mask = 0xFFF0;
uint16 device_id;
int state = 0;
(void)lkbde_dev_state_get(d, &state);
if (state == BDE_DEV_STATE_REMOVED) {
return;
}
ctrl = &_devices[d];
/* Initialize our control info */
@ -849,6 +950,31 @@ _devices_init(int d)
case BCM88952_DEVICE_ID:
ctrl->isr = (isr_f)_cmicd_cmc0_interrupt;
break;
case BCM88790_DEVICE_ID:
ctrl->isr = (isr_f)_cmicx_interrupt;
break;
case BCM56370_DEVICE_ID:
case BCM56371_DEVICE_ID:
case BCM56372_DEVICE_ID:
case BCM56374_DEVICE_ID:
case BCM56375_DEVICE_ID:
case BCM56376_DEVICE_ID:
case BCM56377_DEVICE_ID:
case BCM56577_DEVICE_ID:
case BCM56578_DEVICE_ID:
case BCM56579_DEVICE_ID:
ctrl->isr = (isr_f)_cmicx_interrupt;
if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
if (!ihost_intr_enable_base) {
ihost_intr_enable_base = (uint32_t *)IOREMAP(HX5_IHOST_GICD_ISENABLERN_1,
HX5_IHOST_INTR_MAP_NUM);
}
if (!ihost_intr_status_base) {
ihost_intr_status_base = (uint32_t *)IOREMAP(HX5_INTC_INTR_RAW_STATUS_REG0,
HX5_IHOST_INTR_STATUS_MAP_NUM);
}
}
break;
default:
/* Get CMIC version */
if (user_bde->get_cmic_ver(d, &ver) != 0) {
@ -876,7 +1002,7 @@ _devices_init(int d)
}
break;
}
/*All Ramon devices from 0x8790 to 0x879F*/
/* All Ramon devices from 0x8790 to 0x879F */
if ((user_bde->get_dev(d)->device & BCM88790_DEVICE_ID) == BCM88790_DEVICE_ID) {
ctrl->isr = (isr_f)_cmicx_interrupt;
}
@ -928,10 +1054,14 @@ _init(void)
init_waitqueue_head(&res->intr_wq);
atomic_set(&res->intr, 0);
ihost_intr_enable_base = NULL;
ihost_intr_status_base = NULL;
for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) {
res->inst_id |= (1 << i);
_devices_init(i);
}
return 0;
}
@ -961,6 +1091,16 @@ _cleanup(void)
linux_bde_destroy(user_bde);
user_bde = NULL;
}
if (ihost_intr_enable_base) {
iounmap(ihost_intr_enable_base);
ihost_intr_enable_base = NULL;
}
if (ihost_intr_status_base) {
iounmap(ihost_intr_status_base);
ihost_intr_status_base = NULL;
}
return 0;
}
@ -1088,6 +1228,7 @@ static int
_device_reprobe(void)
{
int i;
for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) {
if (_devices[i].devid == 0) {
_devices_init(i);
@ -1167,7 +1308,8 @@ _ioctl(unsigned int cmd, unsigned long arg)
ssize_t size;
const ibde_dev_t *bde_dev;
int inst_id;
bde_inst_resource_t *res;
bde_inst_resource_t *res;
uint32_t *mapaddr;
if (copy_from_user(&io, (void *)arg, sizeof(io))) {
return -EFAULT;
@ -1396,9 +1538,22 @@ _ioctl(unsigned int cmd, unsigned long arg)
}
break;
case LUBDE_IPROC_READ_REG:
io.d1 = user_bde->iproc_read(io.dev, io.d0);
if (io.d1 == -1) {
io.rc = LUBDE_FAIL;
if (!VALID_DEVICE(io.dev)) {
return -EINVAL;
}
if (_devices[io.dev].dev_type & BDE_AXI_DEV_TYPE) {
mapaddr = IOREMAP(io.d0, sizeof(uint32_t));
if (mapaddr == NULL) {
io.rc = LUBDE_FAIL;
return -1;
}
io.d1 = readl(mapaddr);
iounmap(mapaddr);
} else {
io.d1 = user_bde->iproc_read(io.dev, io.d0);
if (io.d1 == -1) {
io.rc = LUBDE_FAIL;
}
}
break;
case LUBDE_IPROC_WRITE_REG:
@ -1412,6 +1567,9 @@ _ioctl(unsigned int cmd, unsigned long arg)
case LUBDE_GET_DEVICE_STATE:
io.rc = lkbde_dev_state_get(io.dev, &io.d0);
break;
case LUBDE_REPROBE:
io.rc = _device_reprobe();
break;
default:
gprintk("Error: Invalid ioctl (%08x)\n", cmd);
io.rc = LUBDE_FAIL;

View File

@ -81,6 +81,7 @@ typedef struct {
#define LUBDE_IPROC_WRITE_REG _IO(LUBDE_MAGIC, 28)
#define LUBDE_ATTACH_INSTANCE _IO(LUBDE_MAGIC, 29)
#define LUBDE_GET_DEVICE_STATE _IO(LUBDE_MAGIC, 30)
#define LUBDE_REPROBE _IO(LUBDE_MAGIC, 31)
#define LUBDE_SEM_OP_CREATE 1
#define LUBDE_SEM_OP_DESTROY 2
@ -93,9 +94,10 @@ typedef struct {
/*
* Version history
* 1:add LUBDE_GET_DEVICE_STATE to support PCI hot plug
* 1: add LUBDE_GET_DEVICE_STATE to support PCI hot plug
* 2: add LUBDE_REPROBE to support reprobe available devices
*/
#define KBDE_VERSION 1
#define KBDE_VERSION 2
/* This is the signal that will be used

View File

@ -40,6 +40,8 @@
#define BAR0_PAXB_OARR_2_UPPER 0x2d64
#define BAR0_DMU_PCU_PCIE_SLAVE_RESET_MODE 0x7024
#define PAXB_0_FUNC0_IMAP1_3 0x2d88
/* Force byte pointer for offset adjustments */
#define ROFFS(_ptr, _offset) ((unsigned char*)(_ptr) + (_offset))
@ -47,6 +49,7 @@
#define PAXB_CONFIG_IND_ADDRr_PROTOCOL_LAYERf_MASK 0x3
#define PAXB_CONFIG_IND_ADDRr_ADDRESSf_SHFT 0
#define PAXB_CONFIG_IND_ADDRr_ADDRESSf_MASK 0x7ff
#define PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT 20
/* Register value set/get by field */
#define REG_FIELD_SET(_r, _f, _r_val, _f_val) \
@ -273,17 +276,25 @@ shbde_iproc_paxb_init(shbde_hal_t *shbde, void *iproc_regs,
reg = ROFFS(iproc_regs, BAR0_PAXB_PCIE_EP_AXI_CONFIG);
iproc32_write(shbde, reg, 0x0);
if(icfg->cmic_ver < 4) { /* Non-CMICX */
reg = ROFFS(iproc_regs, BAR0_PAXB_OARR_2);
iproc32_write(shbde, reg, 0x1);
reg = ROFFS(iproc_regs, BAR0_PAXB_OARR_2_UPPER);
iproc32_write(shbde, reg, icfg->dma_hi_bits);
/* Configure MSI interrupt page */
if (icfg->use_msi) {
reg = ROFFS(iproc_regs, BAR0_PAXB_OARR_FUNC0_MSI_PAGE);
data = iproc32_read(shbde, reg);
iproc32_write(shbde, reg, data | 0x1);
reg = ROFFS(iproc_regs, BAR0_PAXB_OARR_2);
iproc32_write(shbde, reg, 0x1);
reg = ROFFS(iproc_regs, BAR0_PAXB_OARR_2_UPPER);
iproc32_write(shbde, reg, icfg->dma_hi_bits);
/* Configure MSI interrupt page */
if (icfg->use_msi) {
reg = ROFFS(iproc_regs, BAR0_PAXB_OARR_FUNC0_MSI_PAGE);
data = iproc32_read(shbde, reg);
iproc32_write(shbde, reg, data | 0x1);
}
}
/* Configure MSIX interrupt page, only need for iproc ver == 0x10 */
if ((icfg->use_msi == 2) && (icfg->iproc_ver == 0x10)) {
unsigned int mask = (0x1 << PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT) - 1;
reg = ROFFS(iproc_regs, PAXB_0_FUNC0_IMAP1_3);
data = iproc32_read(shbde, reg);
data &= mask;
data |= 0x410 << PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT;
iproc32_write(shbde, reg, data);
}
return pci_num;
}
@ -315,7 +326,8 @@ shbde_iproc_pci_read(shbde_hal_t *shbde, void *iproc_regs,
/* Sub-window size is 0x1000 (4K) */
subwin_base = (addr & ~0xfff);
if((icfg->cmic_ver >= 4) && (subwin_base == 0x18013000)) {
if((icfg->cmic_ver >= 4) &&
((subwin_base == 0x10231000) || (subwin_base == 0x18013000))) {
/* Route the INTC block access through IMAP0_6 */
reg = ROFFS(iproc_regs, 0x6000 + (addr & 0xfff));
} else {
@ -361,7 +373,8 @@ shbde_iproc_pci_write(shbde_hal_t *shbde, void *iproc_regs,
/* Sub-window size is 0x1000 (4K) */
subwin_base = (addr & ~0xfff);
if((icfg->cmic_ver >= 4) && (subwin_base == 0x18013000)) {
if((icfg->cmic_ver >= 4) &&
((subwin_base == 0x10231000) || (subwin_base == 0x18013000))) {
/* Route the INTC block access through IMAP0_6 */
reg = ROFFS(iproc_regs, 0x6000 + (addr & 0xfff));
} else {

View File

@ -301,6 +301,13 @@ static int use_proxy = 0;
#endif
/* Compatibility */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0))
#define NETDEV_UPDATE_TRANS_START_TIME(dev) dev->trans_start = jiffies
#else
#define NETDEV_UPDATE_TRANS_START_TIME(dev) netif_trans_update(dev)
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
#define skb_copy_to_linear_data(_skb, _pkt, _len) \
eth_copy_and_sum(_skb, _pkt, _len, 0)
@ -505,6 +512,7 @@ typedef struct bkn_switch_info_s {
uint32_t rcpu_sig; /* RCPU signature */
uint64_t halt_addr[NUM_DMA_CHAN]; /* DMA halt address */
uint32_t cdma_channels; /* Active channels for Continuous DMA mode */
uint32_t poll_channels; /* Channels for polling */
uint32_t inst_id; /* Instance id of this device */
int evt_idx; /* Event queue index for this device*/
int basedev_suspended; /* Base device suspended */
@ -536,7 +544,6 @@ typedef struct bkn_switch_info_s {
int dirty; /* Index of next Rx DCB to complete */
int running; /* Rx DMA is active */
int api_active; /* BCM Rx API is active */
int api_wait; /* Wait BCM Rx API resources */
int chain_complete; /* All DCBs in chain processed */
int sync_err; /* Chain done with incomplete DCBs (debug) */
int sync_retry; /* Total retry times for sync error (debug) */
@ -684,7 +691,7 @@ typedef struct bkn_pkt_dnx_s {
#endif /* defined(CMIC_SOFT_BYTE_SWAP) */
#define MEMORY_BARRIER mb()
#define MEMORY_BARRIER smp_mb()
/* Default random MAC address has Broadcom OUI with local admin bit set */
static u8 bkn_dev_mac[6] = { 0x02, 0x10, 0x18, 0x00, 0x00, 0x00 };
@ -1753,7 +1760,6 @@ bkn_clean_rx_dcbs(bkn_switch_info_t *sinfo, int chan)
}
sinfo->rx[chan].running = 0;
sinfo->rx[chan].api_active = 0;
sinfo->rx[chan].api_wait = 0;
DBG_DCB_RX(("Cleaned Rx%d DCBs (%d %d).\n",
chan, sinfo->rx[chan].cur, sinfo->rx[chan].dirty));
}
@ -1959,7 +1965,7 @@ bkn_api_rx_restart(bkn_switch_info_t *sinfo, int chan)
sinfo->rx[chan].chain_complete = 0;
start_dma = 1;
if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) &&
sinfo->rx[chan].api_wait) {
sinfo->rx[chan].api_active) {
/* HW is running already, so we just move to the next chain */
start_dma = 0;
}
@ -1972,7 +1978,6 @@ bkn_api_rx_restart(bkn_switch_info_t *sinfo, int chan)
dev_dma_chan_clear(sinfo, XGS_DMA_RX_CHAN + chan);
dev_irq_mask_enable(sinfo, XGS_DMA_RX_CHAN + chan, 1);
dev_dma_chan_start(sinfo, XGS_DMA_RX_CHAN + chan, dcb_chain->dcb_dma);
sinfo->rx[chan].api_wait = 1;
}
list_del(&dcb_chain->list);
@ -1992,10 +1997,6 @@ bkn_api_rx_chain_done(bkn_switch_info_t *sinfo, int chan)
sinfo->rx[chan].api_dcb_chain = NULL;
}
bkn_api_rx_restart(sinfo, chan);
if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) &&
sinfo->rx[chan].api_dcb_chain == NULL) {
sinfo->rx[chan].api_active = 0;
}
}
static int
@ -2053,6 +2054,7 @@ bkn_api_rx_copy_from_skb(bkn_switch_info_t *sinfo,
}
}
dcb[sinfo->dcb_wsize-1] = dcb_stat | SOC_DCB_KNET_DONE;
MEMORY_BARRIER;
dcb_chain->dcb_cur++;
@ -2062,6 +2064,7 @@ bkn_api_rx_copy_from_skb(bkn_switch_info_t *sinfo,
(sinfo->cmic_type != 'x' && dcb[1] & (1 << 18))) {
/* Get the next chain if reload done */
dcb[sinfo->dcb_wsize-1] |= 1 << 31 | SOC_DCB_KNET_DONE;
MEMORY_BARRIER;
bkn_api_rx_chain_done(sinfo, chan);
dcb_chain = sinfo->rx[chan].api_dcb_chain;
if (dcb_chain == NULL) {
@ -2090,7 +2093,7 @@ bkn_rx_refill(bkn_switch_info_t *sinfo, int chan)
struct sk_buff *skb;
bkn_desc_info_t *desc;
uint32_t *dcb;
uint32_t encap_size = sinfo->cmic_type == 'x' ? RCPU_HDR_SIZE : RCPU_RX_ENCAP_SIZE;
uint32_t resv_size = sinfo->cmic_type == 'x' ? RCPU_HDR_SIZE : RCPU_RX_ENCAP_SIZE;
int prev;
if (sinfo->rx[chan].use_rx_skb == 0) {
@ -2107,11 +2110,11 @@ bkn_rx_refill(bkn_switch_info_t *sinfo, int chan)
while (sinfo->rx[chan].free < MAX_RX_DCBS) {
desc = &sinfo->rx[chan].desc[sinfo->rx[chan].cur];
if (desc->skb == NULL) {
skb = dev_alloc_skb(rx_buffer_size + encap_size);
skb = dev_alloc_skb(rx_buffer_size + RCPU_RX_ENCAP_SIZE);
if (skb == NULL) {
break;
}
skb_reserve(skb, encap_size);
skb_reserve(skb, resv_size);
desc->skb = skb;
} else {
DBG_DCB_RX(("Refill Rx%d SKB in DCB %d recycled.\n",
@ -3198,11 +3201,7 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget)
case KCOM_DEST_T_API:
DBG_FLTR(("Send to Rx API\n"));
sinfo->rx[chan].pkts_f_api++;
if (bkn_api_rx_copy_from_skb(sinfo, chan, desc) < 0) {
/* Suspend SKB Rx due to no API resources */
sinfo->rx[chan].api_wait = 1;
return dcbs_done;
}
bkn_api_rx_copy_from_skb(sinfo, chan, desc);
break;
case KCOM_DEST_T_NETIF:
priv = bkn_netif_lookup(sinfo, filter->kf.dest_id);
@ -3408,10 +3407,6 @@ bkn_rx_desc_done(bkn_switch_info_t *sinfo, int chan)
static void
bkn_rx_chain_done(bkn_switch_info_t *sinfo, int chan)
{
if (sinfo->rx[chan].use_rx_skb && sinfo->rx[chan].api_wait) {
return;
}
DBG_IRQ(("Rx%d chain done\n", chan));
if (sinfo->rx[chan].chain_complete == 0) {
@ -3809,6 +3804,7 @@ static int
xgs_do_dma(bkn_switch_info_t *sinfo, int budget)
{
int rx_dcbs_done = 0, tx_dcbs_done = 0;
int chan_done, budget_chans = 0;
uint32_t dma_stat;
int chan;
@ -3817,7 +3813,28 @@ xgs_do_dma(bkn_switch_info_t *sinfo, int budget)
for (chan = 0; chan < sinfo->rx_chans; chan++) {
if (dma_stat & DS_DESC_DONE_TST(XGS_DMA_RX_CHAN + chan)) {
xgs_dma_desc_clear(sinfo, XGS_DMA_RX_CHAN + chan);
rx_dcbs_done += bkn_do_rx(sinfo, chan, budget - rx_dcbs_done);
sinfo->poll_channels |= 1 << chan;
}
}
if (!sinfo->poll_channels) {
sinfo->poll_channels = (uint32_t)(1 << sinfo->rx_chans) - 1;
budget_chans = budget / sinfo->rx_chans;
} else {
for (chan = 0; chan < sinfo->rx_chans; chan++) {
if (1 << chan & sinfo->poll_channels) {
budget_chans++;
}
}
budget_chans = budget / budget_chans;
}
for (chan = 0; chan < sinfo->rx_chans; chan++) {
if (1 << chan & sinfo->poll_channels) {
chan_done = bkn_do_rx(sinfo, chan, budget_chans);
rx_dcbs_done += chan_done;
if (chan_done < budget_chans) {
sinfo->poll_channels &= ~(1 << chan);
}
bkn_rx_desc_done(sinfo, chan);
}
@ -3833,13 +3850,14 @@ xgs_do_dma(bkn_switch_info_t *sinfo, int budget)
bkn_tx_chain_done(sinfo, tx_dcbs_done);
}
return rx_dcbs_done;
return sinfo->poll_channels ? budget : rx_dcbs_done;
}
static int
xgsm_do_dma(bkn_switch_info_t *sinfo, int budget)
{
int rx_dcbs_done = 0, tx_dcbs_done = 0;
int chan_done, budget_chans = 0;
uint32_t dma_stat, irq_stat = 0;
int chan;
@ -3854,7 +3872,28 @@ xgsm_do_dma(bkn_switch_info_t *sinfo, int budget)
if (dma_stat & (0x10 << (XGS_DMA_RX_CHAN + chan)) ||
irq_stat & (0x08000000 << (XGS_DMA_RX_CHAN + chan))) {
xgsm_dma_desc_clear(sinfo, XGS_DMA_RX_CHAN + chan);
rx_dcbs_done += bkn_do_rx(sinfo, chan, budget - rx_dcbs_done);
sinfo->poll_channels |= 1 << chan;
}
}
if (!sinfo->poll_channels) {
sinfo->poll_channels = (uint32_t)(1 << sinfo->rx_chans) - 1;
budget_chans = budget / sinfo->rx_chans;
} else {
for (chan = 0; chan < sinfo->rx_chans; chan++) {
if (1 << chan & sinfo->poll_channels) {
budget_chans++;
}
}
budget_chans = budget / budget_chans;
}
for (chan = 0; chan < sinfo->rx_chans; chan++) {
if (1 << chan & sinfo->poll_channels) {
chan_done = bkn_do_rx(sinfo, chan, budget_chans);
rx_dcbs_done += chan_done;
if (chan_done < budget_chans) {
sinfo->poll_channels &= ~(1 << chan);
}
bkn_rx_desc_done(sinfo, chan);
}
@ -3879,22 +3918,45 @@ xgsm_do_dma(bkn_switch_info_t *sinfo, int budget)
bkn_tx_chain_done(sinfo, tx_dcbs_done);
}
return rx_dcbs_done;
return sinfo->poll_channels ? budget : rx_dcbs_done;
}
static int
xgsx_do_dma(bkn_switch_info_t *sinfo, int budget)
{
int rx_dcbs_done = 0, tx_dcbs_done = 0;
int chan_done, budget_chans = 0;
uint32_t irq_stat;
int chan;
DEV_READ32(sinfo, CMICX_IRQ_STATr, &irq_stat);
for (chan = 0; chan < sinfo->rx_chans; chan++) {
if ((irq_stat & CMICX_DS_CMC_CTRLD_INT(XGS_DMA_RX_CHAN + chan)) ||
(irq_stat & CMICX_DS_CMC_DESC_DONE(XGS_DMA_RX_CHAN + chan))) {
xgsx_dma_desc_clear(sinfo, XGS_DMA_RX_CHAN + chan);
rx_dcbs_done += bkn_do_rx(sinfo, chan, budget - rx_dcbs_done);
sinfo->poll_channels |= 1 << chan;
}
}
if (!sinfo->poll_channels) {
sinfo->poll_channels = (uint32_t)(1 << sinfo->rx_chans) - 1;
budget_chans = budget / sinfo->rx_chans;
} else {
for (chan = 0; chan < sinfo->rx_chans; chan++) {
if (1 << chan & sinfo->poll_channels) {
budget_chans++;
}
}
budget_chans = budget / budget_chans;
}
for (chan = 0; chan < sinfo->rx_chans; chan++) {
if (1 << chan & sinfo->poll_channels) {
chan_done = bkn_do_rx(sinfo, chan, budget_chans);
rx_dcbs_done += chan_done;
if (chan_done < budget_chans) {
sinfo->poll_channels &= ~(1 << chan);
}
bkn_rx_desc_done(sinfo, chan);
}
@ -3919,7 +3981,7 @@ xgsx_do_dma(bkn_switch_info_t *sinfo, int budget)
bkn_tx_chain_done(sinfo, tx_dcbs_done);
}
return rx_dcbs_done;
return sinfo->poll_channels ? budget : rx_dcbs_done;
}
static int
@ -4400,10 +4462,12 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb_any(skb);
skb = new_skb;
pktdata = skb->data;
rcpulen = 0;
} else {
/* Add tag to RCPU header space */
DBG_SKB(("Expand into unused RCPU header\n"));
pktdata = &skb->data[rcpulen - 4];
rcpulen -= 4;
pktdata = &skb->data[rcpulen];
for (idx = 0; idx < 12; idx++) {
pktdata[idx] = pktdata[idx + 4];
}
@ -4418,7 +4482,7 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev)
} else {
if (sinfo->cmic_type == 'x' && priv->port >= 0) {
if (skb_header_cloned(skb) || skb_headroom(skb) < hdrlen + 4 ||
((unsigned long)skb->data % 4)) {
(sinfo->dcb_type == 36 && (unsigned long)skb->data % 4)) {
/* Current SKB cannot be modified */
DBG_SKB(("Realloc Tx SKB\n"));
new_skb = dev_alloc_skb(pktlen + hdrlen + 4);
@ -4502,6 +4566,8 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&sinfo->lock, flags);
return 0;
}
/* skb_padto may update the skb->data pointer */
pktdata = &skb->data[rcpulen];
DBG_SKB(("Packet padded to %d bytes\n", pktlen));
}
@ -4696,7 +4762,6 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev)
* bit0 -bit15 of dcb[1] is used to save requested byte count
*/
if ((skb->len + 4) <= SOC_DCB_KNET_COUNT_MASK) {
pktdata = skb->data;
pktlen = skb->len + 4;
if (pktlen < (64 + taglen + hdrlen)) {
pktlen = (64 + taglen + hdrlen);
@ -4710,6 +4775,7 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev)
}
DBG_SKB(("Packet padded to %d bytes after tx callback\n", pktlen));
}
pktdata = skb->data;
} else {
DBG_WARN(("Tx drop: size of pkt (%d) is out of range(%d)\n",
pktlen, SOC_DCB_KNET_COUNT_MASK));
@ -4785,11 +4851,8 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev)
bkn_suspend_tx(sinfo);
}
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4,6,0))
dev->trans_start = jiffies;
#else
netif_trans_update(dev);
#endif
NETDEV_UPDATE_TRANS_START_TIME(dev);
spin_unlock_irqrestore(&sinfo->lock, flags);
return 0;
@ -5491,14 +5554,12 @@ bkn_seq_dma_show(struct seq_file *s, void *v)
seq_printf(s,
"Rx%d DCB info (unit %d):\n"
" api: %d\n"
" wait: %d\n"
" dirty: %d\n"
" cur: %d\n"
" free: %d\n"
" run: %d\n",
chan, iter->dev_no,
sinfo->rx[chan].api_active,
sinfo->rx[chan].api_wait,
sinfo->rx[chan].dirty,
sinfo->rx[chan].cur,
sinfo->rx[chan].free,
@ -6127,6 +6188,7 @@ bkn_knet_dma_info(kcom_msg_dma_info_t *kmsg, int len)
if (sinfo->cmic_type == 'x') {
dcb_chain_end->dcb_mem[woffset + 1] = DMA_TO_BUS_HI(dcb_chain->dcb_dma >> 32);
}
MEMORY_BARRIER;
}
sinfo->tx.api_dcb_chain_end = dcb_chain;
if (sinfo->tx.api_active) {
@ -6181,6 +6243,7 @@ bkn_knet_dma_info(kcom_msg_dma_info_t *kmsg, int len)
if (sinfo->cmic_type == 'x') {
dcb_chain_end->dcb_mem[woffset + 1] = DMA_TO_BUS_HI(dcb_chain->dcb_dma >> 32);
}
MEMORY_BARRIER;
}
sinfo->rx[chan].api_dcb_chain_end = dcb_chain;
if (!sinfo->rx[chan].use_rx_skb) {
@ -6194,18 +6257,6 @@ bkn_knet_dma_info(kcom_msg_dma_info_t *kmsg, int len)
if (sinfo->rx[chan].api_active == 0) {
bkn_api_rx_restart(sinfo, chan);
/* Resume SKB Rx due to refilled API resources */
if (sinfo->rx[chan].use_rx_skb && sinfo->rx[chan].api_wait) {
sinfo->rx[chan].api_wait = 0;
if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) {
bkn_do_skb_rx(sinfo, chan, 1);
} else {
bkn_do_skb_rx(sinfo, chan, MAX_RX_DCBS);
if (sinfo->rx[chan].chain_complete) {
bkn_rx_chain_done(sinfo, chan);
}
}
}
}
spin_unlock_irqrestore(&sinfo->lock, flags);
@ -6272,7 +6323,7 @@ bkn_knet_dev_reprobe(void)
for (i = 0; i < kernel_bde->num_devices(BDE_ALL_DEVICES); i++) {
sinfo = bkn_sinfo_from_unit(i);
if (sinfo == NULL ) {
if (sinfo == NULL) {
/* New device found after re-probe. */
if (bkn_knet_dev_init(i) < 0) {
return -1;
@ -6289,7 +6340,7 @@ bkn_knet_dev_reprobe(void)
/* Assign the inst_id and evt_idx */
static int
bkn_knet_dev_inst_set(kcom_msg_version_t *kmsg)
bkn_knet_dev_inst_set(kcom_msg_reprobe_t *kmsg)
{
bkn_switch_info_t *sinfo;
int d = kmsg->hdr.unit;
@ -6333,13 +6384,6 @@ bkn_knet_dev_inst_set(kcom_msg_version_t *kmsg)
static int
bkn_knet_version(kcom_msg_version_t *kmsg, int len)
{
/* Support pci hot plug and multiple instance */
if ((bkn_knet_dev_reprobe() < 0) ||
(bkn_knet_dev_inst_set(kmsg) < 0)) {
kmsg->hdr.status = KCOM_E_RESOURCE;
return sizeof(kcom_msg_version_t);
}
kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
kmsg->version = KCOM_VERSION;
kmsg->netif_max = KCOM_NETIF_MAX;
@ -6496,6 +6540,21 @@ bkn_knet_detach(kcom_msg_detach_t *kmsg, int len)
return sizeof(kcom_msg_detach_t);
}
static int
bkn_knet_reprobe(kcom_msg_reprobe_t *kmsg, int len)
{
kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
/* Support pci hot plug and multiple instance */
if ((bkn_knet_dev_reprobe() < 0) ||
(bkn_knet_dev_inst_set(kmsg) < 0)) {
kmsg->hdr.status = KCOM_E_RESOURCE;
return sizeof(kcom_msg_reprobe_t);
}
return sizeof(kcom_msg_reprobe_t);
}
static int
bkn_knet_netif_create(kcom_msg_netif_create_t *kmsg, int len)
{
@ -7007,7 +7066,6 @@ bkn_knet_wb_cleanup(kcom_msg_wb_cleanup_t *kmsg, int len)
}
sinfo->rx[chan].api_dcb_chain_end = NULL;
sinfo->rx[chan].api_active = 0;
sinfo->rx[chan].api_wait = 0;
}
spin_unlock_irqrestore(&sinfo->lock, flags);
@ -7055,6 +7113,11 @@ bkn_handle_cmd_req(kcom_msg_t *kmsg, int len)
/* Detach kernel module */
len = bkn_knet_detach(&kmsg->detach, len);
break;
case KCOM_M_REPROBE:
DBG_CMD(("KCOM_M_REPROBE\n"));
/* Reprobe device */
len = bkn_knet_reprobe(&kmsg->reprobe, len);
break;
case KCOM_M_NETIF_CREATE:
DBG_CMD(("KCOM_M_NETIF_CREATE\n"));
/* Create network interface */
@ -7174,8 +7237,7 @@ bkn_get_next_dma_event(kcom_msg_dma_info_t *kmsg)
}
DBG_INST(("%s dev %d evt_idx %d\n",__FUNCTION__, dev_evt, sinfo->evt_idx));
evt = &_bkn_evt[sinfo->evt_idx];
dev_no = last_dev_no = dev_evt;
dev_no = last_dev_no;
while (1) {
dev_no++;
sinfo = bkn_sinfo_from_unit(dev_no);
@ -7204,6 +7266,7 @@ bkn_get_next_dma_event(kcom_msg_dma_info_t *kmsg)
}
if (dev_no == last_dev_no) {
evt = &_bkn_evt[sinfo->evt_idx];
DBG_INST(("wait queue index %d\n",sinfo->evt_idx));
wait_event_interruptible(evt->evt_wq,
evt->evt_wq_get != evt->evt_wq_put);

View File

@ -62,6 +62,9 @@
#include <linux/interrupt.h>
#include <linux/stat.h>
#include <linux/sched.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0)
#include <linux/sched/signal.h>
#endif
#include <linux/delay.h>
#include <asm/io.h>