[knet driver] fix PCI device init race condition
Broadcom CS5982299 fix. Signed-off-by: Ying Xie <ying.xie@microsoft.com>
This commit is contained in:
parent
a11c28de46
commit
560d35bf42
@ -58,7 +58,7 @@
|
|||||||
#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
|
#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void _dma_init(int robo_switch);
|
extern void _dma_init(int robo_switch, int dev_index);
|
||||||
extern int _dma_cleanup(void);
|
extern int _dma_cleanup(void);
|
||||||
extern void _dma_pprint(void);
|
extern void _dma_pprint(void);
|
||||||
extern uint32_t *_salloc(int d, int size, const char *name);
|
extern uint32_t *_salloc(int d, int size, const char *name);
|
||||||
|
@ -540,6 +540,40 @@ _parse_eb_args(char *str, char * format, ...)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_bde_add_device(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* In order to be backward compatible with the user mode BDE
|
||||||
|
* (specifically the interrupt IOCTLs) and the CM, switch devices
|
||||||
|
* *must* come first. If this is not the case (due to the probing
|
||||||
|
* order), we let the non-switch device(s) drop down to the end of
|
||||||
|
* the device array.
|
||||||
|
*/
|
||||||
|
if (_switch_ndevices > 0) {
|
||||||
|
bde_ctrl_t tmp_dev;
|
||||||
|
int i, s = 0;
|
||||||
|
|
||||||
|
while (s < _switch_ndevices) {
|
||||||
|
if (_devices[s].dev_type & BDE_SWITCH_DEV_TYPE) {
|
||||||
|
s++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tmp_dev = _devices[s];
|
||||||
|
for (i = s; i < _ndevices - 1; i++) {
|
||||||
|
_devices[i] = _devices[i+1];
|
||||||
|
}
|
||||||
|
_devices[i] = tmp_dev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize device locks and dma */
|
||||||
|
if (_ndevices > 0) {
|
||||||
|
spin_lock_init(&_devices[_ndevices-1].lock);
|
||||||
|
_dma_init(robo_switch, _ndevices-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_eb_device_create(resource_size_t paddr, int irq, int rd_hw, int wr_hw)
|
_eb_device_create(resource_size_t paddr, int irq, int rd_hw, int wr_hw)
|
||||||
{
|
{
|
||||||
@ -575,6 +609,8 @@ _eb_device_create(resource_size_t paddr, int irq, int rd_hw, int wr_hw)
|
|||||||
ctrl->isr = NULL;
|
ctrl->isr = NULL;
|
||||||
ctrl->isr_data = NULL;
|
ctrl->isr_data = NULL;
|
||||||
|
|
||||||
|
_bde_add_device();
|
||||||
|
|
||||||
gprintk("Created EB device at BA=%x IRQ=%d RD16=%d WR16=%d device=0x%x\n",
|
gprintk("Created EB device at BA=%x IRQ=%d RD16=%d WR16=%d device=0x%x\n",
|
||||||
(unsigned int)paddr, irq, rd_hw, wr_hw, ctrl->bde_dev.device);
|
(unsigned int)paddr, irq, rd_hw, wr_hw, ctrl->bde_dev.device);
|
||||||
|
|
||||||
@ -627,6 +663,10 @@ sand_device_create(void)
|
|||||||
ctrl->dev_type |= BDE_PCI_DEV_TYPE | BDE_SWITCH_DEV_TYPE;
|
ctrl->dev_type |= BDE_PCI_DEV_TYPE | BDE_SWITCH_DEV_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __DUNE_LINUX_BCM_CPU_PCIE__
|
||||||
|
_bde_add_device();
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -734,6 +774,7 @@ iproc_cmicd_probe(struct platform_device *pldev)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Let's boogie */
|
/* Let's boogie */
|
||||||
|
_bde_add_device();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -991,6 +1032,7 @@ _ics_bde_create(void)
|
|||||||
|
|
||||||
ctrl->isr = NULL;
|
ctrl->isr = NULL;
|
||||||
ctrl->isr_data = NULL;
|
ctrl->isr_data = NULL;
|
||||||
|
_bde_add_device();
|
||||||
printk("Created ICS device ..%x\n", ctrl->bde_dev.base_address);
|
printk("Created ICS device ..%x\n", ctrl->bde_dev.base_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2629,6 +2671,10 @@ _pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
|
|||||||
ctrl->dma_dev = &dev->dev;
|
ctrl->dma_dev = &dev->dev;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!rescan) {
|
||||||
|
_bde_add_device();
|
||||||
|
}
|
||||||
|
|
||||||
if (debug >= 2) {
|
if (debug >= 2) {
|
||||||
gprintk("_pci_probe: configured dev:0x%x rev:0x%x with base_addresses: 0x%lx 0x%lx\n",
|
gprintk("_pci_probe: configured dev:0x%x rev:0x%x with base_addresses: 0x%lx 0x%lx\n",
|
||||||
(unsigned)ctrl->bde_dev.device, (unsigned)ctrl->bde_dev.rev,
|
(unsigned)ctrl->bde_dev.device, (unsigned)ctrl->bde_dev.rev,
|
||||||
@ -2968,6 +3014,7 @@ probe_robo_switch_iproc_spi(void)
|
|||||||
ctrl->isr = NULL;
|
ctrl->isr = NULL;
|
||||||
ctrl->isr_data = NULL;
|
ctrl->isr_data = NULL;
|
||||||
robo_switch++;
|
robo_switch++;
|
||||||
|
_bde_add_device();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3181,6 +3228,7 @@ probe_robo_switch(void)
|
|||||||
#if defined(KEYSTONE)
|
#if defined(KEYSTONE)
|
||||||
spi_freq = _spi_id_table[match_idx].spifreq;
|
spi_freq = _spi_id_table[match_idx].spifreq;
|
||||||
#endif
|
#endif
|
||||||
|
_bde_add_device();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(KEYSTONE)
|
#if defined(KEYSTONE)
|
||||||
@ -3226,6 +3274,8 @@ map_local_bus(uint64_t addr, uint32_t size)
|
|||||||
ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(addr, size);
|
ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(addr, size);
|
||||||
ctrl->phys_address = addr;
|
ctrl->phys_address = addr;
|
||||||
|
|
||||||
|
_bde_add_device();
|
||||||
|
|
||||||
return(ctrl);
|
return(ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3377,6 +3427,8 @@ map_local_bus2(bde_ctrl_t *plx_ctrl, uint32_t dev_base, uint32_t size)
|
|||||||
ctrl->bde_dev.device = dev_rev_id >> 16;
|
ctrl->bde_dev.device = dev_rev_id >> 16;
|
||||||
ctrl->bde_dev.rev = (dev_rev_id & 0xFF);
|
ctrl->bde_dev.rev = (dev_rev_id & 0xFF);
|
||||||
|
|
||||||
|
_bde_add_device();
|
||||||
|
|
||||||
switch (ctrl->bde_dev.device) {
|
switch (ctrl->bde_dev.device) {
|
||||||
case BCM88130_DEVICE_ID:
|
case BCM88130_DEVICE_ID:
|
||||||
case BME3200_DEVICE_ID:
|
case BME3200_DEVICE_ID:
|
||||||
@ -3697,41 +3749,6 @@ _init(void)
|
|||||||
tok = strtok(NULL,",");
|
tok = strtok(NULL,",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_dma_init(robo_switch);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* In order to be backward compatible with the user mode BDE
|
|
||||||
* (specifically the interrupt IOCTLs) and the CM, switch devices
|
|
||||||
* *must* come first. If this is not the case (due to the probing
|
|
||||||
* order), we let the non-switch device(s) drop down to the end of
|
|
||||||
* the device array.
|
|
||||||
*/
|
|
||||||
if (_switch_ndevices > 0) {
|
|
||||||
bde_ctrl_t tmp_dev;
|
|
||||||
int i, s = 0;
|
|
||||||
|
|
||||||
while (s < _switch_ndevices) {
|
|
||||||
if (_devices[s].dev_type & BDE_SWITCH_DEV_TYPE) {
|
|
||||||
s++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
tmp_dev = _devices[s];
|
|
||||||
for (i = s; i < _ndevices - 1; i++) {
|
|
||||||
_devices[i] = _devices[i+1];
|
|
||||||
}
|
|
||||||
_devices[i] = tmp_dev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize device locks */
|
|
||||||
if (_ndevices > 0) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < _ndevices; i++) {
|
|
||||||
spin_lock_init(&_devices[i].lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -590,9 +590,7 @@ _pgcleanup(void)
|
|||||||
static void
|
static void
|
||||||
_alloc_mpool(size_t size)
|
_alloc_mpool(size_t size)
|
||||||
{
|
{
|
||||||
int i, ndevices;
|
|
||||||
unsigned long pbase = 0;
|
unsigned long pbase = 0;
|
||||||
unsigned long orig_pbase = 0;
|
|
||||||
|
|
||||||
#if defined(__arm__) && !defined(CONFIG_HIGHMEM)
|
#if defined(__arm__) && !defined(CONFIG_HIGHMEM)
|
||||||
if (_use_himem) {
|
if (_use_himem) {
|
||||||
@ -649,27 +647,18 @@ _alloc_mpool(size_t size)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_cpu_pbase = virt_to_bus(_dma_vbase);
|
_cpu_pbase = virt_to_bus(_dma_vbase);
|
||||||
ndevices = BDE_NUM_DEVICES(BDE_ALL_DEVICES);
|
/* Use dma_map_single to obtain DMA bus address or IOVA if iommu is present. */
|
||||||
for (i = 0; i < ndevices && DMA_DEV(i); i ++) {
|
if (DMA_DEV(0)) {
|
||||||
/* Use dma_map_single to obtain DMA bus address or IOVA if iommu is present. */
|
pbase = dma_map_single(DMA_DEV(0), _dma_vbase, size, DMA_BIDIRECTIONAL);
|
||||||
pbase = dma_map_single(DMA_DEV(i), _dma_vbase, size, DMA_BIDIRECTIONAL);
|
if (dma_mapping_error(DMA_DEV(0), pbase)) {
|
||||||
if (_use_dma_mapping && (orig_pbase != pbase)) {
|
gprintk("Failed to map memory at %p\n", _dma_vbase);
|
||||||
/* Bus address/IOVA must be identical for all devices. */
|
|
||||||
gprintk("deivce %d has different pbase: %lx (should be %lx)\n",
|
|
||||||
i, pbase, orig_pbase);
|
|
||||||
dma_unmap_single(DMA_DEV(i), (dma_addr_t)pbase, size, DMA_BIDIRECTIONAL);
|
|
||||||
while (--i >= 0 && DMA_DEV(i)) {
|
|
||||||
dma_unmap_single(DMA_DEV(i), (dma_addr_t)orig_pbase, size, DMA_BIDIRECTIONAL);
|
|
||||||
}
|
|
||||||
_use_dma_mapping = 0;
|
|
||||||
_pgcleanup();
|
_pgcleanup();
|
||||||
_dma_vbase = NULL;
|
_dma_vbase = NULL;
|
||||||
|
_cpu_pbase = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
orig_pbase = pbase;
|
|
||||||
_use_dma_mapping = 1;
|
_use_dma_mapping = 1;
|
||||||
}
|
} else {
|
||||||
if (!_use_dma_mapping) {
|
|
||||||
/* Device has not been probed. */
|
/* Device has not been probed. */
|
||||||
pbase = _cpu_pbase;
|
pbase = _cpu_pbase;
|
||||||
}
|
}
|
||||||
@ -730,8 +719,20 @@ _dma_cleanup(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _dma_init(int robo_switch)
|
void _dma_init(int robo_switch, int dev_index)
|
||||||
{
|
{
|
||||||
|
unsigned long pbase;
|
||||||
|
|
||||||
|
if (dev_index > 0) {
|
||||||
|
if ((_use_dma_mapping == 1) && DMA_DEV(dev_index) && _dma_vbase) {
|
||||||
|
pbase = dma_map_single(DMA_DEV(dev_index), _dma_vbase, _dma_mem_size, DMA_BIDIRECTIONAL);
|
||||||
|
if (dma_mapping_error(DMA_DEV(dev_index), pbase)) {
|
||||||
|
gprintk("Failed to map memory for device %d at %p\n", dev_index, _dma_vbase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* DMA Setup */
|
/* DMA Setup */
|
||||||
if (dmasize) {
|
if (dmasize) {
|
||||||
if ((dmasize[strlen(dmasize)-1] & ~0x20) == 'M') {
|
if ((dmasize[strlen(dmasize)-1] & ~0x20) == 'M') {
|
||||||
|
Reference in New Issue
Block a user