diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index c5b647febac43d70efdbc8487d41e7668df353e3..646b3c0a9171936869a3c0fa3de7c2251ffbb75c 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c @@ -44,7 +44,7 @@ int acpi_found_madt; int apic_version [MAX_APICS]; unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; -cpumask_t mp_bus_to_cpumask [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = CPU_MASK_ALL }; +cpumask_t pci_bus_to_cpumask [256] = { [0 ... 255] = CPU_MASK_ALL }; int mp_current_pci_id = 0; /* I/O APIC entries */ diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index 938bafe3e30eccde715ac6d77847a1df4d939ddd..09fde74cba5bd3545772266922658539548dce70 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c @@ -70,6 +70,8 @@ int iommu_fullflush = 1; static spinlock_t iommu_bitmap_lock = SPIN_LOCK_UNLOCKED; static unsigned long *iommu_gart_bitmap; /* guarded by iommu_bitmap_lock */ +static u32 gart_unmapped_entry; + #define GPTE_VALID 1 #define GPTE_COHERENT 2 #define GPTE_ENCODE(x) \ @@ -147,8 +149,6 @@ static void free_iommu(unsigned long offset, int size) static void flush_gart(struct pci_dev *dev) { unsigned long flags; - int bus = dev ? dev->bus->number : -1; - cpumask_t bus_cpumask = pcibus_to_cpumask(bus); int flushed = 0; int i; @@ -158,8 +158,6 @@ static void flush_gart(struct pci_dev *dev) u32 w; if (!northbridges[i]) continue; - if (bus >= 0 && !(cpu_isset(i, bus_cpumask))) - continue; pci_write_config_dword(northbridges[i], 0x9c, northbridge_flush_word[i] | 1); /* Make sure the hardware actually executed the flush. */ @@ -169,7 +167,7 @@ static void flush_gart(struct pci_dev *dev) flushed++; } if (!flushed) - printk("nothing to flush? %d\n", bus); + printk("nothing to flush?\n"); need_flush = 0; } spin_unlock_irqrestore(&iommu_bitmap_lock, flags); @@ -479,6 +477,11 @@ int pci_map_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, int dir) unsigned long pages = 0; int need = 0, nextneed; +#ifdef CONFIG_SWIOTLB + if (swiotlb) + return swiotlb_map_sg(&dev->dev,sg,nents,dir); +#endif + BUG_ON(dir == PCI_DMA_NONE); if (nents == 0) return 0; @@ -562,7 +565,7 @@ void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT; npages = to_pages(dma_addr, size); for (i = 0; i < npages; i++) { - iommu_gatt_base[iommu_page + i] = 0; + iommu_gatt_base[iommu_page + i] = gart_unmapped_entry; CLEAR_LEAK(iommu_page + i); } free_iommu(iommu_page, npages); @@ -729,7 +732,8 @@ static int __init pci_iommu_init(void) unsigned long aper_size; unsigned long iommu_start; struct pci_dev *dev; - + unsigned long scratch; + long i; #ifndef CONFIG_AGP_AMD64 no_agp = 1; @@ -766,7 +770,7 @@ static int __init pci_iommu_init(void) return -1; } } - + aper_size = info.aper_size * 1024 * 1024; iommu_size = check_iommu_size(info.aper_base, aper_size); iommu_pages = iommu_size >> PAGE_SHIFT; @@ -815,6 +819,19 @@ static int __init pci_iommu_init(void) */ clear_kernel_mapping((unsigned long)__va(iommu_bus_base), iommu_size); + /* + * Try to workaround a bug (thanks to BenH) + * Set unmapped entries to a scratch page instead of 0. + * Any prefetches that hit unmapped entries won't get an bus abort + * then. + */ + scratch = get_zeroed_page(GFP_KERNEL); + if (!scratch) + panic("Cannot allocate iommu scratch page"); + gart_unmapped_entry = GPTE_ENCODE(__pa(scratch)); + for (i = EMERGENCY_PAGES; i < iommu_pages; i++) + iommu_gatt_base[i] = gart_unmapped_entry; + for_all_nb(dev) { u32 flag; int cpu = PCI_SLOT(dev->devfn) - 24; diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 7aa05d696da349ac1f3bc8d40da0ed15dc18deeb..3ea6515e3428f1ef9de17f0db39943361b491c11 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -1942,7 +1942,7 @@ prism54_debug_get_oid(struct net_device *ndev, struct iw_request_info *info, { islpci_private *priv = netdev_priv(ndev); struct islpci_mgmtframe *response = NULL; - int ret = -EIO, response_op = PIMFOR_OP_ERROR; + int ret = -EIO; printk("%s: get_oid 0x%08X\n", ndev->name, priv->priv_oid); data->length = 0; @@ -1952,9 +1952,7 @@ prism54_debug_get_oid(struct net_device *ndev, struct iw_request_info *info, islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, priv->priv_oid, extra, 256, &response); - response_op = response->header->operation; printk("%s: ret: %i\n", ndev->name, ret); - printk("%s: response_op: %i\n", ndev->name, response_op); if (ret || !response || response->header->operation == PIMFOR_OP_ERROR) { if (response) { @@ -1991,16 +1989,20 @@ prism54_debug_set_oid(struct net_device *ndev, struct iw_request_info *info, priv->priv_oid, extra, data->length, &response); printk("%s: ret: %i\n", ndev->name, ret); + if (ret || !response + || response->header->operation == PIMFOR_OP_ERROR) { + if (response) { + islpci_mgt_release(response); + } + printk("%s: EIO\n", ndev->name); + ret = -EIO; + } if (!ret) { response_op = response->header->operation; printk("%s: response_op: %i\n", ndev->name, response_op); islpci_mgt_release(response); } - if (ret || response_op == PIMFOR_OP_ERROR) { - printk("%s: EIO\n", ndev->name); - ret = -EIO; - } } return (ret ? ret : -EINPROGRESS); diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index 11b4c830e56fb5e9f479aee2a5f364b1cffe8992..d279f82960ebf029e67b307474040462d1ce6aa6 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -36,6 +36,9 @@ MODULE_AUTHOR("[Intersil] R.Bastings and W.Termorshuizen, The prism54.org Develo MODULE_DESCRIPTION("The Prism54 802.11 Wireless LAN adapter"); MODULE_LICENSE("GPL"); +static int init_pcitm = 0; +module_param(init_pcitm, int, 0); + /* In this order: vendor, device, subvendor, subdevice, class, class_mask, * driver_data * If you have an update for this please contact prism54-devel@prism54.org @@ -292,14 +295,14 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) * * Writing zero to both these two registers will disable both timeouts and * *can* solve problems caused by devices that are slow to respond. + * Make this configurable - MSW */ - /* I am taking these out, we should not be poking around in the - * programmable timers - MSW - */ -/* Do not zero the programmable timers - pci_write_config_byte(pdev, 0x40, 0); - pci_write_config_byte(pdev, 0x41, 0); -*/ + if ( init_pcitm >= 0 ) { + pci_write_config_byte(pdev, 0x40, (u8)init_pcitm); + pci_write_config_byte(pdev, 0x41, (u8)init_pcitm); + } else { + printk(KERN_INFO "PCI TRDY/RETRY unchanged\n"); + } /* request the pci device I/O regions */ rvalue = pci_request_regions(pdev, DRV_NAME); diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c index 58cd35864672258fbfaf7a13d9fd5cc8d815696d..95b709c907c5e6117cada2e6452df09f6ee1a216 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ b/drivers/net/wireless/prism54/islpci_mgt.c @@ -458,6 +458,8 @@ islpci_mgt_transaction(struct net_device *ndev, int err; DEFINE_WAIT(wait); + *recvframe = NULL; + if (down_interruptible(&priv->mgmt_sem)) return -ERESTARTSYS; diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c index 65085ee1ae95cb7e8f09617b10f962ba921e6922..c4ec1e4878e082761bfcf8e3fe2d7570bbaf3f76 100644 --- a/drivers/net/wireless/prism54/oid_mgt.c +++ b/drivers/net/wireless/prism54/oid_mgt.c @@ -408,7 +408,7 @@ int mgt_set_request(islpci_private *priv, enum oid_num_t n, int extra, void *data) { int ret = 0; - struct islpci_mgmtframe *response; + struct islpci_mgmtframe *response = NULL; int response_op = PIMFOR_OP_ERROR; int dlen; void *cache, *_data = data; @@ -613,14 +613,16 @@ static enum oid_num_t commit_part2[] = { DOT11_OID_DEFKEYID, DOT11_OID_DOT1XENABLE, OID_INL_DOT11D_CONFORMANCE, + /* Do not initialize this - fw < 1.0.4.3 rejects it OID_INL_OUTPUTPOWER, + */ }; /* update the MAC addr. */ static int mgt_update_addr(islpci_private *priv) { - struct islpci_mgmtframe *res; + struct islpci_mgmtframe *res = NULL; int ret; ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, diff --git a/include/asm-x86_64/mpspec.h b/include/asm-x86_64/mpspec.h index 219d40acd489fdbb2eb0cdce40f8f35094fde7c4..2768b7c83ef6df80316eae206993fa279aaaa8bf 100644 --- a/include/asm-x86_64/mpspec.h +++ b/include/asm-x86_64/mpspec.h @@ -166,7 +166,7 @@ enum mp_bustype { }; extern unsigned char mp_bus_id_to_type [MAX_MP_BUSSES]; extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES]; -extern cpumask_t mp_bus_to_cpumask [MAX_MP_BUSSES]; +extern cpumask_t pci_bus_to_cpumask [256]; extern unsigned int boot_cpu_physical_apicid; extern int smp_found_config; diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h index 9310f9a1c1c5cc1c1e1818da5b122d23d72404cd..dbc3f15792bd22df770da0b23e81e531da4cba61 100644 --- a/include/asm-x86_64/topology.h +++ b/include/asm-x86_64/topology.h @@ -22,9 +22,9 @@ extern cpumask_t node_to_cpumask[]; static inline cpumask_t pcibus_to_cpumask(int bus) { - cpumask_t tmp; - cpus_and(tmp, mp_bus_to_cpumask[bus], cpu_online_map); - return tmp; + cpumask_t res; + cpus_and(res, pci_bus_to_cpumask[bus], cpu_online_map); + return res; } #define NODE_BALANCE_RATE 30 /* CHECKME */