[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))
|
||||
#endif
|
||||
|
||||
extern void _dma_init(int robo_switch);
|
||||
extern void _dma_init(int robo_switch, int dev_index);
|
||||
extern int _dma_cleanup(void);
|
||||
extern void _dma_pprint(void);
|
||||
extern uint32_t *_salloc(int d, int size, const char *name);
|
||||
|
@ -540,6 +540,40 @@ _parse_eb_args(char *str, char * format, ...)
|
||||
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
|
||||
_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_data = NULL;
|
||||
|
||||
_bde_add_device();
|
||||
|
||||
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);
|
||||
|
||||
@ -627,6 +663,10 @@ sand_device_create(void)
|
||||
ctrl->dev_type |= BDE_PCI_DEV_TYPE | BDE_SWITCH_DEV_TYPE;
|
||||
}
|
||||
|
||||
#ifndef __DUNE_LINUX_BCM_CPU_PCIE__
|
||||
_bde_add_device();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@ -734,6 +774,7 @@ iproc_cmicd_probe(struct platform_device *pldev)
|
||||
#endif
|
||||
|
||||
/* Let's boogie */
|
||||
_bde_add_device();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -991,6 +1032,7 @@ _ics_bde_create(void)
|
||||
|
||||
ctrl->isr = NULL;
|
||||
ctrl->isr_data = NULL;
|
||||
_bde_add_device();
|
||||
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;
|
||||
#endif
|
||||
|
||||
if (!rescan) {
|
||||
_bde_add_device();
|
||||
}
|
||||
|
||||
if (debug >= 2) {
|
||||
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,
|
||||
@ -2968,6 +3014,7 @@ probe_robo_switch_iproc_spi(void)
|
||||
ctrl->isr = NULL;
|
||||
ctrl->isr_data = NULL;
|
||||
robo_switch++;
|
||||
_bde_add_device();
|
||||
|
||||
}
|
||||
|
||||
@ -3181,6 +3228,7 @@ probe_robo_switch(void)
|
||||
#if defined(KEYSTONE)
|
||||
spi_freq = _spi_id_table[match_idx].spifreq;
|
||||
#endif
|
||||
_bde_add_device();
|
||||
}
|
||||
|
||||
#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->phys_address = addr;
|
||||
|
||||
_bde_add_device();
|
||||
|
||||
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.rev = (dev_rev_id & 0xFF);
|
||||
|
||||
_bde_add_device();
|
||||
|
||||
switch (ctrl->bde_dev.device) {
|
||||
case BCM88130_DEVICE_ID:
|
||||
case BME3200_DEVICE_ID:
|
||||
@ -3697,41 +3749,6 @@ _init(void)
|
||||
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;
|
||||
}
|
||||
|
@ -590,9 +590,7 @@ _pgcleanup(void)
|
||||
static void
|
||||
_alloc_mpool(size_t size)
|
||||
{
|
||||
int i, ndevices;
|
||||
unsigned long pbase = 0;
|
||||
unsigned long orig_pbase = 0;
|
||||
|
||||
#if defined(__arm__) && !defined(CONFIG_HIGHMEM)
|
||||
if (_use_himem) {
|
||||
@ -649,27 +647,18 @@ _alloc_mpool(size_t size)
|
||||
return;
|
||||
}
|
||||
_cpu_pbase = virt_to_bus(_dma_vbase);
|
||||
ndevices = BDE_NUM_DEVICES(BDE_ALL_DEVICES);
|
||||
for (i = 0; i < ndevices && DMA_DEV(i); i ++) {
|
||||
/* Use dma_map_single to obtain DMA bus address or IOVA if iommu is present. */
|
||||
pbase = dma_map_single(DMA_DEV(i), _dma_vbase, size, DMA_BIDIRECTIONAL);
|
||||
if (_use_dma_mapping && (orig_pbase != pbase)) {
|
||||
/* 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;
|
||||
/* Use dma_map_single to obtain DMA bus address or IOVA if iommu is present. */
|
||||
if (DMA_DEV(0)) {
|
||||
pbase = dma_map_single(DMA_DEV(0), _dma_vbase, size, DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(DMA_DEV(0), pbase)) {
|
||||
gprintk("Failed to map memory at %p\n", _dma_vbase);
|
||||
_pgcleanup();
|
||||
_dma_vbase = NULL;
|
||||
_cpu_pbase = 0;
|
||||
return;
|
||||
}
|
||||
orig_pbase = pbase;
|
||||
_use_dma_mapping = 1;
|
||||
}
|
||||
if (!_use_dma_mapping) {
|
||||
} else {
|
||||
/* Device has not been probed. */
|
||||
pbase = _cpu_pbase;
|
||||
}
|
||||
@ -730,8 +719,20 @@ _dma_cleanup(void)
|
||||
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 */
|
||||
if (dmasize) {
|
||||
if ((dmasize[strlen(dmasize)-1] & ~0x20) == 'M') {
|
||||
|
Loading…
Reference in New Issue
Block a user