diff options
Diffstat (limited to 'drivers/parisc')
| -rw-r--r-- | drivers/parisc/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/parisc/README.dino | 3 | ||||
| -rw-r--r-- | drivers/parisc/asp.c | 8 | ||||
| -rw-r--r-- | drivers/parisc/ccio-dma.c | 180 | ||||
| -rw-r--r-- | drivers/parisc/ccio-rm-dma.c | 1 | ||||
| -rw-r--r-- | drivers/parisc/dino.c | 180 | ||||
| -rw-r--r-- | drivers/parisc/eisa.c | 45 | ||||
| -rw-r--r-- | drivers/parisc/eisa_eeprom.c | 29 | ||||
| -rw-r--r-- | drivers/parisc/eisa_enumerator.c | 20 | ||||
| -rw-r--r-- | drivers/parisc/gsc.c | 85 | ||||
| -rw-r--r-- | drivers/parisc/gsc.h | 4 | ||||
| -rw-r--r-- | drivers/parisc/hppb.c | 24 | ||||
| -rw-r--r-- | drivers/parisc/iommu-helpers.h | 17 | ||||
| -rw-r--r-- | drivers/parisc/iosapic.c | 182 | ||||
| -rw-r--r-- | drivers/parisc/iosapic_private.h | 2 | ||||
| -rw-r--r-- | drivers/parisc/lasi.c | 7 | ||||
| -rw-r--r-- | drivers/parisc/lba_pci.c | 506 | ||||
| -rw-r--r-- | drivers/parisc/led.c | 150 | ||||
| -rw-r--r-- | drivers/parisc/pdc_stable.c | 234 | ||||
| -rw-r--r-- | drivers/parisc/power.c | 207 | ||||
| -rw-r--r-- | drivers/parisc/sba_iommu.c | 497 | ||||
| -rw-r--r-- | drivers/parisc/superio.c | 67 | ||||
| -rw-r--r-- | drivers/parisc/wax.c | 5 |
23 files changed, 1108 insertions, 1356 deletions
diff --git a/drivers/parisc/Kconfig b/drivers/parisc/Kconfig index 1d3b84b4af3..592de566e72 100644 --- a/drivers/parisc/Kconfig +++ b/drivers/parisc/Kconfig @@ -103,12 +103,10 @@ config IOMMU_SBA depends on PCI_LBA default PCI_LBA -#config PCI_EPIC -# bool "EPIC/SAGA PCI support" -# depends on PCI -# default y -# help -# Say Y here for V-class PCI, DMA/IOMMU, IRQ subsystem support. +config IOMMU_HELPER + bool + depends on IOMMU_SBA || IOMMU_CCIO + default y source "drivers/pcmcia/Kconfig" @@ -130,6 +128,7 @@ config SUPERIO config CHASSIS_LCD_LED bool "Chassis LCD and LED support" default y + select VM_EVENT_COUNTERS help Say Y here if you want to enable support for the Heartbeat, Disk/Network activities LEDs on some PA-RISC machines, diff --git a/drivers/parisc/README.dino b/drivers/parisc/README.dino index 097324f34bb..1627426996c 100644 --- a/drivers/parisc/README.dino +++ b/drivers/parisc/README.dino @@ -10,8 +10,7 @@ ** PCI bus. HP-supplied graphics cards that utilize the PCI bus are ** not affected." ** -** REVISIT: "go/pci_defect" link below is stale. -** HP Internal can use <http://hpfcdma.fc.hp.com:80/Dino/> +** http://h20000.www2.hp.com/bizsupport/TechSupport/Home.jsp?locale=en_US&prodTypeId=12454&prodSeriesId=44443 ** ** Product First Good Serial Number ** C200/C240 (US) US67350000 diff --git a/drivers/parisc/asp.c b/drivers/parisc/asp.c index 558420bc9f8..6a1ab2512a5 100644 --- a/drivers/parisc/asp.c +++ b/drivers/parisc/asp.c @@ -15,7 +15,6 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/module.h> -#include <linux/slab.h> #include <linux/types.h> #include <asm/io.h> #include <asm/led.h> @@ -71,8 +70,7 @@ static void asp_choose_irq(struct parisc_device *dev, void *ctrl) */ #define ASP_INTERRUPT_ADDR 0xf0800000 -int __init -asp_init_chip(struct parisc_device *dev) +static int __init asp_init_chip(struct parisc_device *dev) { struct gsc_irq gsc_irq; int ret; @@ -82,13 +80,13 @@ asp_init_chip(struct parisc_device *dev) asp.hpa = ASP_INTERRUPT_ADDR; printk(KERN_INFO "%s version %d at 0x%lx found.\n", - asp.name, asp.version, dev->hpa.start); + asp.name, asp.version, (unsigned long)dev->hpa.start); /* the IRQ ASP should use */ ret = -EBUSY; dev->irq = gsc_claim_irq(&gsc_irq, ASP_GSC_IRQ); if (dev->irq < 0) { - printk(KERN_ERR "%s(): cannot get GSC irq\n", __FUNCTION__); + printk(KERN_ERR "%s(): cannot get GSC irq\n", __func__); goto out; } diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 68cb3a08005..8b490d77054 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -32,6 +32,7 @@ */ #include <linux/types.h> +#include <linux/kernel.h> #include <linux/init.h> #include <linux/mm.h> #include <linux/spinlock.h> @@ -41,6 +42,9 @@ #include <linux/reboot.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> +#include <linux/scatterlist.h> +#include <linux/iommu-helper.h> +#include <linux/export.h> #include <asm/byteorder.h> #include <asm/cache.h> /* for L1_CACHE_BYTES */ @@ -63,18 +67,10 @@ #undef DEBUG_CCIO_RUN_SG #ifdef CONFIG_PROC_FS -/* - * CCIO_SEARCH_TIME can help measure how fast the bitmap search is. - * impacts performance though - ditch it if you don't use it. - */ -#define CCIO_SEARCH_TIME -#undef CCIO_MAP_STATS -#else -#undef CCIO_SEARCH_TIME -#undef CCIO_MAP_STATS +/* depends on proc fs support. But costs CPU performance. */ +#undef CCIO_COLLECT_STATS #endif -#include <linux/proc_fs.h> #include <asm/runway.h> /* for proc_runway_root */ #ifdef DEBUG_CCIO_INIT @@ -236,12 +232,10 @@ struct ioc { u32 res_size; /* size of resource map in bytes */ spinlock_t res_lock; -#ifdef CCIO_SEARCH_TIME +#ifdef CCIO_COLLECT_STATS #define CCIO_SEARCH_SAMPLE 0x100 unsigned long avg_search[CCIO_SEARCH_SAMPLE]; unsigned long avg_idx; /* current index into avg_search */ -#endif -#ifdef CCIO_MAP_STATS unsigned long used_pages; unsigned long msingle_calls; unsigned long msingle_pages; @@ -292,7 +286,6 @@ static int ioc_count; #define PDIR_INDEX(iovp) ((iovp)>>IOVP_SHIFT) #define MKIOVP(pdir_idx) ((long)(pdir_idx) << IOVP_SHIFT) #define MKIOVA(iovp,offset) (dma_addr_t)((long)iovp | (long)offset) -#define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1)) /* ** Don't worry about the 150% average search length on a miss. @@ -301,13 +294,17 @@ static int ioc_count; */ #define CCIO_SEARCH_LOOP(ioc, res_idx, mask, size) \ for(; res_ptr < res_end; ++res_ptr) { \ - if(0 == (*res_ptr & mask)) { \ - *res_ptr |= mask; \ - res_idx = (unsigned int)((unsigned long)res_ptr - (unsigned long)ioc->res_map); \ - ioc->res_hint = res_idx + (size >> 3); \ - goto resource_found; \ - } \ - } + int ret;\ + unsigned int idx;\ + idx = (unsigned int)((unsigned long)res_ptr - (unsigned long)ioc->res_map); \ + ret = iommu_is_span_boundary(idx << 3, pages_needed, 0, boundary_size);\ + if ((0 == (*res_ptr & mask)) && !ret) { \ + *res_ptr |= mask; \ + res_idx = idx;\ + ioc->res_hint = res_idx + (size >> 3); \ + goto resource_found; \ + } \ + } #define CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, size) \ u##size *res_ptr = (u##size *)&((ioc)->res_map[ioa->res_hint & ~((size >> 3) - 1)]); \ @@ -340,11 +337,12 @@ static int ioc_count; * of available pages for the requested size. */ static int -ccio_alloc_range(struct ioc *ioc, size_t size) +ccio_alloc_range(struct ioc *ioc, struct device *dev, size_t size) { unsigned int pages_needed = size >> IOVP_SHIFT; unsigned int res_idx; -#ifdef CCIO_SEARCH_TIME + unsigned long boundary_size; +#ifdef CCIO_COLLECT_STATS unsigned long cr_start = mfctl(16); #endif @@ -352,17 +350,20 @@ ccio_alloc_range(struct ioc *ioc, size_t size) BUG_ON((pages_needed * IOVP_SIZE) > DMA_CHUNK_SIZE); DBG_RES("%s() size: %d pages_needed %d\n", - __FUNCTION__, size, pages_needed); + __func__, size, pages_needed); /* ** "seek and ye shall find"...praying never hurts either... ** ggg sacrifices another 710 to the computer gods. */ + boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1, + 1ULL << IOVP_SHIFT) >> IOVP_SHIFT; + if (pages_needed <= 8) { /* * LAN traffic will not thrash the TLB IFF the same NIC - * uses 8 adjacent pages to map seperate payload data. + * uses 8 adjacent pages to map separate payload data. * ie the same byte in the resource bit map. */ #if 0 @@ -385,18 +386,18 @@ ccio_alloc_range(struct ioc *ioc, size_t size) #endif } else { panic("%s: %s() Too many pages to map. pages_needed: %u\n", - __FILE__, __FUNCTION__, pages_needed); + __FILE__, __func__, pages_needed); } panic("%s: %s() I/O MMU is out of mapping resources.\n", __FILE__, - __FUNCTION__); + __func__); resource_found: DBG_RES("%s() res_idx %d res_hint: %d\n", - __FUNCTION__, res_idx, ioc->res_hint); + __func__, res_idx, ioc->res_hint); -#ifdef CCIO_SEARCH_TIME +#ifdef CCIO_COLLECT_STATS { unsigned long cr_end = mfctl(16); unsigned long tmp = cr_end - cr_start; @@ -405,8 +406,6 @@ resource_found: } ioc->avg_search[ioc->avg_idx++] = cr_start; ioc->avg_idx &= CCIO_SEARCH_SAMPLE - 1; -#endif -#ifdef CCIO_MAP_STATS ioc->used_pages += pages_needed; #endif /* @@ -440,9 +439,9 @@ ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped) BUG_ON(pages_mapped > BITS_PER_LONG); DBG_RES("%s(): res_idx: %d pages_mapped %d\n", - __FUNCTION__, res_idx, pages_mapped); + __func__, res_idx, pages_mapped); -#ifdef CCIO_MAP_STATS +#ifdef CCIO_COLLECT_STATS ioc->used_pages -= pages_mapped; #endif @@ -452,10 +451,10 @@ ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped) unsigned long mask = ~(~0UL >> pages_mapped); CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 8); #else - CCIO_FREE_MAPPINGS(ioc, res_idx, 0xff, 8); + CCIO_FREE_MAPPINGS(ioc, res_idx, 0xffUL, 8); #endif } else if(pages_mapped <= 16) { - CCIO_FREE_MAPPINGS(ioc, res_idx, 0xffff, 16); + CCIO_FREE_MAPPINGS(ioc, res_idx, 0xffffUL, 16); } else if(pages_mapped <= 32) { CCIO_FREE_MAPPINGS(ioc, res_idx, ~(unsigned int)0, 32); #ifdef __LP64__ @@ -464,7 +463,7 @@ ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped) #endif } else { panic("%s:%s() Too many pages to unmap.\n", __FILE__, - __FUNCTION__); + __func__); } } @@ -486,7 +485,7 @@ typedef unsigned long space_t; ** This bit tells U2 to do R/M/W for partial cachelines. "Streaming" ** data can avoid this if the mapping covers full cache lines. ** o STOP_MOST is needed for atomicity across cachelines. -** Apperently only "some EISA devices" need this. +** Apparently only "some EISA devices" need this. ** Using CONFIG_ISA is hack. Only the IOA with EISA under it needs ** to use this hint iff the EISA devices needs this feature. ** According to the U2 ERS, STOP_MOST enabled pages hurt performance. @@ -554,7 +553,7 @@ static u32 hint_lookup[] = { * (Load Coherence Index) instruction. The 8 bits used for the virtual * index are bits 12:19 of the value returned by LCI. */ -void CCIO_INLINE +static void CCIO_INLINE ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, unsigned long hints) { @@ -652,7 +651,7 @@ ccio_clear_io_tlb(struct ioc *ioc, dma_addr_t iovp, size_t byte_cnt) * Mark the I/O Pdir entries invalid and blow away the corresponding I/O * TLB entries. * - * FIXME: at some threshhold it might be "cheaper" to just blow + * FIXME: at some threshold it might be "cheaper" to just blow * away the entire I/O TLB instead of individual entries. * * FIXME: Uturn has 256 TLB entries. We don't need to purge every @@ -668,7 +667,7 @@ ccio_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt) size_t saved_byte_cnt; /* round up to nearest page size */ - saved_byte_cnt = byte_cnt = ROUNDUP(byte_cnt, IOVP_SIZE); + saved_byte_cnt = byte_cnt = ALIGN(byte_cnt, IOVP_SIZE); while(byte_cnt > 0) { /* invalidate one page at a time */ @@ -751,21 +750,21 @@ ccio_map_single(struct device *dev, void *addr, size_t size, offset = ((unsigned long) addr) & ~IOVP_MASK; /* round up to nearest IOVP_SIZE */ - size = ROUNDUP(size + offset, IOVP_SIZE); + size = ALIGN(size + offset, IOVP_SIZE); spin_lock_irqsave(&ioc->res_lock, flags); -#ifdef CCIO_MAP_STATS +#ifdef CCIO_COLLECT_STATS ioc->msingle_calls++; ioc->msingle_pages += size >> IOVP_SHIFT; #endif - idx = ccio_alloc_range(ioc, size); + idx = ccio_alloc_range(ioc, dev, size); iovp = (dma_addr_t)MKIOVP(idx); pdir_start = &(ioc->pdir_base[idx]); DBG_RUN("%s() 0x%p -> 0x%lx size: %0x%x\n", - __FUNCTION__, addr, (long)iovp | offset, size); + __func__, addr, (long)iovp | offset, size); /* If not cacheline aligned, force SAFE_DMA on the whole mess */ if((size % L1_CACHE_BYTES) || ((unsigned long)addr % L1_CACHE_BYTES)) @@ -810,15 +809,15 @@ ccio_unmap_single(struct device *dev, dma_addr_t iova, size_t size, ioc = GET_IOC(dev); DBG_RUN("%s() iovp 0x%lx/%x\n", - __FUNCTION__, (long)iova, size); + __func__, (long)iova, size); iova ^= offset; /* clear offset bits */ size += offset; - size = ROUNDUP(size, IOVP_SIZE); + size = ALIGN(size, IOVP_SIZE); spin_lock_irqsave(&ioc->res_lock, flags); -#ifdef CCIO_MAP_STATS +#ifdef CCIO_COLLECT_STATS ioc->usingle_calls++; ioc->usingle_pages += size >> IOVP_SHIFT; #endif @@ -884,7 +883,7 @@ ccio_free_consistent(struct device *dev, size_t size, void *cpu_addr, */ #define PIDE_FLAG 0x80000000UL -#ifdef CCIO_MAP_STATS +#ifdef CCIO_COLLECT_STATS #define IOMMU_MAP_STATS #endif #include "iommu-helpers.h" @@ -912,7 +911,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents, BUG_ON(!dev); ioc = GET_IOC(dev); - DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents); + DBG_RUN_SG("%s() START %d entries\n", __func__, nents); /* Fast path single entry scatterlists. */ if (nents == 1) { @@ -928,7 +927,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents, spin_lock_irqsave(&ioc->res_lock, flags); -#ifdef CCIO_MAP_STATS +#ifdef CCIO_COLLECT_STATS ioc->msg_calls++; #endif @@ -940,7 +939,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents, ** w/o this association, we wouldn't have coherent DMA! ** Access to the virtual address is what forces a two pass algorithm. */ - coalesced = iommu_coalesce_chunks(ioc, sglist, nents, ccio_alloc_range); + coalesced = iommu_coalesce_chunks(ioc, dev, sglist, nents, ccio_alloc_range); /* ** Program the I/O Pdir @@ -956,7 +955,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents, BUG_ON(coalesced != filled); - DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled); + DBG_RUN_SG("%s() DONE %d mappings\n", __func__, filled); for (i = 0; i < filled; i++) current_len += sg_dma_len(sglist + i); @@ -985,15 +984,15 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, ioc = GET_IOC(dev); DBG_RUN_SG("%s() START %d entries, %08lx,%x\n", - __FUNCTION__, nents, sg_virt_addr(sglist), sglist->length); + __func__, nents, sg_virt_addr(sglist), sglist->length); -#ifdef CCIO_MAP_STATS +#ifdef CCIO_COLLECT_STATS ioc->usg_calls++; #endif while(sg_dma_len(sglist) && nents--) { -#ifdef CCIO_MAP_STATS +#ifdef CCIO_COLLECT_STATS ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT; #endif ccio_unmap_single(dev, sg_dma_address(sglist), @@ -1001,7 +1000,7 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, ++sglist; } - DBG_RUN_SG("%s() DONE (nents %d)\n", __FUNCTION__, nents); + DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents); } static struct hppa_dma_ops ccio_ops = { @@ -1027,8 +1026,10 @@ static int ccio_proc_info(struct seq_file *m, void *p) while (ioc != NULL) { unsigned int total_pages = ioc->res_size << 3; +#ifdef CCIO_COLLECT_STATS unsigned long avg = 0, min, max; int j; +#endif len += seq_printf(m, "%s\n", ioc->name); @@ -1038,7 +1039,7 @@ static int ccio_proc_info(struct seq_file *m, void *p) len += seq_printf(m, "IO PDIR size : %d bytes (%d entries)\n", total_pages * 8, total_pages); -#ifdef CCIO_MAP_STATS +#ifdef CCIO_COLLECT_STATS len += seq_printf(m, "IO PDIR entries : %ld free %ld used (%d%%)\n", total_pages - ioc->used_pages, ioc->used_pages, (int)(ioc->used_pages * 100 / total_pages)); @@ -1047,7 +1048,7 @@ static int ccio_proc_info(struct seq_file *m, void *p) len += seq_printf(m, "Resource bitmap : %d bytes (%d pages)\n", ioc->res_size, total_pages); -#ifdef CCIO_SEARCH_TIME +#ifdef CCIO_COLLECT_STATS min = max = ioc->avg_search[0]; for(j = 0; j < CCIO_SEARCH_SAMPLE; ++j) { avg += ioc->avg_search[j]; @@ -1059,8 +1060,7 @@ static int ccio_proc_info(struct seq_file *m, void *p) avg /= CCIO_SEARCH_SAMPLE; len += seq_printf(m, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", min, avg, max); -#endif -#ifdef CCIO_MAP_STATS + len += seq_printf(m, "pci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n", ioc->msingle_calls, ioc->msingle_pages, (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls)); @@ -1078,7 +1078,7 @@ static int ccio_proc_info(struct seq_file *m, void *p) len += seq_printf(m, "pci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n\n\n", ioc->usg_calls, ioc->usg_pages, (int)((ioc->usg_pages * 1000)/ioc->usg_calls)); -#endif /* CCIO_MAP_STATS */ +#endif /* CCIO_COLLECT_STATS */ ioc = ioc->next; } @@ -1091,7 +1091,7 @@ static int ccio_proc_info_open(struct inode *inode, struct file *file) return single_open(file, &ccio_proc_info, NULL); } -static struct file_operations ccio_proc_info_fops = { +static const struct file_operations ccio_proc_info_fops = { .owner = THIS_MODULE, .open = ccio_proc_info_open, .read = seq_read, @@ -1127,14 +1127,14 @@ static int ccio_proc_bitmap_open(struct inode *inode, struct file *file) return single_open(file, &ccio_proc_bitmap_info, NULL); } -static struct file_operations ccio_proc_bitmap_fops = { +static const struct file_operations ccio_proc_bitmap_fops = { .owner = THIS_MODULE, .open = ccio_proc_bitmap_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -#endif +#endif /* CONFIG_PROC_FS */ /** * ccio_find_ioc - Find the ioc in the ioc_list @@ -1215,7 +1215,7 @@ static int ccio_get_iotlb_size(struct parisc_device *dev) { if (dev->spa_shift == 0) { - panic("%s() : Can't determine I/O TLB size.\n", __FUNCTION__); + panic("%s() : Can't determine I/O TLB size.\n", __func__); } return (1 << dev->spa_shift); } @@ -1227,7 +1227,7 @@ ccio_get_iotlb_size(struct parisc_device *dev) #endif /* 0 */ /* We *can't* support JAVA (T600). Venture there at your own risk. */ -static struct parisc_device_id ccio_tbl[] = { +static const struct parisc_device_id ccio_tbl[] = { { HPHW_IOA, HVERSION_REV_ANY_ID, U2_IOA_RUNWAY, 0xb }, /* U2 */ { HPHW_IOA, HVERSION_REV_ANY_ID, UTURN_IOA_RUNWAY, 0xb }, /* UTurn */ { 0, } @@ -1242,10 +1242,10 @@ static struct parisc_driver ccio_driver = { }; /** - * ccio_ioc_init - Initalize the I/O Controller + * ccio_ioc_init - Initialize the I/O Controller * @ioc: The I/O Controller. * - * Initalize the I/O Controller which includes setting up the + * Initialize the I/O Controller which includes setting up the * I/O Page Directory, the resource map, and initalizing the * U2/Uturn chip into virtual mode. */ @@ -1267,7 +1267,7 @@ ccio_ioc_init(struct ioc *ioc) ** Hot-Plug/Removal of PCI cards. (aka PCI OLARD). */ - iova_space_size = (u32) (num_physpages / count_parisc_driver(&ccio_driver)); + iova_space_size = (u32) (totalram_pages / count_parisc_driver(&ccio_driver)); /* limit IOVA space size to 1MB-1GB */ @@ -1305,15 +1305,15 @@ ccio_ioc_init(struct ioc *ioc) BUG_ON((1 << get_order(ioc->pdir_size)) != (ioc->pdir_size >> PAGE_SHIFT)); DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits)\n", - __FUNCTION__, ioc->ioc_regs, - (unsigned long) num_physpages >> (20 - PAGE_SHIFT), + __func__, ioc->ioc_regs, + (unsigned long) totalram_pages >> (20 - PAGE_SHIFT), iova_space_size>>20, iov_order + PAGE_SHIFT); ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL, get_order(ioc->pdir_size)); if(NULL == ioc->pdir_base) { - panic("%s() could not allocate I/O Page Table\n", __FUNCTION__); + panic("%s() could not allocate I/O Page Table\n", __func__); } memset(ioc->pdir_base, 0, ioc->pdir_size); @@ -1322,12 +1322,12 @@ ccio_ioc_init(struct ioc *ioc) /* resource map size dictated by pdir_size */ ioc->res_size = (ioc->pdir_size / sizeof(u64)) >> 3; - DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, ioc->res_size); + DBG_INIT("%s() res_size 0x%x\n", __func__, ioc->res_size); ioc->res_map = (u8 *)__get_free_pages(GFP_KERNEL, get_order(ioc->res_size)); if(NULL == ioc->res_map) { - panic("%s() could not allocate resource map\n", __FUNCTION__); + panic("%s() could not allocate resource map\n", __func__); } memset(ioc->res_map, 0, ioc->res_size); @@ -1370,7 +1370,7 @@ ccio_ioc_init(struct ioc *ioc) } } -static void +static void __init ccio_init_resource(struct resource *res, char *name, void __iomem *ioaddr) { int result; @@ -1399,7 +1399,7 @@ ccio_init_resource(struct resource *res, char *name, void __iomem *ioaddr) result = insert_resource(&iomem_resource, res); if (result < 0) { printk(KERN_ERR "%s() failed to claim CCIO bus address space (%08lx,%08lx)\n", - __FUNCTION__, res->start, res->end); + __func__, (unsigned long)res->start, (unsigned long)res->end); } } @@ -1537,12 +1537,11 @@ int ccio_request_resource(const struct parisc_device *dev, * If so, initialize the chip and tell other partners in crime they * have work to do. */ -static int ccio_probe(struct parisc_device *dev) +static int __init ccio_probe(struct parisc_device *dev) { int i; struct ioc *ioc, **ioc_p = &ioc_list; - struct proc_dir_entry *info_entry, *bitmap_entry; - + ioc = kzalloc(sizeof(struct ioc), GFP_KERNEL); if (ioc == NULL) { printk(KERN_ERR MODULE_NAME ": memory allocation failure\n"); @@ -1551,7 +1550,8 @@ static int ccio_probe(struct parisc_device *dev) ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn"; - printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa.start); + printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, + (unsigned long)dev->hpa.start); for (i = 0; i < ioc_count; i++) { ioc_p = &(*ioc_p)->next; @@ -1568,27 +1568,23 @@ static int ccio_probe(struct parisc_device *dev) /* if this fails, no I/O cards will work, so may as well bug */ BUG_ON(dev->dev.platform_data == NULL); HBA_DATA(dev->dev.platform_data)->iommu = ioc; - - if (ioc_count == 0) { - info_entry = create_proc_entry(MODULE_NAME, 0, proc_runway_root); - if (info_entry) - info_entry->proc_fops = &ccio_proc_info_fops; - bitmap_entry = create_proc_entry(MODULE_NAME"-bitmap", 0, proc_runway_root); - if (bitmap_entry) - bitmap_entry->proc_fops = &ccio_proc_bitmap_fops; +#ifdef CONFIG_PROC_FS + if (ioc_count == 0) { + proc_create(MODULE_NAME, 0, proc_runway_root, + &ccio_proc_info_fops); + proc_create(MODULE_NAME"-bitmap", 0, proc_runway_root, + &ccio_proc_bitmap_fops); } - +#endif ioc_count++; - parisc_vmerge_boundary = IOVP_SIZE; - parisc_vmerge_max_size = BITS_PER_LONG * IOVP_SIZE; parisc_has_iommu(); return 0; } /** - * ccio_init - ccio initalization procedure. + * ccio_init - ccio initialization procedure. * * Register this driver. */ diff --git a/drivers/parisc/ccio-rm-dma.c b/drivers/parisc/ccio-rm-dma.c index 356b8357bcc..f78f6f1aef4 100644 --- a/drivers/parisc/ccio-rm-dma.c +++ b/drivers/parisc/ccio-rm-dma.c @@ -38,6 +38,7 @@ #include <linux/mm.h> #include <linux/string.h> #include <linux/pci.h> +#include <linux/gfp.h> #include <asm/uaccess.h> diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 0d96c50ffe9..9eae9834bcc 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -55,7 +55,6 @@ #include <asm/pdc.h> #include <asm/page.h> -#include <asm/system.h> #include <asm/io.h> #include <asm/hardware.h> @@ -175,12 +174,12 @@ static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) { struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3); void __iomem *base_addr = d->hba.base_addr; unsigned long flags; - DBG("%s: %p, %d, %d, %d\n", __FUNCTION__, base_addr, devfn, where, + DBG("%s: %p, %d, %d, %d\n", __func__, base_addr, devfn, where, size); spin_lock_irqsave(&d->dinosaur_pen, flags); @@ -210,12 +209,12 @@ static int dino_cfg_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) { struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3); void __iomem *base_addr = d->hba.base_addr; unsigned long flags; - DBG("%s: %p, %d, %d, %d\n", __FUNCTION__, base_addr, devfn, where, + DBG("%s: %p, %d, %d, %d\n", __func__, base_addr, devfn, where, size); spin_lock_irqsave(&d->dinosaur_pen, flags); @@ -287,7 +286,7 @@ DINO_PORT_OUT(b, 8, 3) DINO_PORT_OUT(w, 16, 2) DINO_PORT_OUT(l, 32, 0) -struct pci_port_ops dino_port_ops = { +static struct pci_port_ops dino_port_ops = { .inb = dino_in8, .inw = dino_in16, .inl = dino_in32, @@ -296,25 +295,25 @@ struct pci_port_ops dino_port_ops = { .outl = dino_out32 }; -static void dino_disable_irq(unsigned int irq) +static void dino_mask_irq(struct irq_data *d) { - struct dino_device *dino_dev = irq_desc[irq].chip_data; - int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS); + struct dino_device *dino_dev = irq_data_get_irq_chip_data(d); + int local_irq = gsc_find_local_irq(d->irq, dino_dev->global_irq, DINO_LOCAL_IRQS); - DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq); + DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, d->irq); /* Clear the matching bit in the IMR register */ dino_dev->imr &= ~(DINO_MASK_IRQ(local_irq)); __raw_writel(dino_dev->imr, dino_dev->hba.base_addr+DINO_IMR); } -static void dino_enable_irq(unsigned int irq) +static void dino_unmask_irq(struct irq_data *d) { - struct dino_device *dino_dev = irq_desc[irq].chip_data; - int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS); + struct dino_device *dino_dev = irq_data_get_irq_chip_data(d); + int local_irq = gsc_find_local_irq(d->irq, dino_dev->global_irq, DINO_LOCAL_IRQS); u32 tmp; - DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq); + DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, d->irq); /* ** clear pending IRQ bits @@ -340,25 +339,15 @@ static void dino_enable_irq(unsigned int irq) tmp = __raw_readl(dino_dev->hba.base_addr+DINO_ILR); if (tmp & DINO_MASK_IRQ(local_irq)) { DBG(KERN_WARNING "%s(): IRQ asserted! (ILR 0x%x)\n", - __FUNCTION__, tmp); + __func__, tmp); gsc_writel(dino_dev->txn_data, dino_dev->txn_addr); } } -static unsigned int dino_startup_irq(unsigned int irq) -{ - dino_enable_irq(irq); - return 0; -} - -static struct hw_interrupt_type dino_interrupt_type = { - .typename = "GSC-PCI", - .startup = dino_startup_irq, - .shutdown = dino_disable_irq, - .enable = dino_enable_irq, - .disable = dino_disable_irq, - .ack = no_ack_irq, - .end = no_end_irq, +static struct irq_chip dino_interrupt_type = { + .name = "GSC-PCI", + .irq_unmask = dino_unmask_irq, + .irq_mask = dino_mask_irq, }; @@ -368,8 +357,7 @@ static struct hw_interrupt_type dino_interrupt_type = { * ilr_loop counter is a kluge to prevent a "stuck" IRQ line from * wedging the CPU. Could be removed or made optional at some point. */ -static irqreturn_t -dino_isr(int irq, void *intr_dev, struct pt_regs *regs) +static irqreturn_t dino_isr(int irq, void *intr_dev) { struct dino_device *dino_dev = intr_dev; u32 mask; @@ -389,8 +377,8 @@ ilr_again: int local_irq = __ffs(mask); int irq = dino_dev->global_irq[local_irq]; DBG(KERN_DEBUG "%s(%d, %p) mask 0x%x\n", - __FUNCTION__, irq, intr_dev, mask); - __do_IRQ(irq, regs); + __func__, irq, intr_dev, mask); + generic_handle_irq(irq); mask &= ~(1 << local_irq); } while (mask); @@ -442,7 +430,7 @@ static void dino_choose_irq(struct parisc_device *dev, void *ctrl) * Cirrus 6832 Cardbus reports wrong irq on RDI Tadpole PARISC Laptop (deller@gmx.de) * (the irqs are off-by-one, not sure yet if this is a cirrus, dino-hardware or dino-driver problem...) */ -static void __devinit quirk_cirrus_cardbus(struct pci_dev *dev) +static void quirk_cirrus_cardbus(struct pci_dev *dev) { u8 new_irq = dev->irq - 1; printk(KERN_INFO "PCI: Cirrus Cardbus IRQ fixup for %s, from %d to %d\n", @@ -478,7 +466,7 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr) res = &dino_dev->hba.lmmio_space; res->flags = IORESOURCE_MEM; size = scnprintf(name, sizeof(name), "Dino LMMIO (%s)", - bus->bridge->bus_id); + dev_name(bus->bridge)); res->name = kmalloc(size+1, GFP_KERNEL); if(res->name) strcpy((char *)res->name, name); @@ -489,15 +477,12 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr) if (ccio_allocate_resource(dino_dev->hba.dev, res, _8MB, F_EXTEND(0xf0000000UL) | _8MB, F_EXTEND(0xffffffffUL) &~ _8MB, _8MB) < 0) { - struct list_head *ln, *tmp_ln; + struct pci_dev *dev, *tmp; printk(KERN_ERR "Dino: cannot attach bus %s\n", - bus->bridge->bus_id); + dev_name(bus->bridge)); /* kill the bus, we can't do anything with it */ - list_for_each_safe(ln, tmp_ln, &bus->devices) { - struct pci_dev *dev = pci_dev_b(ln); - - list_del(&dev->global_list); + list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { list_del(&dev->bus_list); } @@ -547,7 +532,7 @@ dino_card_fixup(struct pci_dev *dev) ** The additional "-1" adjusts for skewing the IRQ<->slot. */ dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 1, &irq_pin); - dev->irq = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ; + dev->irq = pci_swizzle_interrupt_pin(dev, irq_pin) - 1; /* Shouldn't really need to do this but it's in case someone tries ** to bypass PCI services and look at the card themselves. @@ -562,32 +547,17 @@ dino_card_fixup(struct pci_dev *dev) static void __init dino_fixup_bus(struct pci_bus *bus) { - struct list_head *ln; struct pci_dev *dev; struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge)); - int port_base = HBA_PORT_BASE(dino_dev->hba.hba_num); DBG(KERN_WARNING "%s(0x%p) bus %d platform_data 0x%p\n", - __FUNCTION__, bus, bus->secondary, + __func__, bus, bus->busn_res.start, bus->bridge->platform_data); /* Firmware doesn't set up card-mode dino, so we have to */ if (is_card_dino(&dino_dev->hba.dev->id)) { dino_card_setup(bus, dino_dev->hba.base_addr); - } else if(bus->parent == NULL) { - /* must have a dino above it, reparent the resources - * into the dino window */ - int i; - struct resource *res = &dino_dev->hba.lmmio_space; - - bus->resource[0] = &(dino_dev->hba.io_space); - for(i = 0; i < DINO_MAX_LMMIO_RESOURCES; i++) { - if(res[i].flags == 0) - break; - bus->resource[i+1] = &res[i]; - } - - } else if(bus->self) { + } else if (bus->parent) { int i; pci_read_bridge_bases(bus); @@ -610,23 +580,18 @@ dino_fixup_bus(struct pci_bus *bus) } - DBG("DEBUG %s assigning %d [0x%lx,0x%lx]\n", - bus->self->dev.bus_id, i, - bus->self->resource[i].start, - bus->self->resource[i].end); - pci_assign_resource(bus->self, i); - DBG("DEBUG %s after assign %d [0x%lx,0x%lx]\n", - bus->self->dev.bus_id, i, - bus->self->resource[i].start, - bus->self->resource[i].end); + DBG("DEBUG %s assigning %d [%pR]\n", + dev_name(&bus->self->dev), i, + &bus->self->resource[i]); + WARN_ON(pci_assign_resource(bus->self, i)); + DBG("DEBUG %s after assign %d [%pR]\n", + dev_name(&bus->self->dev), i, + &bus->self->resource[i]); } } - list_for_each(ln, &bus->devices) { - int i; - - dev = pci_dev_b(ln); + list_for_each_entry(dev, &bus->devices, bus_list) { if (is_card_dino(&dino_dev->hba.dev->id)) dino_card_fixup(dev); @@ -637,21 +602,6 @@ dino_fixup_bus(struct pci_bus *bus) if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) continue; - /* Adjust the I/O Port space addresses */ - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *res = &dev->resource[i]; - if (res->flags & IORESOURCE_IO) { - res->start |= port_base; - res->end |= port_base; - } -#ifdef __LP64__ - /* Sign Extend MMIO addresses */ - else if (res->flags & IORESOURCE_MEM) { - res->start |= F_EXTEND(0UL); - res->end |= F_EXTEND(0UL); - } -#endif - } /* null out the ROM resource if there is one (we don't * care about an expansion rom on parisc, since it * usually contains (x86) bios code) */ @@ -672,7 +622,7 @@ dino_fixup_bus(struct pci_bus *bus) dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 1, &irq_pin); - irq_pin = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ; + irq_pin = pci_swizzle_interrupt_pin(dev, irq_pin) - 1; printk(KERN_WARNING "Device %s has undefined IRQ, " "setting to %d\n", pci_name(dev), irq_pin); dino_cfg_write(dev->bus, dev->devfn, @@ -690,7 +640,7 @@ dino_fixup_bus(struct pci_bus *bus) } -struct pci_bios_ops dino_bios_ops = { +static struct pci_bios_ops dino_bios_ops = { .init = dino_bios_init, .fixup_bus = dino_fixup_bus }; @@ -819,7 +769,8 @@ dino_bridge_init(struct dino_device *dino_dev, const char *name) result = ccio_request_resource(dino_dev->hba.dev, &res[i]); if (result < 0) { - printk(KERN_ERR "%s: failed to claim PCI Bus address space %d (0x%lx-0x%lx)!\n", name, i, res[i].start, res[i].end); + printk(KERN_ERR "%s: failed to claim PCI Bus address " + "space %d (%pR)!\n", name, i, &res[i]); return result; } } @@ -899,7 +850,8 @@ static int __init dino_common_init(struct parisc_device *dev, if (request_resource(&ioport_resource, res) < 0) { printk(KERN_ERR "%s: request I/O Port region failed " "0x%lx/%lx (hpa 0x%p)\n", - name, res->start, res->end, dino_dev->hba.base_addr); + name, (unsigned long)res->start, (unsigned long)res->end, + dino_dev->hba.base_addr); return 1; } @@ -936,8 +888,10 @@ static int __init dino_probe(struct parisc_device *dev) const char *version = "unknown"; char *name; int is_cujo = 0; + LIST_HEAD(resources); struct pci_bus *bus; unsigned long hpa = dev->hpa.start; + int max; name = "Dino"; if (is_card_dino(&dev->id)) { @@ -1012,25 +966,45 @@ static int __init dino_probe(struct parisc_device *dev) dev->dev.platform_data = dino_dev; + pci_add_resource_offset(&resources, &dino_dev->hba.io_space, + HBA_PORT_BASE(dino_dev->hba.hba_num)); + if (dino_dev->hba.lmmio_space.flags) + pci_add_resource_offset(&resources, &dino_dev->hba.lmmio_space, + dino_dev->hba.lmmio_space_offset); + if (dino_dev->hba.elmmio_space.flags) + pci_add_resource_offset(&resources, &dino_dev->hba.elmmio_space, + dino_dev->hba.lmmio_space_offset); + if (dino_dev->hba.gmmio_space.flags) + pci_add_resource(&resources, &dino_dev->hba.gmmio_space); + + dino_dev->hba.bus_num.start = dino_current_bus; + dino_dev->hba.bus_num.end = 255; + dino_dev->hba.bus_num.flags = IORESOURCE_BUS; + pci_add_resource(&resources, &dino_dev->hba.bus_num); /* ** It's not used to avoid chicken/egg problems ** with configuration accessor functions. */ - bus = pci_scan_bus_parented(&dev->dev, dino_current_bus, - &dino_cfg_ops, NULL); - if(bus) { - pci_bus_add_devices(bus); - /* This code *depends* on scanning being single threaded - * if it isn't, this global bus number count will fail - */ - dino_current_bus = bus->subordinate + 1; - pci_bus_assign_resources(bus); - } else { - printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", dev->dev.bus_id, dino_current_bus); + dino_dev->hba.hba_bus = bus = pci_create_root_bus(&dev->dev, + dino_current_bus, &dino_cfg_ops, NULL, &resources); + if (!bus) { + printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n", + dev_name(&dev->dev), dino_current_bus); + pci_free_resource_list(&resources); /* increment the bus number in case of duplicates */ dino_current_bus++; + return 0; } - dino_dev->hba.hba_bus = bus; + + max = pci_scan_child_bus(bus); + pci_bus_update_busn_res_end(bus, max); + + /* This code *depends* on scanning being single threaded + * if it isn't, this global bus number count will fail + */ + dino_current_bus = max + 1; + pci_bus_assign_resources(bus); + pci_bus_add_devices(bus); return 0; } diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index 884965cedec..103095bbe8c 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c @@ -33,7 +33,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> -#include <linux/sched.h> #include <linux/spinlock.h> #include <linux/eisa.h> @@ -145,8 +144,9 @@ static unsigned int eisa_irq_level __read_mostly; /* default to edge triggered * /* called by free irq */ -static void eisa_disable_irq(unsigned int irq) +static void eisa_mask_irq(struct irq_data *d) { + unsigned int irq = d->irq; unsigned long flags; EISA_DBG("disable irq %d\n", irq); @@ -165,8 +165,9 @@ static void eisa_disable_irq(unsigned int irq) } /* called by request irq */ -static void eisa_enable_irq(unsigned int irq) +static void eisa_unmask_irq(struct irq_data *d) { + unsigned int irq = d->irq; unsigned long flags; EISA_DBG("enable irq %d\n", irq); @@ -183,23 +184,13 @@ static void eisa_enable_irq(unsigned int irq) EISA_DBG("pic1 mask %02x\n", eisa_in8(0xa1)); } -static unsigned int eisa_startup_irq(unsigned int irq) -{ - eisa_enable_irq(irq); - return 0; -} - -static struct hw_interrupt_type eisa_interrupt_type = { - .typename = "EISA", - .startup = eisa_startup_irq, - .shutdown = eisa_disable_irq, - .enable = eisa_enable_irq, - .disable = eisa_disable_irq, - .ack = no_ack_irq, - .end = no_end_irq, +static struct irq_chip eisa_interrupt_type = { + .name = "EISA", + .irq_unmask = eisa_unmask_irq, + .irq_mask = eisa_mask_irq, }; -static irqreturn_t eisa_irq(int wax_irq, void *intr_dev, struct pt_regs *regs) +static irqreturn_t eisa_irq(int wax_irq, void *intr_dev) { int irq = gsc_readb(0xfc01f000); /* EISA supports 16 irqs */ unsigned long flags; @@ -234,7 +225,7 @@ static irqreturn_t eisa_irq(int wax_irq, void *intr_dev, struct pt_regs *regs) } spin_unlock_irqrestore(&eisa_irq_lock, flags); - __do_IRQ(irq, regs); + generic_handle_irq(irq); spin_lock_irqsave(&eisa_irq_lock, flags); /* unmask */ @@ -249,7 +240,7 @@ static irqreturn_t eisa_irq(int wax_irq, void *intr_dev, struct pt_regs *regs) return IRQ_HANDLED; } -static irqreturn_t dummy_irq2_handler(int _, void *dev, struct pt_regs *regs) +static irqreturn_t dummy_irq2_handler(int _, void *dev) { printk(KERN_ALERT "eisa: uhh, irq2?\n"); return IRQ_HANDLED; @@ -308,14 +299,14 @@ static void init_eisa_pic(void) #define is_mongoose(dev) (dev->id.sversion == 0x00076) -static int __devinit eisa_probe(struct parisc_device *dev) +static int __init eisa_probe(struct parisc_device *dev) { int i, result; char *name = is_mongoose(dev) ? "Mongoose" : "Wax"; printk(KERN_INFO "%s EISA Adapter found at 0x%08lx\n", - name, dev->hpa.start); + name, (unsigned long)dev->hpa.start); eisa_dev.hba.dev = dev; eisa_dev.hba.iommu = ccio_get_iommu(dev); @@ -347,10 +338,10 @@ static int __devinit eisa_probe(struct parisc_device *dev) } /* Reserve IRQ2 */ - irq_desc[2].action = &irq2_action; - + setup_irq(2, &irq2_action); for (i = 0; i < 16; i++) { - irq_desc[i].chip = &eisa_interrupt_type; + irq_set_chip_and_handler(i, &eisa_interrupt_type, + handle_simple_irq); } EISA_bus = 1; @@ -374,7 +365,7 @@ static int __devinit eisa_probe(struct parisc_device *dev) if (result >= 0) { /* FIXME : Don't enumerate the bus twice. */ eisa_dev.root.dev = &dev->dev; - dev->dev.driver_data = &eisa_dev.root; + dev_set_drvdata(&dev->dev, &eisa_dev.root); eisa_dev.root.bus_base_addr = 0; eisa_dev.root.res = &eisa_dev.hba.io_space; eisa_dev.root.slots = result; @@ -388,7 +379,7 @@ static int __devinit eisa_probe(struct parisc_device *dev) return 0; } -static struct parisc_device_id eisa_tbl[] = { +static const struct parisc_device_id eisa_tbl[] = { { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00076 }, /* Mongoose */ { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00090 }, /* Wax EISA */ { 0, } diff --git a/drivers/parisc/eisa_eeprom.c b/drivers/parisc/eisa_eeprom.c index e13aafa70bf..783906fe659 100644 --- a/drivers/parisc/eisa_eeprom.c +++ b/drivers/parisc/eisa_eeprom.c @@ -31,20 +31,9 @@ #define EISA_EEPROM_MINOR 241 -static loff_t eisa_eeprom_llseek(struct file *file, loff_t offset, int origin ) +static loff_t eisa_eeprom_llseek(struct file *file, loff_t offset, int origin) { - switch (origin) { - case 0: - /* nothing to do */ - break; - case 1: - offset += file->f_pos; - break; - case 2: - offset += HPEE_MAX_LENGTH; - break; - } - return (offset >= 0 && offset < HPEE_MAX_LENGTH) ? (file->f_pos = offset) : -EINVAL; + return fixed_size_llseek(file, offset, origin, HPEE_MAX_LENGTH); } static ssize_t eisa_eeprom_read(struct file * file, @@ -54,7 +43,7 @@ static ssize_t eisa_eeprom_read(struct file * file, ssize_t ret; int i; - if (*ppos >= HPEE_MAX_LENGTH) + if (*ppos < 0 || *ppos >= HPEE_MAX_LENGTH) return 0; count = *ppos + count < HPEE_MAX_LENGTH ? count : HPEE_MAX_LENGTH - *ppos; @@ -74,16 +63,9 @@ static ssize_t eisa_eeprom_read(struct file * file, return ret; } -static int eisa_eeprom_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, - unsigned long arg) -{ - return -ENOTTY; -} - static int eisa_eeprom_open(struct inode *inode, struct file *file) { - if (file->f_mode & 2) + if (file->f_mode & FMODE_WRITE) return -EINVAL; return 0; @@ -97,11 +79,10 @@ static int eisa_eeprom_release(struct inode *inode, struct file *file) /* * The various file operations we support. */ -static struct file_operations eisa_eeprom_fops = { +static const struct file_operations eisa_eeprom_fops = { .owner = THIS_MODULE, .llseek = eisa_eeprom_llseek, .read = eisa_eeprom_read, - .ioctl = eisa_eeprom_ioctl, .open = eisa_eeprom_open, .release = eisa_eeprom_release, }; diff --git a/drivers/parisc/eisa_enumerator.c b/drivers/parisc/eisa_enumerator.c index 6d8aae003f6..caa15313375 100644 --- a/drivers/parisc/eisa_enumerator.c +++ b/drivers/parisc/eisa_enumerator.c @@ -98,10 +98,10 @@ static int configure_memory(const unsigned char *buf, res->start = mem_parent->start + get_24(buf+len+2); res->end = res->start + get_16(buf+len+5)*1024; res->flags = IORESOURCE_MEM; - printk("memory %lx-%lx ", res->start, res->end); + printk("memory %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end); result = request_resource(mem_parent, res); if (result < 0) { - printk("\n" KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); + printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); return result; } } @@ -188,10 +188,10 @@ static int configure_port(const unsigned char *buf, struct resource *io_parent, res->start = get_16(buf+len+1); res->end = get_16(buf+len+1)+(c&HPEE_PORT_SIZE_MASK)+1; res->flags = IORESOURCE_IO; - printk("ioports %lx-%lx ", res->start, res->end); + printk("ioports %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end); result = request_resource(io_parent, res); if (result < 0) { - printk("\n" KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); + printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); return result; } } @@ -224,7 +224,7 @@ static int configure_port_init(const unsigned char *buf) case HPEE_PORT_INIT_WIDTH_BYTE: s=1; if (c & HPEE_PORT_INIT_MASK) { - printk("\n" KERN_WARNING "port_init: unverified mask attribute\n"); + printk(KERN_WARNING "port_init: unverified mask attribute\n"); outb((inb(get_16(buf+len+1) & get_8(buf+len+3)) | get_8(buf+len+4)), get_16(buf+len+1)); @@ -249,7 +249,7 @@ static int configure_port_init(const unsigned char *buf) case HPEE_PORT_INIT_WIDTH_DWORD: s=4; if (c & HPEE_PORT_INIT_MASK) { - printk("\n" KERN_WARNING "port_init: unverified mask attribute\n"); + printk(KERN_WARNING "port_init: unverified mask attribute\n"); outl((inl(get_16(buf+len+1) & get_32(buf+len+3)) | get_32(buf+len+7)), get_16(buf+len+1)); @@ -259,7 +259,7 @@ static int configure_port_init(const unsigned char *buf) break; default: - printk("\n" KERN_ERR "Invalid port init word %02x\n", c); + printk(KERN_ERR "Invalid port init word %02x\n", c); return 0; } @@ -297,7 +297,7 @@ static int configure_type_string(const unsigned char *buf) /* just skip past the type field */ len = get_8(buf); if (len > 80) { - printk("\n" KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len); + printk(KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len); } return 1+len; @@ -398,7 +398,7 @@ static int parse_slot_config(int slot, } if (p0 + function_len < pos) { - printk("\n" KERN_ERR "eisa_enumerator: function %d length mis-match " + printk(KERN_ERR "eisa_enumerator: function %d length mis-match " "got %d, expected %d\n", num_func, pos-p0, function_len); res=-1; @@ -460,7 +460,7 @@ static int init_slot(int slot, struct eeprom_eisa_slot_info *es) slot, id_string); print_eisa_id(id_string, es->eisa_slot_id); - printk(" expected %s \n", id_string); + printk(" expected %s\n", id_string); return -1; diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index b45aa5c675a..1bab5a2cd35 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c @@ -19,7 +19,6 @@ #include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/module.h> -#include <linux/slab.h> #include <linux/types.h> #include <asm/hardware.h> @@ -73,7 +72,7 @@ EXPORT_SYMBOL(gsc_alloc_irq); EXPORT_SYMBOL(gsc_claim_irq); /* Common interrupt demultiplexer used by Asp, Lasi & Wax. */ -irqreturn_t gsc_asic_intr(int gsc_asic_irq, void *dev, struct pt_regs *regs) +irqreturn_t gsc_asic_intr(int gsc_asic_irq, void *dev) { unsigned long irr; struct gsc_asic *gsc_asic = dev; @@ -87,7 +86,7 @@ irqreturn_t gsc_asic_intr(int gsc_asic_irq, void *dev, struct pt_regs *regs) do { int local_irq = __ffs(irr); unsigned int irq = gsc_asic->global_irq[local_irq]; - __do_IRQ(irq, regs); + generic_handle_irq(irq); irr &= ~(1 << local_irq); } while (irr); @@ -106,13 +105,13 @@ int gsc_find_local_irq(unsigned int irq, int *global_irqs, int limit) return NO_IRQ; } -static void gsc_asic_disable_irq(unsigned int irq) +static void gsc_asic_mask_irq(struct irq_data *d) { - struct gsc_asic *irq_dev = irq_desc[irq].chip_data; - int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32); + struct gsc_asic *irq_dev = irq_data_get_irq_chip_data(d); + int local_irq = gsc_find_local_irq(d->irq, irq_dev->global_irq, 32); u32 imr; - DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __FUNCTION__, irq, + DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, d->irq, irq_dev->name, imr); /* Disable the IRQ line by clearing the bit in the IMR */ @@ -121,13 +120,13 @@ static void gsc_asic_disable_irq(unsigned int irq) gsc_writel(imr, irq_dev->hpa + OFFSET_IMR); } -static void gsc_asic_enable_irq(unsigned int irq) +static void gsc_asic_unmask_irq(struct irq_data *d) { - struct gsc_asic *irq_dev = irq_desc[irq].chip_data; - int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32); + struct gsc_asic *irq_dev = irq_data_get_irq_chip_data(d); + int local_irq = gsc_find_local_irq(d->irq, irq_dev->global_irq, 32); u32 imr; - DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __FUNCTION__, irq, + DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, d->irq, irq_dev->name, imr); /* Enable the IRQ line by setting the bit in the IMR */ @@ -140,31 +139,22 @@ static void gsc_asic_enable_irq(unsigned int irq) */ } -static unsigned int gsc_asic_startup_irq(unsigned int irq) -{ - gsc_asic_enable_irq(irq); - return 0; -} - -static struct hw_interrupt_type gsc_asic_interrupt_type = { - .typename = "GSC-ASIC", - .startup = gsc_asic_startup_irq, - .shutdown = gsc_asic_disable_irq, - .enable = gsc_asic_enable_irq, - .disable = gsc_asic_disable_irq, - .ack = no_ack_irq, - .end = no_end_irq, +static struct irq_chip gsc_asic_interrupt_type = { + .name = "GSC-ASIC", + .irq_unmask = gsc_asic_unmask_irq, + .irq_mask = gsc_asic_mask_irq, }; -int gsc_assign_irq(struct hw_interrupt_type *type, void *data) +int gsc_assign_irq(struct irq_chip *type, void *data) { static int irq = GSC_IRQ_BASE; if (irq > GSC_IRQ_MAX) return NO_IRQ; - irq_desc[irq].chip = type; - irq_desc[irq].chip_data = data; + irq_set_chip_and_handler(irq, type, handle_simple_irq); + irq_set_chip_data(irq, data); + return irq++; } @@ -182,29 +172,34 @@ void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp) *irqp = irq; } -static struct device *next_device(struct klist_iter *i) +struct gsc_fixup_struct { + void (*choose_irq)(struct parisc_device *, void *); + void *ctrl; +}; + +static int gsc_fixup_irqs_callback(struct device *dev, void *data) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; + struct parisc_device *padev = to_parisc_device(dev); + struct gsc_fixup_struct *gf = data; + + /* work-around for 715/64 and others which have parent + at path [5] and children at path [5/0/x] */ + if (padev->id.hw_type == HPHW_FAULTY) + gsc_fixup_irqs(padev, gf->ctrl, gf->choose_irq); + gf->choose_irq(padev, gf->ctrl); + + return 0; } void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl, void (*choose_irq)(struct parisc_device *, void *)) { - struct device *dev; - struct klist_iter i; - - klist_iter_init(&parent->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *padev = to_parisc_device(dev); - - /* work-around for 715/64 and others which have parent - at path [5] and children at path [5/0/x] */ - if (padev->id.hw_type == HPHW_FAULTY) - return gsc_fixup_irqs(padev, ctrl, choose_irq); - choose_irq(padev, ctrl); - } - klist_iter_exit(&i); + struct gsc_fixup_struct data = { + .choose_irq = choose_irq, + .ctrl = ctrl, + }; + + device_for_each_child(&parent->dev, &data, gsc_fixup_irqs_callback); } int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic) diff --git a/drivers/parisc/gsc.h b/drivers/parisc/gsc.h index a3dc456709d..b9d7bfb68e2 100644 --- a/drivers/parisc/gsc.h +++ b/drivers/parisc/gsc.h @@ -38,10 +38,10 @@ struct gsc_asic { int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic); int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */ int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */ -int gsc_assign_irq(struct hw_interrupt_type *type, void *data); +int gsc_assign_irq(struct irq_chip *type, void *data); int gsc_find_local_irq(unsigned int irq, int *global_irq, int limit); void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl, void (*choose)(struct parisc_device *child, void *ctrl)); void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp); -irqreturn_t gsc_asic_intr(int irq, void *dev, struct pt_regs *regs); +irqreturn_t gsc_asic_intr(int irq, void *dev); diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c index 07dc2b6d4e9..898208e4f30 100644 --- a/drivers/parisc/hppb.c +++ b/drivers/parisc/hppb.c @@ -10,31 +10,26 @@ ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** -** This Driver currently only supports the console (port 0) on the MUX. -** Additional work will be needed on this driver to enable the full -** functionality of the MUX. -** */ #include <linux/types.h> #include <linux/init.h> #include <linux/mm.h> #include <linux/slab.h> +#include <linux/dma-mapping.h> #include <linux/ioport.h> #include <asm/io.h> #include <asm/hardware.h> #include <asm/parisc-device.h> -#include <linux/pci.h> - struct hppb_card { unsigned long hpa; struct resource mmio_region; struct hppb_card *next; }; -struct hppb_card hppb_card_head = { +static struct hppb_card hppb_card_head = { .hpa = 0, .next = NULL, }; @@ -67,7 +62,8 @@ static int hppb_probe(struct parisc_device *dev) } card = card->next; } - printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa.start); + printk(KERN_INFO "Found GeckoBoa at 0x%llx\n", + (unsigned long long) dev->hpa.start); card->hpa = dev->hpa.start; card->mmio_region.name = "HP-PB Bus"; @@ -78,16 +74,18 @@ static int hppb_probe(struct parisc_device *dev) status = ccio_request_resource(dev, &card->mmio_region); if(status < 0) { - printk(KERN_ERR "%s: failed to claim HP-PB bus space (%08lx, %08lx)\n", - __FILE__, card->mmio_region.start, card->mmio_region.end); + printk(KERN_ERR "%s: failed to claim HP-PB bus space (%pR)\n", + __FILE__, &card->mmio_region); } return 0; } - static struct parisc_device_id hppb_tbl[] = { - { HPHW_BCPORT, HVERSION_REV_ANY_ID, 0x500, 0xc }, + { HPHW_BCPORT, HVERSION_REV_ANY_ID, 0x500, 0xc }, /* E25 and K */ + { HPHW_BCPORT, 0x0, 0x501, 0xc }, /* E35 */ + { HPHW_BCPORT, 0x0, 0x502, 0xc }, /* E45 */ + { HPHW_BCPORT, 0x0, 0x503, 0xc }, /* E55 */ { 0, } }; @@ -98,7 +96,7 @@ static struct parisc_driver hppb_driver = { }; /** - * hppb_init - HP-PB bus initalization procedure. + * hppb_init - HP-PB bus initialization procedure. * * Register this driver. */ diff --git a/drivers/parisc/iommu-helpers.h b/drivers/parisc/iommu-helpers.h index 38d9e1aba1d..8c33491b21f 100644 --- a/drivers/parisc/iommu-helpers.h +++ b/drivers/parisc/iommu-helpers.h @@ -1,3 +1,5 @@ +#include <linux/prefetch.h> + /** * iommu_fill_pdir - Insert coalesced scatter/gather chunks into the I/O Pdir. * @ioc: The I/O Controller. @@ -95,12 +97,14 @@ iommu_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents, */ static inline unsigned int -iommu_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg, int nents, - int (*iommu_alloc_range)(struct ioc *, size_t)) +iommu_coalesce_chunks(struct ioc *ioc, struct device *dev, + struct scatterlist *startsg, int nents, + int (*iommu_alloc_range)(struct ioc *, struct device *, size_t)) { struct scatterlist *contig_sg; /* contig chunk head */ unsigned long dma_offset, dma_len; /* start/len of DMA stream */ unsigned int n_mappings = 0; + unsigned int max_seg_size = dma_get_max_seg_size(dev); while (nents > 0) { @@ -138,10 +142,13 @@ iommu_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg, int nents, ** exceed DMA_CHUNK_SIZE if we coalesce the ** next entry. */ - if(unlikely(ROUNDUP(dma_len + dma_offset + startsg->length, + if(unlikely(ALIGN(dma_len + dma_offset + startsg->length, IOVP_SIZE) > DMA_CHUNK_SIZE)) break; + if (startsg->length + dma_len > max_seg_size) + break; + /* ** Next see if we can append the next chunk (i.e. ** it must end on one page and begin on another @@ -158,10 +165,10 @@ iommu_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg, int nents, ** Allocate space for DMA stream. */ sg_dma_len(contig_sg) = dma_len; - dma_len = ROUNDUP(dma_len + dma_offset, IOVP_SIZE); + dma_len = ALIGN(dma_len + dma_offset, IOVP_SIZE); sg_dma_address(contig_sg) = PIDE_FLAG - | (iommu_alloc_range(ioc, dma_len) << IOVP_SHIFT) + | (iommu_alloc_range(ioc, dev, dma_len) << IOVP_SHIFT) | dma_offset; n_mappings++; } diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 1fbda77cefc..9ee04b4b68b 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -50,12 +50,12 @@ ** ** PA Firmware ** ----------- -** PA-RISC platforms have two fundementally different types of firmware. +** PA-RISC platforms have two fundamentally different types of firmware. ** For PCI devices, "Legacy" PDC initializes the "INTERRUPT_LINE" register ** and BARs similar to a traditional PC BIOS. ** The newer "PAT" firmware supports PDC calls which return tables. -** PAT firmware only initializes PCI Console and Boot interface. -** With these tables, the OS can progam all other PCI devices. +** PAT firmware only initializes the PCI Console and Boot interface. +** With these tables, the OS can program all other PCI devices. ** ** One such PAT PDC call returns the "Interrupt Routing Table" (IRT). ** The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC @@ -140,14 +140,13 @@ #include <asm/pdc.h> #include <asm/pdcpat.h> #include <asm/page.h> -#include <asm/system.h> #include <asm/io.h> /* read/write functions */ #ifdef CONFIG_SUPERIO #include <asm/superio.h> #endif -#include <asm/iosapic.h> -#include "./iosapic_private.h" +#include <asm/ropes.h> +#include "iosapic_private.h" #define MODULE_NAME "iosapic" @@ -487,7 +486,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) } /* Check if pcidev behind a PPB */ - if (NULL != pcidev->bus->self) { + if (pcidev->bus->parent) { /* Convert pcidev INTR_PIN into something we ** can lookup in the IRT. */ @@ -519,15 +518,13 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) ** ** Advantage is it's really easy to implement. */ - intr_pin = ((intr_pin-1)+PCI_SLOT(pcidev->devfn)) % 4; - intr_pin++; /* convert back to INTA-D (1-4) */ + intr_pin = pci_swizzle_interrupt_pin(pcidev, intr_pin); #endif /* PCI_BRIDGE_FUNCS */ /* - ** Locate the host slot the PPB nearest the Host bus - ** adapter. - */ - while (NULL != p->parent->self) + * Locate the host slot of the PPB. + */ + while (p->parent->parent) p = p->parent; intr_slot = PCI_SLOT(p->self->devfn); @@ -535,7 +532,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) intr_slot = PCI_SLOT(pcidev->devfn); } DBG_IRT("iosapic_xlate_pin: bus %d slot %d pin %d\n", - pcidev->bus->secondary, intr_slot, intr_pin); + pcidev->bus->busn_res.start, intr_slot, intr_pin); return irt_find_irqline(isi, intr_slot, intr_pin); } @@ -617,15 +614,10 @@ iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1) } -static struct vector_info *iosapic_get_vector(unsigned int irq) -{ - return irq_desc[irq].chip_data; -} - -static void iosapic_disable_irq(unsigned int irq) +static void iosapic_mask_irq(struct irq_data *d) { unsigned long flags; - struct vector_info *vi = iosapic_get_vector(irq); + struct vector_info *vi = irq_data_get_irq_chip_data(d); u32 d0, d1; spin_lock_irqsave(&iosapic_lock, flags); @@ -635,9 +627,9 @@ static void iosapic_disable_irq(unsigned int irq) spin_unlock_irqrestore(&iosapic_lock, flags); } -static void iosapic_enable_irq(unsigned int irq) +static void iosapic_unmask_irq(struct irq_data *d) { - struct vector_info *vi = iosapic_get_vector(irq); + struct vector_info *vi = irq_data_get_irq_chip_data(d); u32 d0, d1; /* data is initialized by fixup_irq */ @@ -673,44 +665,34 @@ printk("\n"); * enables their IRQ. It can lead to "interesting" race conditions * in the driver initialization sequence. */ - DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", irq, + DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", d->irq, vi->eoi_addr, vi->eoi_data); iosapic_eoi(vi->eoi_addr, vi->eoi_data); } -/* - * PARISC only supports PCI devices below I/O SAPIC. - * PCI only supports level triggered in order to share IRQ lines. - * ergo I/O SAPIC must always issue EOI on parisc. - * - * i386/ia64 support ISA devices and have to deal with - * edge-triggered interrupts too. - */ -static void iosapic_end_irq(unsigned int irq) +static void iosapic_eoi_irq(struct irq_data *d) { - struct vector_info *vi = iosapic_get_vector(irq); - DBG(KERN_DEBUG "end_irq(%d): eoi(%p, 0x%x)\n", irq, - vi->eoi_addr, vi->eoi_data); - iosapic_eoi(vi->eoi_addr, vi->eoi_data); -} + struct vector_info *vi = irq_data_get_irq_chip_data(d); -static unsigned int iosapic_startup_irq(unsigned int irq) -{ - iosapic_enable_irq(irq); - return 0; + iosapic_eoi(vi->eoi_addr, vi->eoi_data); + cpu_eoi_irq(d); } #ifdef CONFIG_SMP -static void iosapic_set_affinity_irq(unsigned int irq, cpumask_t dest) +static int iosapic_set_affinity_irq(struct irq_data *d, + const struct cpumask *dest, bool force) { - struct vector_info *vi = iosapic_get_vector(irq); + struct vector_info *vi = irq_data_get_irq_chip_data(d); u32 d0, d1, dummy_d0; unsigned long flags; + int dest_cpu; - if (cpu_check_affinity(irq, &dest)) - return; + dest_cpu = cpu_check_affinity(d, dest); + if (dest_cpu < 0) + return -1; - vi->txn_addr = txn_affinity_addr(irq, first_cpu(dest)); + cpumask_copy(d->affinity, cpumask_of(dest_cpu)); + vi->txn_addr = txn_affinity_addr(d->irq, dest_cpu); spin_lock_irqsave(&iosapic_lock, flags); /* d1 contains the destination CPU, so only want to set that @@ -719,19 +701,19 @@ static void iosapic_set_affinity_irq(unsigned int irq, cpumask_t dest) iosapic_set_irt_data(vi, &dummy_d0, &d1); iosapic_wr_irt_entry(vi, d0, d1); spin_unlock_irqrestore(&iosapic_lock, flags); + + return 0; } #endif -static struct hw_interrupt_type iosapic_interrupt_type = { - .typename = "IO-SAPIC-level", - .startup = iosapic_startup_irq, - .shutdown = iosapic_disable_irq, - .enable = iosapic_enable_irq, - .disable = iosapic_disable_irq, - .ack = no_ack_irq, - .end = iosapic_end_irq, +static struct irq_chip iosapic_interrupt_type = { + .name = "IO-SAPIC-level", + .irq_unmask = iosapic_unmask_irq, + .irq_mask = iosapic_mask_irq, + .irq_ack = cpu_ack_irq, + .irq_eoi = iosapic_eoi_irq, #ifdef CONFIG_SMP - .set_affinity = iosapic_set_affinity_irq, + .irq_set_affinity = iosapic_set_affinity_irq, #endif }; @@ -829,6 +811,86 @@ int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev) return pcidev->irq; } +static struct iosapic_info *iosapic_list; + +#ifdef CONFIG_64BIT +int iosapic_serial_irq(struct parisc_device *dev) +{ + struct iosapic_info *isi; + struct irt_entry *irte; + struct vector_info *vi; + int cnt; + int intin; + + intin = (dev->mod_info >> 24) & 15; + + /* lookup IRT entry for isi/slot/pin set */ + for (cnt = 0; cnt < irt_num_entry; cnt++) { + irte = &irt_cell[cnt]; + if (COMPARE_IRTE_ADDR(irte, dev->mod0) && + irte->dest_iosapic_intin == intin) + break; + } + if (cnt >= irt_num_entry) + return 0; /* no irq found, force polling */ + + DBG_IRT("iosapic_serial_irq(): irte %p %x %x %x %x %x %x %x %x\n", + irte, + irte->entry_type, + irte->entry_length, + irte->polarity_trigger, + irte->src_bus_irq_devno, + irte->src_bus_id, + irte->src_seg_id, + irte->dest_iosapic_intin, + (u32) irte->dest_iosapic_addr); + + /* search for iosapic */ + for (isi = iosapic_list; isi; isi = isi->isi_next) + if (isi->isi_hpa == dev->mod0) + break; + if (!isi) + return 0; /* no iosapic found, force polling */ + + /* get vector info for this input line */ + vi = isi->isi_vector + intin; + DBG_IRT("iosapic_serial_irq: line %d vi 0x%p\n", iosapic_intin, vi); + + /* If this IRQ line has already been setup, skip it */ + if (vi->irte) + goto out; + + vi->irte = irte; + + /* + * Allocate processor IRQ + * + * XXX/FIXME The txn_alloc_irq() code and related code should be + * moved to enable_irq(). That way we only allocate processor IRQ + * bits for devices that actually have drivers claiming them. + * Right now we assign an IRQ to every PCI device present, + * regardless of whether it's used or not. + */ + vi->txn_irq = txn_alloc_irq(8); + + if (vi->txn_irq < 0) + panic("I/O sapic: couldn't get TXN IRQ\n"); + + /* enable_irq() will use txn_* to program IRdT */ + vi->txn_addr = txn_alloc_addr(vi->txn_irq); + vi->txn_data = txn_alloc_data(vi->txn_irq); + + vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI; + vi->eoi_data = cpu_to_le32(vi->txn_data); + + cpu_claim_irq(vi->txn_irq, &iosapic_interrupt_type, vi); + + out: + + return vi->txn_irq; +} +#endif + /* ** squirrel away the I/O Sapic Version @@ -873,7 +935,7 @@ void *iosapic_register(unsigned long hpa) return NULL; } - isi = (struct iosapic_info *)kzalloc(sizeof(struct iosapic_info), GFP_KERNEL); + isi = kzalloc(sizeof(struct iosapic_info), GFP_KERNEL); if (!isi) { BUG(); return NULL; @@ -884,8 +946,8 @@ void *iosapic_register(unsigned long hpa) isi->isi_version = iosapic_rd_version(isi); isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; - vip = isi->isi_vector = (struct vector_info *) - kzalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL); + vip = isi->isi_vector = kcalloc(isi->isi_num_vectors, + sizeof(struct vector_info), GFP_KERNEL); if (vip == NULL) { kfree(isi); return NULL; @@ -895,6 +957,8 @@ void *iosapic_register(unsigned long hpa) vip->irqline = (unsigned char) cnt; vip->iosapic = isi; } + isi->isi_next = iosapic_list; + iosapic_list = isi; return isi; } diff --git a/drivers/parisc/iosapic_private.h b/drivers/parisc/iosapic_private.h index 41e7ec2a44a..6e05e30a245 100644 --- a/drivers/parisc/iosapic_private.h +++ b/drivers/parisc/iosapic_private.h @@ -132,7 +132,7 @@ struct iosapic_irt { struct vector_info { struct iosapic_info *iosapic; /* I/O SAPIC this vector is on */ struct irt_entry *irte; /* IRT entry */ - u32 *eoi_addr; /* precalculate EOI reg address */ + u32 __iomem *eoi_addr; /* precalculate EOI reg address */ u32 eoi_data; /* IA64: ? PA: swapped txn_data */ int txn_irq; /* virtual IRQ number for processor */ ulong txn_addr; /* IA64: id_eid PA: partial HPA */ diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c index cb3d2817612..e65727ca9fc 100644 --- a/drivers/parisc/lasi.c +++ b/drivers/parisc/lasi.c @@ -107,7 +107,7 @@ lasi_init_irq(struct gsc_asic *this_lasi) #else -void __init lasi_led_init(unsigned long lasi_hpa) +static void __init lasi_led_init(unsigned long lasi_hpa) { unsigned long datareg; @@ -163,8 +163,7 @@ static void lasi_power_off(void) gsc_writel(0x02, datareg); } -int __init -lasi_init_chip(struct parisc_device *dev) +static int __init lasi_init_chip(struct parisc_device *dev) { extern void (*chassis_power_off)(void); struct gsc_asic *lasi; @@ -193,7 +192,7 @@ lasi_init_chip(struct parisc_device *dev) dev->irq = gsc_alloc_irq(&gsc_irq); if (dev->irq < 0) { printk(KERN_ERR "%s(): cannot get GSC irq\n", - __FUNCTION__); + __func__); kfree(lasi); return -EBUSY; } diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 3fe4a77fa16..37e71ff6408 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -34,21 +34,19 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/spinlock.h> -#include <linux/init.h> /* for __init and __devinit */ +#include <linux/init.h> /* for __init */ #include <linux/pci.h> #include <linux/ioport.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <asm/byteorder.h> #include <asm/pdc.h> #include <asm/pdcpat.h> #include <asm/page.h> -#include <asm/system.h> +#include <asm/ropes.h> #include <asm/hardware.h> /* for register_parisc_driver() stuff */ #include <asm/parisc-device.h> -#include <asm/iosapic.h> /* for iosapic_register() */ #include <asm/io.h> /* read/write stuff */ #undef DEBUG_LBA /* general stuff */ @@ -100,113 +98,10 @@ #define MODULE_NAME "LBA" -#define LBA_FUNC_ID 0x0000 /* function id */ -#define LBA_FCLASS 0x0008 /* function class, bist, header, rev... */ -#define LBA_CAPABLE 0x0030 /* capabilities register */ - -#define LBA_PCI_CFG_ADDR 0x0040 /* poke CFG address here */ -#define LBA_PCI_CFG_DATA 0x0048 /* read or write data here */ - -#define LBA_PMC_MTLT 0x0050 /* Firmware sets this - read only. */ -#define LBA_FW_SCRATCH 0x0058 /* Firmware writes the PCI bus number here. */ -#define LBA_ERROR_ADDR 0x0070 /* On error, address gets logged here */ - -#define LBA_ARB_MASK 0x0080 /* bit 0 enable arbitration. PAT/PDC enables */ -#define LBA_ARB_PRI 0x0088 /* firmware sets this. */ -#define LBA_ARB_MODE 0x0090 /* firmware sets this. */ -#define LBA_ARB_MTLT 0x0098 /* firmware sets this. */ - -#define LBA_MOD_ID 0x0100 /* Module ID. PDC_PAT_CELL reports 4 */ - -#define LBA_STAT_CTL 0x0108 /* Status & Control */ -#define LBA_BUS_RESET 0x01 /* Deassert PCI Bus Reset Signal */ -#define CLEAR_ERRLOG 0x10 /* "Clear Error Log" cmd */ -#define CLEAR_ERRLOG_ENABLE 0x20 /* "Clear Error Log" Enable */ -#define HF_ENABLE 0x40 /* enable HF mode (default is -1 mode) */ - -#define LBA_LMMIO_BASE 0x0200 /* < 4GB I/O address range */ -#define LBA_LMMIO_MASK 0x0208 - -#define LBA_GMMIO_BASE 0x0210 /* > 4GB I/O address range */ -#define LBA_GMMIO_MASK 0x0218 - -#define LBA_WLMMIO_BASE 0x0220 /* All < 4GB ranges under the same *SBA* */ -#define LBA_WLMMIO_MASK 0x0228 - -#define LBA_WGMMIO_BASE 0x0230 /* All > 4GB ranges under the same *SBA* */ -#define LBA_WGMMIO_MASK 0x0238 - -#define LBA_IOS_BASE 0x0240 /* I/O port space for this LBA */ -#define LBA_IOS_MASK 0x0248 - -#define LBA_ELMMIO_BASE 0x0250 /* Extra LMMIO range */ -#define LBA_ELMMIO_MASK 0x0258 - -#define LBA_EIOS_BASE 0x0260 /* Extra I/O port space */ -#define LBA_EIOS_MASK 0x0268 - -#define LBA_GLOBAL_MASK 0x0270 /* Mercury only: Global Address Mask */ -#define LBA_DMA_CTL 0x0278 /* firmware sets this */ - -#define LBA_IBASE 0x0300 /* SBA DMA support */ -#define LBA_IMASK 0x0308 - -/* FIXME: ignore DMA Hint stuff until we can measure performance */ -#define LBA_HINT_CFG 0x0310 -#define LBA_HINT_BASE 0x0380 /* 14 registers at every 8 bytes. */ - -#define LBA_BUS_MODE 0x0620 - -/* ERROR regs are needed for config cycle kluges */ -#define LBA_ERROR_CONFIG 0x0680 -#define LBA_SMART_MODE 0x20 -#define LBA_ERROR_STATUS 0x0688 -#define LBA_ROPE_CTL 0x06A0 - -#define LBA_IOSAPIC_BASE 0x800 /* Offset of IRQ logic */ - /* non-postable I/O port space, densely packed */ #define LBA_PORT_BASE (PCI_F_EXTEND | 0xfee00000UL) static void __iomem *astro_iop_base __read_mostly; -#define ELROY_HVERS 0x782 -#define MERCURY_HVERS 0x783 -#define QUICKSILVER_HVERS 0x784 - -static inline int IS_ELROY(struct parisc_device *d) -{ - return (d->id.hversion == ELROY_HVERS); -} - -static inline int IS_MERCURY(struct parisc_device *d) -{ - return (d->id.hversion == MERCURY_HVERS); -} - -static inline int IS_QUICKSILVER(struct parisc_device *d) -{ - return (d->id.hversion == QUICKSILVER_HVERS); -} - - -/* -** lba_device: Per instance Elroy data structure -*/ -struct lba_device { - struct pci_hba_data hba; - - spinlock_t lba_lock; - void *iosapic_obj; - -#ifdef CONFIG_64BIT - void __iomem * iop_base; /* PA_VIEW - for IO port accessor funcs */ -#endif - - int flags; /* state/functionality enabled */ - int hw_rev; /* HW revision of chip */ -}; - - static u32 lba_t32; /* lba flags */ @@ -271,7 +166,8 @@ lba_dump_res(struct resource *r, int d) printk(KERN_DEBUG "(%p)", r->parent); for (i = d; i ; --i) printk(" "); - printk(KERN_DEBUG "%p [%lx,%lx]/%lx\n", r, r->start, r->end, r->flags); + printk(KERN_DEBUG "%p [%lx,%lx]/%lx\n", r, + (long)r->start, (long)r->end, r->flags); lba_dump_res(r->child, d+2); lba_dump_res(r->sibling, d); } @@ -293,8 +189,8 @@ lba_dump_res(struct resource *r, int d) static int lba_device_present(u8 bus, u8 dfn, struct lba_device *d) { - u8 first_bus = d->hba.hba_bus->secondary; - u8 last_sub_bus = d->hba.hba_bus->subordinate; + u8 first_bus = d->hba.hba_bus->busn_res.start; + u8 last_sub_bus = d->hba.hba_bus->busn_res.end; if ((bus < first_bus) || (bus > last_sub_bus) || @@ -468,7 +364,7 @@ lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size) static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) { struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 tok = LBA_CFG_TOK(local_bus, devfn); void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; @@ -480,12 +376,12 @@ static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int /* original - Generate config cycle on broken elroy with risk we will miss PCI bus errors. */ *data = lba_rd_cfg(d, tok, pos, size); - DBG_CFG("%s(%x+%2x) -> 0x%x (a)\n", __FUNCTION__, tok, pos, *data); + DBG_CFG("%s(%x+%2x) -> 0x%x (a)\n", __func__, tok, pos, *data); return 0; } - if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->secondary, devfn, d)) { - DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __FUNCTION__, tok, pos); + if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->busn_res.start, devfn, d)) { + DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __func__, tok, pos); /* either don't want to look or know device isn't present. */ *data = ~0U; return(0); @@ -501,7 +397,7 @@ static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int case 2: *data = READ_REG16(data_reg + (pos & 2)); break; case 4: *data = READ_REG32(data_reg); break; } - DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __FUNCTION__, tok, pos, *data); + DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __func__, tok, pos, *data); return 0; } @@ -535,7 +431,7 @@ lba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size) static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data) { struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 tok = LBA_CFG_TOK(local_bus,devfn); if ((pos > 255) || (devfn > 255)) @@ -544,16 +440,16 @@ static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int if (!LBA_SKIP_PROBE(d)) { /* Original Workaround */ lba_wr_cfg(d, tok, pos, (u32) data, size); - DBG_CFG("%s(%x+%2x) = 0x%x (a)\n", __FUNCTION__, tok, pos,data); + DBG_CFG("%s(%x+%2x) = 0x%x (a)\n", __func__, tok, pos,data); return 0; } - if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->secondary, devfn, d))) { - DBG_CFG("%s(%x+%2x) = 0x%x (b)\n", __FUNCTION__, tok, pos,data); + if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->busn_res.start, devfn, d))) { + DBG_CFG("%s(%x+%2x) = 0x%x (b)\n", __func__, tok, pos,data); return 1; /* New Workaround */ } - DBG_CFG("%s(%x+%2x) = 0x%x (c)\n", __FUNCTION__, tok, pos, data); + DBG_CFG("%s(%x+%2x) = 0x%x (c)\n", __func__, tok, pos, data); /* Basic Algorithm */ LBA_CFG_ADDR_SETUP(d, tok | pos); @@ -585,7 +481,7 @@ static struct pci_ops elroy_cfg_ops = { static int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) { struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 tok = LBA_CFG_TOK(local_bus, devfn); void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; @@ -618,13 +514,13 @@ static int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, i { struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; - u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; u32 tok = LBA_CFG_TOK(local_bus,devfn); if ((pos > 255) || (devfn > 255)) return -EINVAL; - DBG_CFG("%s(%x+%2x) <- 0x%x (c)\n", __FUNCTION__, tok, pos, data); + DBG_CFG("%s(%x+%2x) <- 0x%x (c)\n", __func__, tok, pos, data); LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); switch(size) { @@ -660,44 +556,6 @@ lba_bios_init(void) #ifdef CONFIG_64BIT /* -** Determine if a device is already configured. -** If so, reserve it resources. -** -** Read PCI cfg command register and see if I/O or MMIO is enabled. -** PAT has to enable the devices it's using. -** -** Note: resources are fixed up before we try to claim them. -*/ -static void -lba_claim_dev_resources(struct pci_dev *dev) -{ - u16 cmd; - int i, srch_flags; - - (void) pci_read_config_word(dev, PCI_COMMAND, &cmd); - - srch_flags = (cmd & PCI_COMMAND_IO) ? IORESOURCE_IO : 0; - if (cmd & PCI_COMMAND_MEMORY) - srch_flags |= IORESOURCE_MEM; - - if (!srch_flags) - return; - - for (i = 0; i <= PCI_ROM_RESOURCE; i++) { - if (dev->resource[i].flags & srch_flags) { - pci_claim_resource(dev, i); - DBG(" claimed %s %d [%lx,%lx]/%lx\n", - pci_name(dev), i, - dev->resource[i].start, - dev->resource[i].end, - dev->resource[i].flags - ); - } - } -} - - -/* * truncate_pat_collision: Deal with overlaps or outright collisions * between PAT PDC reported ranges. * @@ -750,13 +608,60 @@ truncate_pat_collision(struct resource *root, struct resource *new) printk(KERN_WARNING "LBA: Truncating lmmio_space [%lx/%lx] " "to [%lx,%lx]\n", start, end, - new->start, new->end ); + (long)new->start, (long)new->end ); return 0; /* truncation successful */ } +/* + * extend_lmmio_len: extend lmmio range to maximum length + * + * This is needed at least on C8000 systems to get the ATI FireGL card + * working. On other systems we will currently not extend the lmmio space. + */ +static unsigned long +extend_lmmio_len(unsigned long start, unsigned long end, unsigned long lba_len) +{ + struct resource *tmp; + + pr_debug("LMMIO mismatch: PAT length = 0x%lx, MASK register = 0x%lx\n", + end - start, lba_len); + + lba_len = min(lba_len+1, 256UL*1024*1024); /* limit to 256 MB */ + + pr_debug("LBA: lmmio_space [0x%lx-0x%lx] - original\n", start, end); + + if (boot_cpu_data.cpu_type < mako) { + pr_info("LBA: Not a C8000 system - not extending LMMIO range.\n"); + return end; + } + + end += lba_len; + if (end < start) /* fix overflow */ + end = -1ULL; + + pr_debug("LBA: lmmio_space [0x%lx-0x%lx] - current\n", start, end); + + /* first overlap */ + for (tmp = iomem_resource.child; tmp; tmp = tmp->sibling) { + pr_debug("LBA: testing %pR\n", tmp); + if (tmp->start == start) + continue; /* ignore ourself */ + if (tmp->end < start) + continue; + if (tmp->start > end) + continue; + if (end >= tmp->start) + end = tmp->start - 1; + } + + pr_info("LBA: lmmio_space [0x%lx-0x%lx] - new\n", start, end); + + /* return new end */ + return end; +} + #else -#define lba_claim_dev_resources(dev) do { } while (0) #define truncate_pat_collision(r,n) (0) #endif @@ -772,26 +677,29 @@ truncate_pat_collision(struct resource *root, struct resource *new) static void lba_fixup_bus(struct pci_bus *bus) { - struct list_head *ln; + struct pci_dev *dev; #ifdef FBB_SUPPORT u16 status; #endif struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge)); - int lba_portbase = HBA_PORT_BASE(ldev->hba.hba_num); DBG("lba_fixup_bus(0x%p) bus %d platform_data 0x%p\n", - bus, bus->secondary, bus->bridge->platform_data); + bus, (int)bus->busn_res.start, bus->bridge->platform_data); /* ** Properly Setup MMIO resources for this bus. ** pci_alloc_primary_bus() mangles this. */ - if (bus->self) { + if (bus->parent) { + int i; /* PCI-PCI Bridge */ pci_read_bridge_bases(bus); + for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) { + pci_claim_resource(bus->self, i); + } } else { /* Host-PCI Bridge */ - int err, i; + int err; DBG("lba_fixup_bus() %s [%lx/%lx]/%lx\n", ldev->hba.io_space.name, @@ -807,51 +715,30 @@ lba_fixup_bus(struct pci_bus *bus) lba_dump_res(&ioport_resource, 2); BUG(); } - /* advertize Host bridge resources to PCI bus */ - bus->resource[0] = &(ldev->hba.io_space); - i = 1; - if (ldev->hba.elmmio_space.start) { + if (ldev->hba.elmmio_space.flags) { err = request_resource(&iomem_resource, &(ldev->hba.elmmio_space)); if (err < 0) { printk("FAILED: lba_fixup_bus() request for " "elmmio_space [%lx/%lx]\n", - ldev->hba.elmmio_space.start, - ldev->hba.elmmio_space.end); + (long)ldev->hba.elmmio_space.start, + (long)ldev->hba.elmmio_space.end); /* lba_dump_res(&iomem_resource, 2); */ /* BUG(); */ - } else - bus->resource[i++] = &(ldev->hba.elmmio_space); + } } - - /* Overlaps with elmmio can (and should) fail here. - * We will prune (or ignore) the distributed range. - * - * FIXME: SBA code should register all elmmio ranges first. - * that would take care of elmmio ranges routed - * to a different rope (already discovered) from - * getting registered *after* LBA code has already - * registered it's distributed lmmio range. - */ - if (truncate_pat_collision(&iomem_resource, - &(ldev->hba.lmmio_space))) { - - printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n", - ldev->hba.lmmio_space.start, - ldev->hba.lmmio_space.end); - } else { + if (ldev->hba.lmmio_space.flags) { err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space)); if (err < 0) { printk(KERN_ERR "FAILED: lba_fixup_bus() request for " "lmmio_space [%lx/%lx]\n", - ldev->hba.lmmio_space.start, - ldev->hba.lmmio_space.end); - } else - bus->resource[i++] = &(ldev->hba.lmmio_space); + (long)ldev->hba.lmmio_space.start, + (long)ldev->hba.lmmio_space.end); + } } #ifdef CONFIG_64BIT @@ -861,20 +748,18 @@ lba_fixup_bus(struct pci_bus *bus) if (err < 0) { printk("FAILED: lba_fixup_bus() request for " "gmmio_space [%lx/%lx]\n", - ldev->hba.gmmio_space.start, - ldev->hba.gmmio_space.end); + (long)ldev->hba.gmmio_space.start, + (long)ldev->hba.gmmio_space.end); lba_dump_res(&iomem_resource, 2); BUG(); } - bus->resource[i++] = &(ldev->hba.gmmio_space); } #endif } - list_for_each(ln, &bus->devices) { + list_for_each_entry(dev, &bus->devices, bus_list) { int i; - struct pci_dev *dev = pci_dev_b(ln); DBG("lba_fixup_bus() %s\n", pci_name(dev)); @@ -886,26 +771,12 @@ lba_fixup_bus(struct pci_bus *bus) if (!res->start) continue; - if (res->flags & IORESOURCE_IO) { - DBG("lba_fixup_bus() I/O Ports [%lx/%lx] -> ", - res->start, res->end); - res->start |= lba_portbase; - res->end |= lba_portbase; - DBG("[%lx/%lx]\n", res->start, res->end); - } else if (res->flags & IORESOURCE_MEM) { - /* - ** Convert PCI (IO_VIEW) addresses to - ** processor (PA_VIEW) addresses - */ - DBG("lba_fixup_bus() MMIO [%lx/%lx] -> ", - res->start, res->end); - res->start = PCI_HOST_ADDR(HBA_DATA(ldev), res->start); - res->end = PCI_HOST_ADDR(HBA_DATA(ldev), res->end); - DBG("[%lx/%lx]\n", res->start, res->end); - } else { - DBG("lba_fixup_bus() WTF? 0x%lx [%lx/%lx] XXX", - res->flags, res->start, res->end); - } + /* + ** FIXME: this will result in whinging for devices + ** that share expansion ROMs (think quad tulip), but + ** isn't harmful. + */ + pci_claim_resource(dev, i); } #ifdef FBB_SUPPORT @@ -917,11 +788,6 @@ lba_fixup_bus(struct pci_bus *bus) bus->bridge_ctl &= ~(status & PCI_STATUS_FAST_BACK); #endif - if (is_pdc_pat()) { - /* Claim resources for PDC's devices */ - lba_claim_dev_resources(dev); - } - /* ** P2PB's have no IRQs. ignore them. */ @@ -938,7 +804,7 @@ lba_fixup_bus(struct pci_bus *bus) ** Can't fixup here anyway....garr... */ if (fbb_enable) { - if (bus->self) { + if (bus->parent) { u8 control; /* enable on PPB */ (void) pci_read_config_byte(bus->self, PCI_BRIDGE_CONTROL, &control); @@ -951,7 +817,7 @@ lba_fixup_bus(struct pci_bus *bus) } /* Lastly enable FBB/PERR/SERR on all devices too */ - list_for_each(ln, &bus->devices) { + list_for_each_entry(dev, &bus->devices, bus_list) { (void) pci_read_config_word(dev, PCI_COMMAND, &status); status |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR | fbb_enable; (void) pci_write_config_word(dev, PCI_COMMAND, status); @@ -960,7 +826,7 @@ lba_fixup_bus(struct pci_bus *bus) } -struct pci_bios_ops lba_bios_ops = { +static struct pci_bios_ops lba_bios_ops = { .init = lba_bios_init, .fixup_bus = lba_fixup_bus, }; @@ -1026,7 +892,7 @@ LBA_PORT_IN(32, 0) #define LBA_PORT_OUT(size, mask) \ static void lba_astro_out##size (struct pci_hba_data *d, u16 addr, u##size val) \ { \ - DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \ + DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __func__, d, addr, val); \ WRITE_REG##size(val, astro_iop_base + addr); \ if (LBA_DEV(d)->hw_rev < 3) \ lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \ @@ -1068,7 +934,7 @@ static struct pci_port_ops lba_astro_port_ops = { static u##size lba_pat_in##size (struct pci_hba_data *l, u16 addr) \ { \ u##size t; \ - DBG_PORT("%s(0x%p, 0x%x) ->", __FUNCTION__, l, addr); \ + DBG_PORT("%s(0x%p, 0x%x) ->", __func__, l, addr); \ t = READ_REG##size(PIOP_TO_GMMIO(LBA_DEV(l), addr)); \ DBG_PORT(" 0x%x\n", t); \ return (t); \ @@ -1083,8 +949,8 @@ LBA_PORT_IN(32, 0) #define LBA_PORT_OUT(size, mask) \ static void lba_pat_out##size (struct pci_hba_data *l, u16 addr, u##size val) \ { \ - void *where = (void *) PIOP_TO_GMMIO(LBA_DEV(l), addr); \ - DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \ + void __iomem *where = PIOP_TO_GMMIO(LBA_DEV(l), addr); \ + DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __func__, l, addr, val); \ WRITE_REG##size(val, where); \ /* flush the I/O down to the elroy at least */ \ lba_t32 = READ_U32(l->base_addr + LBA_FUNC_ID); \ @@ -1116,28 +982,38 @@ static void lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) { unsigned long bytecnt; - pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; /* PA_VIEW */ - pdc_pat_cell_mod_maddr_block_t io_pdc_cell; /* IO_VIEW */ long io_count; long status; /* PDC return status */ long pa_count; + pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; /* PA_VIEW */ + pdc_pat_cell_mod_maddr_block_t *io_pdc_cell; /* IO_VIEW */ int i; + pa_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL); + if (!pa_pdc_cell) + return; + + io_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL); + if (!io_pdc_cell) { + kfree(pa_pdc_cell); + return; + } + /* return cell module (IO view) */ status = pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, - PA_VIEW, & pa_pdc_cell); - pa_count = pa_pdc_cell.mod[1]; + PA_VIEW, pa_pdc_cell); + pa_count = pa_pdc_cell->mod[1]; status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, - IO_VIEW, &io_pdc_cell); - io_count = io_pdc_cell.mod[1]; + IO_VIEW, io_pdc_cell); + io_count = io_pdc_cell->mod[1]; /* We've already done this once for device discovery...*/ if (status != PDC_OK) { panic("pdc_pat_cell_module() call failed for LBA!\n"); } - if (PAT_GET_ENTITY(pa_pdc_cell.mod_info) != PAT_ENTITY_LBA) { + if (PAT_GET_ENTITY(pa_pdc_cell->mod_info) != PAT_ENTITY_LBA) { panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n"); } @@ -1152,30 +1028,39 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) } *p, *io; struct resource *r; - p = (void *) &(pa_pdc_cell.mod[2+i*3]); - io = (void *) &(io_pdc_cell.mod[2+i*3]); + p = (void *) &(pa_pdc_cell->mod[2+i*3]); + io = (void *) &(io_pdc_cell->mod[2+i*3]); /* Convert the PAT range data to PCI "struct resource" */ switch(p->type & 0xff) { case PAT_PBNUM: lba_dev->hba.bus_num.start = p->start; lba_dev->hba.bus_num.end = p->end; + lba_dev->hba.bus_num.flags = IORESOURCE_BUS; break; case PAT_LMMIO: /* used to fix up pre-initialized MEM BARs */ - if (!lba_dev->hba.lmmio_space.start) { + if (!lba_dev->hba.lmmio_space.flags) { + unsigned long lba_len; + + lba_len = ~READ_REG32(lba_dev->hba.base_addr + + LBA_LMMIO_MASK); + if ((p->end - p->start) != lba_len) + p->end = extend_lmmio_len(p->start, + p->end, lba_len); + sprintf(lba_dev->hba.lmmio_name, - "PCI%02lx LMMIO", - lba_dev->hba.bus_num.start); + "PCI%02x LMMIO", + (int)lba_dev->hba.bus_num.start); lba_dev->hba.lmmio_space_offset = p->start - io->start; r = &lba_dev->hba.lmmio_space; r->name = lba_dev->hba.lmmio_name; - } else if (!lba_dev->hba.elmmio_space.start) { + } else if (!lba_dev->hba.elmmio_space.flags) { sprintf(lba_dev->hba.elmmio_name, - "PCI%02lx ELMMIO", - lba_dev->hba.bus_num.start); + "PCI%02x ELMMIO", + (int)lba_dev->hba.bus_num.start); r = &lba_dev->hba.elmmio_space; r->name = lba_dev->hba.elmmio_name; } else { @@ -1192,8 +1077,8 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) case PAT_GMMIO: /* MMIO space > 4GB phys addr; for 64-bit BAR */ - sprintf(lba_dev->hba.gmmio_name, "PCI%02lx GMMIO", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.gmmio_name, "PCI%02x GMMIO", + (int)lba_dev->hba.bus_num.start); r = &lba_dev->hba.gmmio_space; r->name = lba_dev->hba.gmmio_name; r->start = p->start; @@ -1215,8 +1100,8 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) */ lba_dev->iop_base = ioremap_nocache(p->start, 64 * 1024 * 1024); - sprintf(lba_dev->hba.io_name, "PCI%02lx Ports", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.io_name, "PCI%02x Ports", + (int)lba_dev->hba.bus_num.start); r = &lba_dev->hba.io_space; r->name = lba_dev->hba.io_name; r->start = HBA_PORT_BASE(lba_dev->hba.hba_num); @@ -1232,6 +1117,9 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) break; } } + + kfree(pa_pdc_cell); + kfree(io_pdc_cell); } #else /* keep compiler from complaining about missing declarations */ @@ -1264,13 +1152,14 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) r->name = "LBA PCI Busses"; r->start = lba_num & 0xff; r->end = (lba_num>>8) & 0xff; + r->flags = IORESOURCE_BUS; /* Set up local PCI Bus resources - we don't need them for ** Legacy boxes but it's nice to see in /proc/iomem. */ r = &(lba_dev->hba.lmmio_space); - sprintf(lba_dev->hba.lmmio_name, "PCI%02lx LMMIO", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO", + (int)lba_dev->hba.bus_num.start); r->name = lba_dev->hba.lmmio_name; #if 1 @@ -1378,8 +1267,8 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ** an existing (but unused portion of) distributed range. */ r = &(lba_dev->hba.elmmio_space); - sprintf(lba_dev->hba.elmmio_name, "PCI%02lx ELMMIO", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.elmmio_name, "PCI%02x ELMMIO", + (int)lba_dev->hba.bus_num.start); r->name = lba_dev->hba.elmmio_name; #if 1 @@ -1400,8 +1289,8 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) #endif r = &(lba_dev->hba.io_space); - sprintf(lba_dev->hba.io_name, "PCI%02lx Ports", - lba_dev->hba.bus_num.start); + sprintf(lba_dev->hba.io_name, "PCI%02x Ports", + (int)lba_dev->hba.bus_num.start); r->name = lba_dev->hba.io_name; r->flags = IORESOURCE_IO; r->start = READ_REG32(lba_dev->hba.base_addr + LBA_IOS_BASE) & ~1L; @@ -1509,23 +1398,32 @@ lba_hw_init(struct lba_device *d) return 0; } - +/* + * Unfortunately, when firmware numbers busses, it doesn't take into account + * Cardbus bridges. So we have to renumber the busses to suit ourselves. + * Elroy/Mercury don't actually know what bus number they're attached to; + * we use bus 0 to indicate the directly attached bus and any other bus + * number will be taken care of by the PCI-PCI bridge. + */ +static unsigned int lba_next_bus = 0; /* -** Determine if lba should claim this chip (return 0) or not (return 1). -** If so, initialize the chip and tell other partners in crime they -** have work to do. -*/ + * Determine if lba should claim this chip (return 0) or not (return 1). + * If so, initialize the chip and tell other partners in crime they + * have work to do. + */ static int __init lba_driver_probe(struct parisc_device *dev) { struct lba_device *lba_dev; + LIST_HEAD(resources); struct pci_bus *lba_bus; struct pci_ops *cfg_ops; u32 func_class; void *tmp_obj; char *version; void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096); + int max; /* Read HW Rev First */ func_class = READ_REG32(addr + LBA_FCLASS); @@ -1542,8 +1440,8 @@ lba_driver_probe(struct parisc_device *dev) default: version = "TR4+"; } - printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n", - MODULE_NAME, version, func_class & 0xf, dev->hpa.start); + printk(KERN_INFO "Elroy version %s (0x%x) found at 0x%lx\n", + version, func_class & 0xf, (long)dev->hpa.start); if (func_class < 2) { printk(KERN_WARNING "Can't support LBA older than " @@ -1563,23 +1461,26 @@ lba_driver_probe(struct parisc_device *dev) } } else if (IS_MERCURY(dev) || IS_QUICKSILVER(dev)) { + int major, minor; + func_class &= 0xff; - version = kmalloc(6, GFP_KERNEL); - snprintf(version, 6, "TR%d.%d",(func_class >> 4),(func_class & 0xf)); + major = func_class >> 4, minor = func_class & 0xf; + /* We could use one printk for both Elroy and Mercury, * but for the mask for func_class. */ - printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n", - MODULE_NAME, version, func_class & 0xff, dev->hpa.start); + printk(KERN_INFO "%s version TR%d.%d (0x%x) found at 0x%lx\n", + IS_MERCURY(dev) ? "Mercury" : "Quicksilver", major, + minor, func_class, (long)dev->hpa.start); + cfg_ops = &mercury_cfg_ops; } else { - printk(KERN_ERR "Unknown LBA found at 0x%lx\n", dev->hpa.start); + printk(KERN_ERR "Unknown LBA found at 0x%lx\n", + (long)dev->hpa.start); return -ENODEV; } - /* - ** Tell I/O SAPIC driver we have a IRQ handler/region. - */ + /* Tell I/O SAPIC driver we have a IRQ handler/region. */ tmp_obj = iosapic_register(dev->hpa.start + LBA_IOSAPIC_BASE); /* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't @@ -1600,6 +1501,7 @@ lba_driver_probe(struct parisc_device *dev) lba_dev->hba.dev = dev; lba_dev->iosapic_obj = tmp_obj; /* save interrupt handle */ lba_dev->hba.iommu = sba_get_iommu(dev); /* get iommu data */ + parisc_set_drvdata(dev, lba_dev); /* ------------ Second : initialize common stuff ---------- */ pci_bios = &lba_bios_ops; @@ -1627,16 +1529,49 @@ lba_driver_probe(struct parisc_device *dev) lba_legacy_resources(dev, lba_dev); } - /* - ** Tell PCI support another PCI bus was found. - ** Walks PCI bus for us too. - */ + if (lba_dev->hba.bus_num.start < lba_next_bus) + lba_dev->hba.bus_num.start = lba_next_bus; + + /* Overlaps with elmmio can (and should) fail here. + * We will prune (or ignore) the distributed range. + * + * FIXME: SBA code should register all elmmio ranges first. + * that would take care of elmmio ranges routed + * to a different rope (already discovered) from + * getting registered *after* LBA code has already + * registered it's distributed lmmio range. + */ + if (truncate_pat_collision(&iomem_resource, + &(lba_dev->hba.lmmio_space))) { + printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n", + (long)lba_dev->hba.lmmio_space.start, + (long)lba_dev->hba.lmmio_space.end); + lba_dev->hba.lmmio_space.flags = 0; + } + + pci_add_resource_offset(&resources, &lba_dev->hba.io_space, + HBA_PORT_BASE(lba_dev->hba.hba_num)); + if (lba_dev->hba.elmmio_space.flags) + pci_add_resource_offset(&resources, &lba_dev->hba.elmmio_space, + lba_dev->hba.lmmio_space_offset); + if (lba_dev->hba.lmmio_space.flags) + pci_add_resource_offset(&resources, &lba_dev->hba.lmmio_space, + lba_dev->hba.lmmio_space_offset); + if (lba_dev->hba.gmmio_space.flags) + pci_add_resource(&resources, &lba_dev->hba.gmmio_space); + + pci_add_resource(&resources, &lba_dev->hba.bus_num); + dev->dev.platform_data = lba_dev; lba_bus = lba_dev->hba.hba_bus = - pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start, - cfg_ops, NULL); - if (lba_bus) - pci_bus_add_devices(lba_bus); + pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start, + cfg_ops, NULL, &resources); + if (!lba_bus) { + pci_free_resource_list(&resources); + return 0; + } + + max = pci_scan_child_bus(lba_bus); /* This is in lieu of calling pci_assign_unassigned_resources() */ if (is_pdc_pat()) { @@ -1655,8 +1590,6 @@ lba_driver_probe(struct parisc_device *dev) lba_dump_res(&lba_dev->hba.lmmio_space, 2); #endif } - pci_enable_bridges(lba_bus); - /* ** Once PCI register ops has walked the bus, access to config @@ -1667,6 +1600,9 @@ lba_driver_probe(struct parisc_device *dev) lba_dev->flags |= LBA_FLAG_SKIP_PROBE; } + lba_next_bus = max + 1; + pci_bus_add_devices(lba_bus); + /* Whew! Finally done! Tell services we got this one covered. */ return 0; } @@ -1708,7 +1644,7 @@ void lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask) WARN_ON((ibase & 0x001fffff) != 0); WARN_ON((imask & 0x001fffff) != 0); - DBG("%s() ibase 0x%x imask 0x%x\n", __FUNCTION__, ibase, imask); + DBG("%s() ibase 0x%x imask 0x%x\n", __func__, ibase, imask); WRITE_REG32( imask, base_addr + LBA_IMASK); WRITE_REG32( ibase, base_addr + LBA_IBASE); iounmap(base_addr); diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index bf00fa2537b..b4824313199 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -3,7 +3,7 @@ * * (c) Copyright 2000 Red Hat Software * (c) Copyright 2000 Helge Deller <hdeller@redhat.com> - * (c) Copyright 2001-2005 Helge Deller <deller@gmx.de> + * (c) Copyright 2001-2009 Helge Deller <deller@gmx.de> * (c) Copyright 2001 Randolph Chung <tausq@debian.org> * * This program is free software; you can redistribute it and/or modify @@ -38,6 +38,7 @@ #include <linux/kernel_stat.h> #include <linux/reboot.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/ctype.h> #include <linux/blkdev.h> #include <linux/workqueue.h> @@ -63,11 +64,12 @@ static unsigned int led_diskio __read_mostly = 1; static unsigned int led_lanrxtx __read_mostly = 1; static char lcd_text[32] __read_mostly; static char lcd_text_default[32] __read_mostly; +static int lcd_no_led_support __read_mostly = 0; /* KittyHawk doesn't support LED on its LCD */ static struct workqueue_struct *led_wq; -static void led_work_func(void *); -static DECLARE_WORK(led_task, led_work_func, NULL); +static void led_work_func(struct work_struct *); +static DECLARE_DELAYED_WORK(led_task, led_work_func); #if 0 #define DPRINTK(x) printk x @@ -114,7 +116,7 @@ lcd_info __attribute__((aligned(8))) __read_mostly = .lcd_width = 16, .lcd_cmd_reg_addr = KITTYHAWK_LCD_CMD, .lcd_data_reg_addr = KITTYHAWK_LCD_DATA, - .min_cmd_delay = 40, + .min_cmd_delay = 80, .reset_cmd1 = 0x80, .reset_cmd2 = 0xc0, }; @@ -134,9 +136,12 @@ static int start_task(void) /* Display the default text now */ if (led_type == LED_HASLCD) lcd_print( lcd_text_default ); + /* KittyHawk has no LED support on its LCD */ + if (lcd_no_led_support) return 0; + /* Create the work queue and queue the LED task */ led_wq = create_singlethread_workqueue("led_wq"); - queue_work(led_wq, &led_task); + queue_delayed_work(led_wq, &led_task, 0); return 0; } @@ -147,60 +152,49 @@ device_initcall(start_task); static void (*led_func_ptr) (unsigned char) __read_mostly; #ifdef CONFIG_PROC_FS -static int led_proc_read(char *page, char **start, off_t off, int count, - int *eof, void *data) +static int led_proc_show(struct seq_file *m, void *v) { - char *out = page; - int len; - - switch ((long)data) + switch ((long)m->private) { case LED_NOLCD: - out += sprintf(out, "Heartbeat: %d\n", led_heartbeat); - out += sprintf(out, "Disk IO: %d\n", led_diskio); - out += sprintf(out, "LAN Rx/Tx: %d\n", led_lanrxtx); + seq_printf(m, "Heartbeat: %d\n", led_heartbeat); + seq_printf(m, "Disk IO: %d\n", led_diskio); + seq_printf(m, "LAN Rx/Tx: %d\n", led_lanrxtx); break; case LED_HASLCD: - out += sprintf(out, "%s\n", lcd_text); + seq_printf(m, "%s\n", lcd_text); break; default: - *eof = 1; return 0; } + return 0; +} - len = out - page - off; - if (len < count) { - *eof = 1; - if (len <= 0) return 0; - } else { - len = count; - } - *start = page + off; - return len; +static int led_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, led_proc_show, PDE_DATA(inode)); } -static int led_proc_write(struct file *file, const char *buf, - unsigned long count, void *data) + +static ssize_t led_proc_write(struct file *file, const char *buf, + size_t count, loff_t *pos) { - char *cur, lbuf[count + 1]; + void *data = PDE_DATA(file_inode(file)); + char *cur, lbuf[32]; int d; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - memset(lbuf, 0, count + 1); + if (count >= sizeof(lbuf)) + count = sizeof(lbuf)-1; if (copy_from_user(lbuf, buf, count)) return -EFAULT; + lbuf[count] = 0; cur = lbuf; - /* skip initial spaces */ - while (*cur && isspace(*cur)) - { - cur++; - } - switch ((long)data) { case LED_NOLCD: @@ -240,6 +234,15 @@ parse_error: return -EINVAL; } +static const struct file_operations led_proc_fops = { + .owner = THIS_MODULE, + .open = led_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = led_proc_write, +}; + static int __init led_create_procfs(void) { struct proc_dir_entry *proc_pdc_root = NULL; @@ -249,24 +252,19 @@ static int __init led_create_procfs(void) proc_pdc_root = proc_mkdir("pdc", 0); if (!proc_pdc_root) return -1; - proc_pdc_root->owner = THIS_MODULE; - ent = create_proc_entry("led", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root); - if (!ent) return -1; - ent->nlink = 1; - ent->data = (void *)LED_NOLCD; /* LED */ - ent->read_proc = led_proc_read; - ent->write_proc = led_proc_write; - ent->owner = THIS_MODULE; + + if (!lcd_no_led_support) + { + ent = proc_create_data("led", S_IRUGO|S_IWUSR, proc_pdc_root, + &led_proc_fops, (void *)LED_NOLCD); /* LED */ + if (!ent) return -1; + } if (led_type == LED_HASLCD) { - ent = create_proc_entry("lcd", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root); + ent = proc_create_data("lcd", S_IRUGO|S_IWUSR, proc_pdc_root, + &led_proc_fops, (void *)LED_HASLCD); /* LCD */ if (!ent) return -1; - ent->nlink = 1; - ent->data = (void *)LED_HASLCD; /* LCD */ - ent->read_proc = led_proc_read; - ent->write_proc = led_proc_write; - ent->owner = THIS_MODULE; } return 0; @@ -356,32 +354,28 @@ static __inline__ int led_get_net_activity(void) #ifndef CONFIG_NET return 0; #else - static unsigned long rx_total_last, tx_total_last; - unsigned long rx_total, tx_total; + static u64 rx_total_last, tx_total_last; + u64 rx_total, tx_total; struct net_device *dev; int retval; rx_total = tx_total = 0; - /* we are running as a workqueue task, so locking dev_base - * for reading should be OK */ - read_lock(&dev_base_lock); + /* we are running as a workqueue task, so we can use an RCU lookup */ rcu_read_lock(); - for (dev = dev_base; dev; dev = dev->next) { - struct net_device_stats *stats; + for_each_netdev_rcu(&init_net, dev) { + const struct rtnl_link_stats64 *stats; + struct rtnl_link_stats64 temp; struct in_device *in_dev = __in_dev_get_rcu(dev); if (!in_dev || !in_dev->ifa_list) continue; - if (LOOPBACK(in_dev->ifa_list->ifa_local)) - continue; - if (!dev->get_stats) + if (ipv4_is_loopback(in_dev->ifa_list->ifa_local)) continue; - stats = dev->get_stats(dev); + stats = dev_get_stats(dev, &temp); rx_total += stats->rx_packets; tx_total += stats->tx_packets; } rcu_read_unlock(); - read_unlock(&dev_base_lock); retval = 0; @@ -443,7 +437,7 @@ static __inline__ int led_get_diskio_activity(void) #define LED_UPDATE_INTERVAL (1 + (HZ*19/1000)) -static void led_work_func (void *unused) +static void led_work_func (struct work_struct *unused) { static unsigned long last_jiffies; static unsigned long count_HZ; /* counter in range 0..HZ */ @@ -473,9 +467,20 @@ static void led_work_func (void *unused) if (likely(led_lanrxtx)) currentleds |= led_get_net_activity(); if (likely(led_diskio)) currentleds |= led_get_diskio_activity(); - /* blink all LEDs twice a second if we got an Oops (HPMC) */ - if (unlikely(oops_in_progress)) - currentleds = (count_HZ<=(HZ/2)) ? 0 : 0xff; + /* blink LEDs if we got an Oops (HPMC) */ + if (unlikely(oops_in_progress)) { + if (boot_cpu_data.cpu_type >= pcxl2) { + /* newer machines don't have loadavg. LEDs, so we + * let all LEDs blink twice per second instead */ + currentleds = (count_HZ <= (HZ/2)) ? 0 : 0xff; + } else { + /* old machines: blink loadavg. LEDs twice per second */ + if (count_HZ <= (HZ/2)) + currentleds &= ~(LED4|LED5|LED6|LED7); + else + currentleds |= (LED4|LED5|LED6|LED7); + } + } if (currentleds != lastleds) { @@ -521,7 +526,7 @@ static int led_halt(struct notifier_block *nb, unsigned long event, void *buf) /* Cancel the work item and delete the queue */ if (led_wq) { - cancel_rearming_delayed_workqueue(led_wq, &led_task); + cancel_delayed_work_sync(&led_task); destroy_workqueue(led_wq); led_wq = NULL; } @@ -579,7 +584,7 @@ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long d default: printk(KERN_ERR "%s: Wrong LCD/LED model %d !\n", - __FUNCTION__, lcd_info.model); + __func__, lcd_info.model); return 1; } @@ -590,7 +595,7 @@ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long d /* Ensure the work is queued */ if (led_wq) { - queue_work(led_wq, &led_task); + queue_delayed_work(led_wq, &led_task, 0); } return 0; @@ -631,7 +636,7 @@ void __init register_led_regions(void) ** avoid a race condition while writing the CMD/DATA register pair. ** */ -int lcd_print( char *str ) +int lcd_print( const char *str ) { int i; @@ -640,7 +645,7 @@ int lcd_print( char *str ) /* temporarily disable the led work task */ if (led_wq) - cancel_rearming_delayed_workqueue(led_wq, &led_task); + cancel_delayed_work_sync(&led_task); /* copy display string to buffer for procfs */ strlcpy(lcd_text, str, sizeof(lcd_text)); @@ -660,7 +665,7 @@ int lcd_print( char *str ) /* re-queue the work */ if (led_wq) { - queue_work(led_wq, &led_task); + queue_delayed_work(led_wq, &led_task, 0); } return lcd_info.lcd_width; @@ -684,7 +689,7 @@ int __init led_init(void) int ret; snprintf(lcd_text_default, sizeof(lcd_text_default), - "Linux %s", system_utsname.release); + "Linux %s", init_utsname()->release); /* Work around the buggy PDC of KittyHawk-machines */ switch (CPU_HVERSION) { @@ -695,6 +700,7 @@ int __init led_init(void) case 0x58B: /* KittyHawk DC2 100 (K200) */ printk(KERN_INFO "%s: KittyHawk-Machine (hversion 0x%x) found, " "LED detection skipped.\n", __FILE__, CPU_HVERSION); + lcd_no_led_support = 1; goto found; /* use the preinitialized values of lcd_info */ } diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index ea1b7a63598..0f54ab6260d 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c @@ -120,15 +120,15 @@ struct pdcspath_entry pdcspath_entry_##_name = { \ }; #define PDCS_ATTR(_name, _mode, _show, _store) \ -struct subsys_attribute pdcs_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ +struct kobj_attribute pdcs_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = _mode}, \ .show = _show, \ .store = _store, \ }; #define PATHS_ATTR(_name, _mode, _show, _store) \ struct pdcspath_attribute paths_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ + .attr = {.name = __stringify(_name), .mode = _mode}, \ .show = _show, \ .store = _store, \ }; @@ -141,7 +141,7 @@ struct pdcspath_attribute paths_attr_##_name = { \ * @entry: A pointer to an allocated pdcspath_entry. * * The general idea is that you don't read from the Stable Storage every time - * you access the files provided by the facilites. We store a copy of the + * you access the files provided by the facilities. We store a copy of the * content of the stable storage WRT various paths in these structs. We read * these structs when reading the files, and we will write to these structs when * writing to the files, and only then write them back to the Stable Storage. @@ -212,12 +212,10 @@ pdcspath_store(struct pdcspath_entry *entry) entry, devpath, entry->addr); /* addr, devpath and count must be word aligned */ - if (pdc_stable_write(entry->addr, devpath, sizeof(*devpath)) != PDC_OK) { - printk(KERN_ERR "%s: an error occured when writing to PDC.\n" + if (pdc_stable_write(entry->addr, devpath, sizeof(*devpath)) != PDC_OK) + WARN(1, KERN_ERR "%s: an error occurred when writing to PDC.\n" "It is likely that the Stable Storage data has been corrupted.\n" "Please check it carefully upon next reboot.\n", __func__); - WARN_ON(1); - } /* kobject is already registered */ entry->ready = 2; @@ -282,6 +280,7 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun unsigned short i; char in[count+1], *temp; struct device *dev; + int ret; if (!entry || !buf || !count) return -EINVAL; @@ -333,7 +332,9 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun /* Update the symlink to the real device */ sysfs_remove_link(&entry->kobj, "device"); - sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); + ret = sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); + WARN_ON(ret); + write_unlock(&entry->rw_lock); printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" path to \"%s\"\n", @@ -367,7 +368,7 @@ pdcspath_layer_read(struct pdcspath_entry *entry, char *buf) if (!i) /* entry is not ready */ return -ENODATA; - for (i = 0; devpath->layers[i] && (likely(i < 6)); i++) + for (i = 0; i < 6 && devpath->layers[i]; i++) out += sprintf(out, "%u ", devpath->layers[i]); out += sprintf(out, "\n"); @@ -478,7 +479,7 @@ pdcspath_attr_store(struct kobject *kobj, struct attribute *attr, return ret; } -static struct sysfs_ops pdcspath_attr_ops = { +static const struct sysfs_ops pdcspath_attr_ops = { .show = pdcspath_attr_show, .store = pdcspath_attr_store, }; @@ -520,17 +521,17 @@ static struct pdcspath_entry *pdcspath_entries[] = { /** * pdcs_size_read - Stable Storage size output. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The output buffer to write to. */ -static ssize_t -pdcs_size_read(struct subsystem *entry, char *buf) +static ssize_t pdcs_size_read(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) { char *out = buf; - - if (!entry || !buf) + + if (!buf) return -EINVAL; - + /* show the size of the stable storage */ out += sprintf(out, "%ld\n", pdcs_size); @@ -539,17 +540,17 @@ pdcs_size_read(struct subsystem *entry, char *buf) /** * pdcs_auto_read - Stable Storage autoboot/search flag output. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The output buffer to write to. * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag */ -static ssize_t -pdcs_auto_read(struct subsystem *entry, char *buf, int knob) +static ssize_t pdcs_auto_read(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf, int knob) { char *out = buf; struct pdcspath_entry *pathentry; - if (!entry || !buf) + if (!buf) return -EINVAL; /* Current flags are stored in primary boot path entry */ @@ -565,40 +566,37 @@ pdcs_auto_read(struct subsystem *entry, char *buf, int knob) /** * pdcs_autoboot_read - Stable Storage autoboot flag output. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The output buffer to write to. */ -static inline ssize_t -pdcs_autoboot_read(struct subsystem *entry, char *buf) +static ssize_t pdcs_autoboot_read(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { - return pdcs_auto_read(entry, buf, PF_AUTOBOOT); + return pdcs_auto_read(kobj, attr, buf, PF_AUTOBOOT); } /** * pdcs_autosearch_read - Stable Storage autoboot flag output. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The output buffer to write to. */ -static inline ssize_t -pdcs_autosearch_read(struct subsystem *entry, char *buf) +static ssize_t pdcs_autosearch_read(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { - return pdcs_auto_read(entry, buf, PF_AUTOSEARCH); + return pdcs_auto_read(kobj, attr, buf, PF_AUTOSEARCH); } /** * pdcs_timer_read - Stable Storage timer count output (in seconds). - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The output buffer to write to. * * The value of the timer field correponds to a number of seconds in powers of 2. */ -static ssize_t -pdcs_timer_read(struct subsystem *entry, char *buf) +static ssize_t pdcs_timer_read(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { char *out = buf; struct pdcspath_entry *pathentry; - if (!entry || !buf) + if (!buf) return -EINVAL; /* Current flags are stored in primary boot path entry */ @@ -615,15 +613,14 @@ pdcs_timer_read(struct subsystem *entry, char *buf) /** * pdcs_osid_read - Stable Storage OS ID register output. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The output buffer to write to. */ -static ssize_t -pdcs_osid_read(struct subsystem *entry, char *buf) +static ssize_t pdcs_osid_read(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { char *out = buf; - if (!entry || !buf) + if (!buf) return -EINVAL; out += sprintf(out, "%s dependent data (0x%.4x)\n", @@ -634,18 +631,17 @@ pdcs_osid_read(struct subsystem *entry, char *buf) /** * pdcs_osdep1_read - Stable Storage OS-Dependent data area 1 output. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The output buffer to write to. * * This can hold 16 bytes of OS-Dependent data. */ -static ssize_t -pdcs_osdep1_read(struct subsystem *entry, char *buf) +static ssize_t pdcs_osdep1_read(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { char *out = buf; u32 result[4]; - if (!entry || !buf) + if (!buf) return -EINVAL; if (pdc_stable_read(PDCS_ADDR_OSD1, &result, sizeof(result)) != PDC_OK) @@ -661,18 +657,17 @@ pdcs_osdep1_read(struct subsystem *entry, char *buf) /** * pdcs_diagnostic_read - Stable Storage Diagnostic register output. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The output buffer to write to. * * I have NFC how to interpret the content of that register ;-). */ -static ssize_t -pdcs_diagnostic_read(struct subsystem *entry, char *buf) +static ssize_t pdcs_diagnostic_read(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { char *out = buf; u32 result; - if (!entry || !buf) + if (!buf) return -EINVAL; /* get diagnostic */ @@ -686,18 +681,17 @@ pdcs_diagnostic_read(struct subsystem *entry, char *buf) /** * pdcs_fastsize_read - Stable Storage FastSize register output. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The output buffer to write to. * * This register holds the amount of system RAM to be tested during boot sequence. */ -static ssize_t -pdcs_fastsize_read(struct subsystem *entry, char *buf) +static ssize_t pdcs_fastsize_read(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { char *out = buf; u32 result; - if (!entry || !buf) + if (!buf) return -EINVAL; /* get fast-size */ @@ -715,13 +709,12 @@ pdcs_fastsize_read(struct subsystem *entry, char *buf) /** * pdcs_osdep2_read - Stable Storage OS-Dependent data area 2 output. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The output buffer to write to. * * This can hold pdcs_size - 224 bytes of OS-Dependent data, when available. */ -static ssize_t -pdcs_osdep2_read(struct subsystem *entry, char *buf) +static ssize_t pdcs_osdep2_read(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { char *out = buf; unsigned long size; @@ -733,7 +726,7 @@ pdcs_osdep2_read(struct subsystem *entry, char *buf) size = pdcs_size - 224; - if (!entry || !buf) + if (!buf) return -EINVAL; for (i=0; i<size; i+=4) { @@ -748,7 +741,6 @@ pdcs_osdep2_read(struct subsystem *entry, char *buf) /** * pdcs_auto_write - This function handles autoboot/search flag modifying. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag @@ -757,8 +749,9 @@ pdcs_osdep2_read(struct subsystem *entry, char *buf) * We expect a precise syntax: * \"n\" (n == 0 or 1) to toggle AutoBoot Off or On */ -static ssize_t -pdcs_auto_write(struct subsystem *entry, const char *buf, size_t count, int knob) +static ssize_t pdcs_auto_write(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, + size_t count, int knob) { struct pdcspath_entry *pathentry; unsigned char flags; @@ -768,7 +761,7 @@ pdcs_auto_write(struct subsystem *entry, const char *buf, size_t count, int knob if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (!entry || !buf || !count) + if (!buf || !count) return -EINVAL; /* We'll use a local copy of buf */ @@ -784,12 +777,9 @@ pdcs_auto_write(struct subsystem *entry, const char *buf, size_t count, int knob read_unlock(&pathentry->rw_lock); DPRINTK("%s: flags before: 0x%X\n", __func__, flags); - - temp = in; - - while (*temp && isspace(*temp)) - temp++; - + + temp = skip_spaces(in); + c = *temp++ - '0'; if ((c != 0) && (c != 1)) goto parse_error; @@ -823,7 +813,6 @@ parse_error: /** * pdcs_autoboot_write - This function handles autoboot flag modifying. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @@ -831,15 +820,15 @@ parse_error: * We expect a precise syntax: * \"n\" (n == 0 or 1) to toggle AutoSearch Off or On */ -static inline ssize_t -pdcs_autoboot_write(struct subsystem *entry, const char *buf, size_t count) +static ssize_t pdcs_autoboot_write(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) { - return pdcs_auto_write(entry, buf, count, PF_AUTOBOOT); + return pdcs_auto_write(kobj, attr, buf, count, PF_AUTOBOOT); } /** * pdcs_autosearch_write - This function handles autosearch flag modifying. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @@ -847,15 +836,15 @@ pdcs_autoboot_write(struct subsystem *entry, const char *buf, size_t count) * We expect a precise syntax: * \"n\" (n == 0 or 1) to toggle AutoSearch Off or On */ -static inline ssize_t -pdcs_autosearch_write(struct subsystem *entry, const char *buf, size_t count) +static ssize_t pdcs_autosearch_write(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) { - return pdcs_auto_write(entry, buf, count, PF_AUTOSEARCH); + return pdcs_auto_write(kobj, attr, buf, count, PF_AUTOSEARCH); } /** * pdcs_osdep1_write - Stable Storage OS-Dependent data area 1 input. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @@ -863,15 +852,16 @@ pdcs_autosearch_write(struct subsystem *entry, const char *buf, size_t count) * write approach. It's up to userspace to deal with it when constructing * its input buffer. */ -static ssize_t -pdcs_osdep1_write(struct subsystem *entry, const char *buf, size_t count) +static ssize_t pdcs_osdep1_write(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) { u8 in[16]; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (!entry || !buf || !count) + if (!buf || !count) return -EINVAL; if (unlikely(pdcs_osid != OS_ID_LINUX)) @@ -892,7 +882,6 @@ pdcs_osdep1_write(struct subsystem *entry, const char *buf, size_t count) /** * pdcs_osdep2_write - Stable Storage OS-Dependent data area 2 input. - * @entry: An allocated and populated subsytem struct. We don't use it tho. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @@ -900,8 +889,9 @@ pdcs_osdep1_write(struct subsystem *entry, const char *buf, size_t count) * byte-by-byte write approach. It's up to userspace to deal with it when * constructing its input buffer. */ -static ssize_t -pdcs_osdep2_write(struct subsystem *entry, const char *buf, size_t count) +static ssize_t pdcs_osdep2_write(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) { unsigned long size; unsigned short i; @@ -910,7 +900,7 @@ pdcs_osdep2_write(struct subsystem *entry, const char *buf, size_t count) if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (!entry || !buf || !count) + if (!buf || !count) return -EINVAL; if (unlikely(pdcs_size <= 224)) @@ -948,21 +938,25 @@ static PDCS_ATTR(diagnostic, 0400, pdcs_diagnostic_read, NULL); static PDCS_ATTR(fastsize, 0400, pdcs_fastsize_read, NULL); static PDCS_ATTR(osdep2, 0600, pdcs_osdep2_read, pdcs_osdep2_write); -static struct subsys_attribute *pdcs_subsys_attrs[] = { - &pdcs_attr_size, - &pdcs_attr_autoboot, - &pdcs_attr_autosearch, - &pdcs_attr_timer, - &pdcs_attr_osid, - &pdcs_attr_osdep1, - &pdcs_attr_diagnostic, - &pdcs_attr_fastsize, - &pdcs_attr_osdep2, +static struct attribute *pdcs_subsys_attrs[] = { + &pdcs_attr_size.attr, + &pdcs_attr_autoboot.attr, + &pdcs_attr_autosearch.attr, + &pdcs_attr_timer.attr, + &pdcs_attr_osid.attr, + &pdcs_attr_osdep1.attr, + &pdcs_attr_diagnostic.attr, + &pdcs_attr_fastsize.attr, + &pdcs_attr_osdep2.attr, NULL, }; -static decl_subsys(paths, &ktype_pdcspath, NULL); -static decl_subsys(stable, NULL, NULL); +static struct attribute_group pdcs_attr_group = { + .attrs = pdcs_subsys_attrs, +}; + +static struct kobject *stable_kobj; +static struct kset *paths_kset; /** * pdcs_register_pathentries - Prepares path entries kobjects for sysfs usage. @@ -992,21 +986,24 @@ pdcs_register_pathentries(void) if (err < 0) continue; - if ((err = kobject_set_name(&entry->kobj, "%s", entry->name))) + entry->kobj.kset = paths_kset; + err = kobject_init_and_add(&entry->kobj, &ktype_pdcspath, NULL, + "%s", entry->name); + if (err) return err; - kobj_set_kset_s(entry, paths_subsys); - if ((err = kobject_register(&entry->kobj))) - return err; - + /* kobject is now registered */ write_lock(&entry->rw_lock); entry->ready = 2; /* Add a nice symlink to the real device */ - if (entry->dev) - sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); + if (entry->dev) { + err = sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); + WARN_ON(err); + } write_unlock(&entry->rw_lock); + kobject_uevent(&entry->kobj, KOBJ_ADD); } return 0; @@ -1024,7 +1021,7 @@ pdcs_unregister_pathentries(void) for (i = 0; (entry = pdcspath_entries[i]); i++) { read_lock(&entry->rw_lock); if (entry->ready >= 2) - kobject_unregister(&entry->kobj); + kobject_put(&entry->kobj); read_unlock(&entry->rw_lock); } } @@ -1036,8 +1033,7 @@ pdcs_unregister_pathentries(void) static int __init pdc_stable_init(void) { - struct subsys_attribute *attr; - int i, rc = 0, error = 0; + int rc = 0, error = 0; u32 result; /* find the size of the stable storage */ @@ -1057,21 +1053,24 @@ pdc_stable_init(void) /* the actual result is 16 bits away */ pdcs_osid = (u16)(result >> 16); - /* For now we'll register the stable subsys within this driver */ - if ((rc = firmware_register(&stable_subsys))) + /* For now we'll register the directory at /sys/firmware/stable */ + stable_kobj = kobject_create_and_add("stable", firmware_kobj); + if (!stable_kobj) { + rc = -ENOMEM; goto fail_firmreg; + } /* Don't forget the root entries */ - for (i = 0; (attr = pdcs_subsys_attrs[i]) && !error; i++) - if (attr->show) - error = subsys_create_file(&stable_subsys, attr); - - /* register the paths subsys as a subsystem of stable subsys */ - kset_set_kset_s(&paths_subsys, stable_subsys); - if ((rc = subsystem_register(&paths_subsys))) - goto fail_subsysreg; + error = sysfs_create_group(stable_kobj, &pdcs_attr_group); - /* now we create all "files" for the paths subsys */ + /* register the paths kset as a child of the stable kset */ + paths_kset = kset_create_and_add("paths", NULL, stable_kobj); + if (!paths_kset) { + rc = -ENOMEM; + goto fail_ksetreg; + } + + /* now we create all "files" for the paths kset */ if ((rc = pdcs_register_pathentries())) goto fail_pdcsreg; @@ -1079,10 +1078,10 @@ pdc_stable_init(void) fail_pdcsreg: pdcs_unregister_pathentries(); - subsystem_unregister(&paths_subsys); + kset_unregister(paths_kset); -fail_subsysreg: - firmware_unregister(&stable_subsys); +fail_ksetreg: + kobject_put(stable_kobj); fail_firmreg: printk(KERN_INFO PDCS_PREFIX " bailing out\n"); @@ -1093,9 +1092,8 @@ static void __exit pdc_stable_exit(void) { pdcs_unregister_pathentries(); - subsystem_unregister(&paths_subsys); - - firmware_unregister(&stable_subsys); + kset_unregister(paths_kset); + kobject_put(stable_kobj); } diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c index fad5a33bf0f..90cca5e3805 100644 --- a/drivers/parisc/power.c +++ b/drivers/parisc/power.c @@ -1,8 +1,8 @@ /* - * linux/arch/parisc/kernel/power.c + * linux/drivers/parisc/power.c * HP PARISC soft power switch support driver * - * Copyright (c) 2001-2005 Helge Deller <deller@gmx.de> + * Copyright (c) 2001-2007 Helge Deller <deller@gmx.de> * All rights reserved. * * @@ -29,7 +29,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * * - * * HINT: * Support of the soft power switch button may be enabled or disabled at * runtime through the "/proc/sys/kernel/power" procfs entry. @@ -38,34 +37,29 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> -#include <linux/string.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> +#include <linux/kthread.h> +#include <linux/pm.h> #include <asm/pdc.h> #include <asm/io.h> #include <asm/led.h> -#include <asm/uaccess.h> +#define DRIVER_NAME "powersw" +#define KTHREAD_NAME "kpowerswd" -#ifdef DEBUG -# define DPRINTK(x...) printk(x) -#else -# define DPRINTK(x...) -#endif - - -/* filename in /proc which can be used to enable/disable the power switch */ -#define SYSCTL_FILENAME "sys/kernel/power" +/* how often should the power button be polled ? */ +#define POWERSWITCH_POLL_PER_SEC 2 +/* how long does the power button needs to be down until we react ? */ +#define POWERSWITCH_DOWN_SEC 2 +/* assembly code to access special registers */ +/* taken from PCXL ERS page 82 */ #define DIAG_CODE(code) (0x14000000 + ((code)<<5)) -/* this will go to processor.h or any other place... */ -/* taken from PCXL ERS page 82 */ #define MFCPU_X(rDiagReg, t_ch, t_th, code) \ (DIAG_CODE(code) + ((rDiagReg)<<21) + ((t_ch)<<16) + ((t_th)<<0) ) @@ -76,112 +70,95 @@ #define __getDIAG(dr) ( { \ register unsigned long __res asm("r28");\ __asm__ __volatile__ ( \ - ".word %1\n nop\n" : "=&r" (__res) : "i" (MFCPU_T(dr,28)) \ + ".word %1" : "=&r" (__res) : "i" (MFCPU_T(dr,28) ) \ ); \ __res; \ } ) - -static void deferred_poweroff(void *dummy) -{ - extern int cad_pid; /* from kernel/sys.c */ - if (kill_proc(cad_pid, SIGINT, 1)) { - /* just in case killing init process failed */ - machine_power_off(); - } -} - -/* - * This function gets called from interrupt context. - * As it's called within an interrupt, it wouldn't sync if we don't - * use schedule_work(). - */ - -static DECLARE_WORK(poweroff_work, deferred_poweroff, NULL); - -static void poweroff(void) -{ - static int powering_off __read_mostly; - - if (powering_off) - return; - - powering_off++; - schedule_work(&poweroff_work); -} - - -/* local time-counter for shutdown */ +/* local shutdown counter */ static int shutdown_timer __read_mostly; /* check, give feedback and start shutdown after one second */ static void process_shutdown(void) { if (shutdown_timer == 0) - DPRINTK(KERN_INFO "Shutdown requested...\n"); + printk(KERN_ALERT KTHREAD_NAME ": Shutdown requested...\n"); shutdown_timer++; /* wait until the button was pressed for 1 second */ - if (shutdown_timer == HZ) { -#if defined (DEBUG) || defined(CONFIG_CHASSIS_LCD_LED) - static char msg[] = "Shutting down..."; -#endif - DPRINTK(KERN_INFO "%s\n", msg); + if (shutdown_timer == (POWERSWITCH_DOWN_SEC*POWERSWITCH_POLL_PER_SEC)) { + static const char msg[] = "Shutting down..."; + printk(KERN_INFO KTHREAD_NAME ": %s\n", msg); lcd_print(msg); - poweroff(); + + /* send kill signal */ + if (kill_cad_pid(SIGINT, 1)) { + /* just in case killing init process failed */ + if (pm_power_off) + pm_power_off(); + } } } -/* main power switch tasklet struct (scheduled from time.c) */ -DECLARE_TASKLET_DISABLED(power_tasklet, NULL, 0); +/* main power switch task struct */ +static struct task_struct *power_task; + +/* filename in /proc which can be used to enable/disable the power switch */ +#define SYSCTL_FILENAME "sys/kernel/power" /* soft power switch enabled/disabled */ int pwrsw_enabled __read_mostly = 1; -/* - * On gecko style machines (e.g. 712/xx and 715/xx) - * the power switch status is stored in Bit 0 ("the highest bit") - * of CPU diagnose register 25. - * - */ -static void gecko_tasklet_func(unsigned long unused) +/* main kernel thread worker. It polls the button state */ +static int kpowerswd(void *param) { - if (unlikely(!pwrsw_enabled)) - return; - - if (__getDIAG(25) & 0x80000000) { - /* power switch button not pressed or released again */ - /* Warning: Some machines do never reset this DIAG flag! */ - shutdown_timer = 0; - } else { - process_shutdown(); - } -} - + __set_current_state(TASK_RUNNING); + + do { + int button_not_pressed; + unsigned long soft_power_reg = (unsigned long) param; + + schedule_timeout_interruptible(pwrsw_enabled ? HZ : HZ/POWERSWITCH_POLL_PER_SEC); + __set_current_state(TASK_RUNNING); + + if (unlikely(!pwrsw_enabled)) + continue; + + if (soft_power_reg) { + /* + * Non-Gecko-style machines: + * Check the power switch status which is read from the + * real I/O location at soft_power_reg. + * Bit 31 ("the lowest bit) is the status of the power switch. + * This bit is "1" if the button is NOT pressed. + */ + button_not_pressed = (gsc_readl(soft_power_reg) & 0x1); + } else { + /* + * On gecko style machines (e.g. 712/xx and 715/xx) + * the power switch status is stored in Bit 0 ("the highest bit") + * of CPU diagnose register 25. + * Warning: Some machines never reset the DIAG flag, even if + * the button has been released again. + */ + button_not_pressed = (__getDIAG(25) & 0x80000000); + } + + if (likely(button_not_pressed)) { + if (unlikely(shutdown_timer && /* avoid writing if not necessary */ + shutdown_timer < (POWERSWITCH_DOWN_SEC*POWERSWITCH_POLL_PER_SEC))) { + shutdown_timer = 0; + printk(KERN_INFO KTHREAD_NAME ": Shutdown request aborted.\n"); + } + } else + process_shutdown(); + + + } while (!kthread_should_stop()); - -/* - * Check the power switch status which is read from the - * real I/O location at soft_power_reg. - * Bit 31 ("the lowest bit) is the status of the power switch. - */ - -static void polling_tasklet_func(unsigned long soft_power_reg) -{ - unsigned long current_status; - - if (unlikely(!pwrsw_enabled)) - return; - - current_status = gsc_readl(soft_power_reg); - if (current_status & 0x1) { - /* power switch button not pressed */ - shutdown_timer = 0; - } else { - process_shutdown(); - } + return 0; } @@ -189,7 +166,7 @@ static void polling_tasklet_func(unsigned long soft_power_reg) * powerfail interruption handler (irq IRQ_FROM_REGION(CPU_IRQ_REGION)+2) */ #if 0 -static void powerfail_interrupt(int code, void *x, struct pt_regs *regs) +static void powerfail_interrupt(int code, void *x) { printk(KERN_CRIT "POWERFAIL INTERRUPTION !\n"); poweroff(); @@ -221,7 +198,7 @@ static struct notifier_block parisc_panic_block = { static int __init power_init(void) { unsigned long ret; - unsigned long soft_power_reg = 0; + unsigned long soft_power_reg; #if 0 request_irq( IRQ_FROM_REGION(CPU_IRQ_REGION)+2, &powerfail_interrupt, @@ -236,44 +213,44 @@ static int __init power_init(void) soft_power_reg = -1UL; switch (soft_power_reg) { - case 0: printk(KERN_INFO "Gecko-style soft power switch enabled.\n"); - power_tasklet.func = gecko_tasklet_func; + case 0: printk(KERN_INFO DRIVER_NAME ": Gecko-style soft power switch enabled.\n"); break; - case -1UL: printk(KERN_INFO "Soft power switch support not available.\n"); + case -1UL: printk(KERN_INFO DRIVER_NAME ": Soft power switch support not available.\n"); return -ENODEV; - default: printk(KERN_INFO "Soft power switch enabled, polling @ 0x%08lx.\n", + default: printk(KERN_INFO DRIVER_NAME ": Soft power switch at 0x%08lx enabled.\n", soft_power_reg); - power_tasklet.data = soft_power_reg; - power_tasklet.func = polling_tasklet_func; + } + + power_task = kthread_run(kpowerswd, (void*)soft_power_reg, KTHREAD_NAME); + if (IS_ERR(power_task)) { + printk(KERN_ERR DRIVER_NAME ": thread creation failed. Driver not loaded.\n"); + pdc_soft_power_button(0); + return -EIO; } /* Register a call for panic conditions. */ atomic_notifier_chain_register(&panic_notifier_list, &parisc_panic_block); - tasklet_enable(&power_tasklet); - return 0; } static void __exit power_exit(void) { - if (!power_tasklet.func) - return; + kthread_stop(power_task); - tasklet_disable(&power_tasklet); atomic_notifier_chain_unregister(&panic_notifier_list, &parisc_panic_block); - power_tasklet.func = NULL; + pdc_soft_power_button(0); } -module_init(power_init); +arch_initcall(power_init); module_exit(power_exit); -MODULE_AUTHOR("Helge Deller"); +MODULE_AUTHOR("Helge Deller <deller@gmx.de>"); MODULE_DESCRIPTION("Soft power switch driver"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 8b473281551..1ff1b67e8b2 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -28,6 +28,8 @@ #include <linux/mm.h> #include <linux/string.h> #include <linux/pci.h> +#include <linux/scatterlist.h> +#include <linux/iommu-helper.h> #include <asm/byteorder.h> #include <asm/io.h> @@ -37,23 +39,18 @@ #include <linux/proc_fs.h> #include <linux/seq_file.h> +#include <linux/module.h> +#include <asm/ropes.h> +#include <asm/mckinley.h> /* for proc_mckinley_root */ #include <asm/runway.h> /* for proc_runway_root */ +#include <asm/page.h> /* for PAGE0 */ #include <asm/pdc.h> /* for PDC_MODEL_* */ #include <asm/pdcpat.h> /* for is_pdc_pat() */ #include <asm/parisc-device.h> - -/* declared in arch/parisc/kernel/setup.c */ -extern struct proc_dir_entry * proc_mckinley_root; - #define MODULE_NAME "SBA" -#ifdef CONFIG_PROC_FS -/* depends on proc fs support. But costs CPU performance */ -#undef SBA_COLLECT_STATS -#endif - /* ** The number of debug flags is a clue - this code is fragile. ** Don't even think about messing with it unless you have @@ -92,202 +89,12 @@ extern struct proc_dir_entry * proc_mckinley_root; #define DBG_RES(x...) #endif -#if defined(CONFIG_64BIT) -/* "low end" PA8800 machines use ZX1 chipset: PAT PDC and only run 64-bit */ -#define ZX1_SUPPORT -#endif - #define SBA_INLINE __inline__ - -/* -** The number of pdir entries to "free" before issueing -** a read to PCOM register to flush out PCOM writes. -** Interacts with allocation granularity (ie 4 or 8 entries -** allocated and free'd/purged at a time might make this -** less interesting). -*/ -#define DELAYED_RESOURCE_CNT 16 - #define DEFAULT_DMA_HINT_REG 0 -#define ASTRO_RUNWAY_PORT 0x582 -#define IKE_MERCED_PORT 0x803 -#define REO_MERCED_PORT 0x804 -#define REOG_MERCED_PORT 0x805 -#define PLUTO_MCKINLEY_PORT 0x880 - -#define SBA_FUNC_ID 0x0000 /* function id */ -#define SBA_FCLASS 0x0008 /* function class, bist, header, rev... */ - -#define IS_ASTRO(id) ((id)->hversion == ASTRO_RUNWAY_PORT) -#define IS_IKE(id) ((id)->hversion == IKE_MERCED_PORT) -#define IS_PLUTO(id) ((id)->hversion == PLUTO_MCKINLEY_PORT) - -#define SBA_FUNC_SIZE 4096 /* SBA configuration function reg set */ - -#define ASTRO_IOC_OFFSET (32 * SBA_FUNC_SIZE) -#define PLUTO_IOC_OFFSET (1 * SBA_FUNC_SIZE) -/* Ike's IOC's occupy functions 2 and 3 */ -#define IKE_IOC_OFFSET(p) ((p+2) * SBA_FUNC_SIZE) - -#define IOC_CTRL 0x8 /* IOC_CTRL offset */ -#define IOC_CTRL_TC (1 << 0) /* TOC Enable */ -#define IOC_CTRL_CE (1 << 1) /* Coalesce Enable */ -#define IOC_CTRL_DE (1 << 2) /* Dillon Enable */ -#define IOC_CTRL_RM (1 << 8) /* Real Mode */ -#define IOC_CTRL_NC (1 << 9) /* Non Coherent Mode */ -#define IOC_CTRL_D4 (1 << 11) /* Disable 4-byte coalescing */ -#define IOC_CTRL_DD (1 << 13) /* Disable distr. LMMIO range coalescing */ - -#define MAX_IOC 2 /* per Ike. Pluto/Astro only have 1. */ - -#define ROPES_PER_IOC 8 /* per Ike half or Pluto/Astro */ - - -/* -** Offsets into MBIB (Function 0 on Ike and hopefully Astro) -** Firmware programs this stuff. Don't touch it. -*/ -#define LMMIO_DIRECT0_BASE 0x300 -#define LMMIO_DIRECT0_MASK 0x308 -#define LMMIO_DIRECT0_ROUTE 0x310 - -#define LMMIO_DIST_BASE 0x360 -#define LMMIO_DIST_MASK 0x368 -#define LMMIO_DIST_ROUTE 0x370 - -#define IOS_DIST_BASE 0x390 -#define IOS_DIST_MASK 0x398 -#define IOS_DIST_ROUTE 0x3A0 - -#define IOS_DIRECT_BASE 0x3C0 -#define IOS_DIRECT_MASK 0x3C8 -#define IOS_DIRECT_ROUTE 0x3D0 - -/* -** Offsets into I/O TLB (Function 2 and 3 on Ike) -*/ -#define ROPE0_CTL 0x200 /* "regbus pci0" */ -#define ROPE1_CTL 0x208 -#define ROPE2_CTL 0x210 -#define ROPE3_CTL 0x218 -#define ROPE4_CTL 0x220 -#define ROPE5_CTL 0x228 -#define ROPE6_CTL 0x230 -#define ROPE7_CTL 0x238 - -#define IOC_ROPE0_CFG 0x500 /* pluto only */ -#define IOC_ROPE_AO 0x10 /* Allow "Relaxed Ordering" */ - - - -#define HF_ENABLE 0x40 - - -#define IOC_IBASE 0x300 /* IO TLB */ -#define IOC_IMASK 0x308 -#define IOC_PCOM 0x310 -#define IOC_TCNFG 0x318 -#define IOC_PDIR_BASE 0x320 - -/* AGP GART driver looks for this */ -#define SBA_IOMMU_COOKIE 0x0000badbadc0ffeeUL - - -/* -** IOC supports 4/8/16/64KB page sizes (see TCNFG register) -** It's safer (avoid memory corruption) to keep DMA page mappings -** equivalently sized to VM PAGE_SIZE. -** -** We really can't avoid generating a new mapping for each -** page since the Virtual Coherence Index has to be generated -** and updated for each page. -** -** PAGE_SIZE could be greater than IOVP_SIZE. But not the inverse. -*/ -#define IOVP_SIZE PAGE_SIZE -#define IOVP_SHIFT PAGE_SHIFT -#define IOVP_MASK PAGE_MASK - -#define SBA_PERF_CFG 0x708 /* Performance Counter stuff */ -#define SBA_PERF_MASK1 0x718 -#define SBA_PERF_MASK2 0x730 - - -/* -** Offsets into PCI Performance Counters (functions 12 and 13) -** Controlled by PERF registers in function 2 & 3 respectively. -*/ -#define SBA_PERF_CNT1 0x200 -#define SBA_PERF_CNT2 0x208 -#define SBA_PERF_CNT3 0x210 - - -struct ioc { - void __iomem *ioc_hpa; /* I/O MMU base address */ - char *res_map; /* resource map, bit == pdir entry */ - u64 *pdir_base; /* physical base address */ - unsigned long ibase; /* pdir IOV Space base - shared w/lba_pci */ - unsigned long imask; /* pdir IOV Space mask - shared w/lba_pci */ -#ifdef ZX1_SUPPORT - unsigned long iovp_mask; /* help convert IOVA to IOVP */ -#endif - unsigned long *res_hint; /* next avail IOVP - circular search */ - spinlock_t res_lock; - unsigned int res_bitshift; /* from the LEFT! */ - unsigned int res_size; /* size of resource map in bytes */ -#ifdef SBA_HINT_SUPPORT -/* FIXME : DMA HINTs not used */ - unsigned long hint_mask_pdir; /* bits used for DMA hints */ - unsigned int hint_shift_pdir; -#endif -#if DELAYED_RESOURCE_CNT > 0 - int saved_cnt; - struct sba_dma_pair { - dma_addr_t iova; - size_t size; - } saved[DELAYED_RESOURCE_CNT]; -#endif - -#ifdef SBA_COLLECT_STATS -#define SBA_SEARCH_SAMPLE 0x100 - unsigned long avg_search[SBA_SEARCH_SAMPLE]; - unsigned long avg_idx; /* current index into avg_search */ - unsigned long used_pages; - unsigned long msingle_calls; - unsigned long msingle_pages; - unsigned long msg_calls; - unsigned long msg_pages; - unsigned long usingle_calls; - unsigned long usingle_pages; - unsigned long usg_calls; - unsigned long usg_pages; -#endif - - /* STUFF We don't need in performance path */ - unsigned int pdir_size; /* in bytes, determined by IOV Space size */ -}; - -struct sba_device { - struct sba_device *next; /* list of SBA's in system */ - struct parisc_device *dev; /* dev found in bus walk */ - struct parisc_device_id *iodc; /* data about dev from firmware */ - const char *name; - void __iomem *sba_hpa; /* base address */ - spinlock_t sba_lock; - unsigned int flags; /* state/functionality enabled */ - unsigned int hw_rev; /* HW revision of chip */ - - struct resource chip_resv; /* MMIO reserved for chip */ - struct resource iommu_resv; /* MMIO reserved for iommu */ - - unsigned int num_ioc; /* number of on-board IOC's */ - struct ioc ioc[MAX_IOC]; -}; - - -static struct sba_device *sba_list; +struct sba_device *sba_list; +EXPORT_SYMBOL_GPL(sba_list); static unsigned long ioc_needs_fdc = 0; @@ -300,12 +107,16 @@ static unsigned long piranha_bad_128k = 0; /* Looks nice and keeps the compiler happy */ #define SBA_DEV(d) ((struct sba_device *) (d)) +#ifdef CONFIG_AGP_PARISC +#define SBA_AGP_SUPPORT +#endif /*CONFIG_AGP_PARISC*/ + #ifdef SBA_AGP_SUPPORT -static int reserve_sba_gart = 1; +static int sba_reserve_agpgart = 1; +module_param(sba_reserve_agpgart, int, 0444); +MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART"); #endif -#define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1)) - /************************************ ** SBA register read and write support @@ -505,6 +316,12 @@ sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents) #define RESMAP_MASK(n) (~0UL << (BITS_PER_LONG - (n))) #define RESMAP_IDX_MASK (sizeof(unsigned long) - 1) +static unsigned long ptr_to_pide(struct ioc *ioc, unsigned long *res_ptr, + unsigned int bitshiftcnt) +{ + return (((unsigned long)res_ptr - (unsigned long)ioc->res_map) << 3) + + bitshiftcnt; +} /** * sba_search_bitmap - find free space in IO PDIR resource bitmap @@ -516,19 +333,36 @@ sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents) * Cool perf optimization: search for log2(size) bits at a time. */ static SBA_INLINE unsigned long -sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted) +sba_search_bitmap(struct ioc *ioc, struct device *dev, + unsigned long bits_wanted) { unsigned long *res_ptr = ioc->res_hint; unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]); - unsigned long pide = ~0UL; + unsigned long pide = ~0UL, tpide; + unsigned long boundary_size; + unsigned long shift; + int ret; + + boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1, + 1ULL << IOVP_SHIFT) >> IOVP_SHIFT; + +#if defined(ZX1_SUPPORT) + BUG_ON(ioc->ibase & ~IOVP_MASK); + shift = ioc->ibase >> IOVP_SHIFT; +#else + shift = 0; +#endif if (bits_wanted > (BITS_PER_LONG/2)) { /* Search word at a time - no mask needed */ for(; res_ptr < res_end; ++res_ptr) { - if (*res_ptr == 0) { + tpide = ptr_to_pide(ioc, res_ptr, 0); + ret = iommu_is_span_boundary(tpide, bits_wanted, + shift, + boundary_size); + if ((*res_ptr == 0) && !ret) { *res_ptr = RESMAP_MASK(bits_wanted); - pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); - pide <<= 3; /* convert to bit address */ + pide = tpide; break; } } @@ -543,7 +377,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted) ** SBA HW features in the unmap path. */ unsigned long o = 1 << get_order(bits_wanted << PAGE_SHIFT); - uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o); + uint bitshiftcnt = ALIGN(ioc->res_bitshift, o); unsigned long mask; if (bitshiftcnt >= BITS_PER_LONG) { @@ -552,16 +386,18 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted) } mask = RESMAP_MASK(bits_wanted) >> bitshiftcnt; - DBG_RES("%s() o %ld %p", __FUNCTION__, o, res_ptr); + DBG_RES("%s() o %ld %p", __func__, o, res_ptr); while(res_ptr < res_end) { DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr); WARN_ON(mask == 0); - if(((*res_ptr) & mask) == 0) { + tpide = ptr_to_pide(ioc, res_ptr, bitshiftcnt); + ret = iommu_is_span_boundary(tpide, bits_wanted, + shift, + boundary_size); + if ((((*res_ptr) & mask) == 0) && !ret) { *res_ptr |= mask; /* mark resources busy! */ - pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); - pide <<= 3; /* convert to bit address */ - pide += bitshiftcnt; + pide = tpide; break; } mask >>= o; @@ -596,7 +432,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted) * resource bit map. */ static int -sba_alloc_range(struct ioc *ioc, size_t size) +sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size) { unsigned int pages_needed = size >> IOVP_SHIFT; #ifdef SBA_COLLECT_STATS @@ -604,9 +440,9 @@ sba_alloc_range(struct ioc *ioc, size_t size) #endif unsigned long pide; - pide = sba_search_bitmap(ioc, pages_needed); + pide = sba_search_bitmap(ioc, dev, pages_needed); if (pide >= (ioc->res_size << 3)) { - pide = sba_search_bitmap(ioc, pages_needed); + pide = sba_search_bitmap(ioc, dev, pages_needed); if (pide >= (ioc->res_size << 3)) panic("%s: I/O MMU @ %p is out of mapping resources\n", __FILE__, ioc->ioc_hpa); @@ -620,7 +456,7 @@ sba_alloc_range(struct ioc *ioc, size_t size) #endif DBG_RES("%s(%x) %d -> %lx hint %x/%x\n", - __FUNCTION__, size, pages_needed, pide, + __func__, size, pages_needed, pide, (uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map), ioc->res_bitshift ); @@ -663,7 +499,7 @@ sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size) unsigned long m = RESMAP_MASK(bits_not_wanted) >> (pide & (BITS_PER_LONG - 1)); DBG_RES("%s( ,%x,%x) %x/%lx %x %p %lx\n", - __FUNCTION__, (uint) iova, size, + __func__, (uint) iova, size, bits_not_wanted, m, pide, res_ptr, *res_ptr); #ifdef SBA_COLLECT_STATS @@ -727,7 +563,7 @@ typedef unsigned long space_t; * IOMMU uses little endian for the pdir. */ -void SBA_INLINE +static void SBA_INLINE sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, unsigned long hint) { @@ -739,9 +575,9 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, mtsp(sid,1); asm("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba)); - pa |= (ci >> 12) & 0xff; /* move CI (8 bits) into lowest byte */ + pa |= (ci >> PAGE_SHIFT) & 0xff; /* move CI (8 bits) into lowest byte */ - pa |= 0x8000000000000000ULL; /* set "valid" bit */ + pa |= SBA_PDIR_VALID_BIT; /* set "valid" bit */ *pdir_ptr = cpu_to_le64(pa); /* swap and store into I/O Pdir */ /* @@ -834,7 +670,7 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt) * @dev: instance of PCI owned by the driver that's asking * @mask: number of address bits this PCI device can handle * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static int sba_dma_supported( struct device *dev, u64 mask) { @@ -846,8 +682,8 @@ static int sba_dma_supported( struct device *dev, u64 mask) return(0); } - /* Documentation/DMA-mapping.txt tells drivers to try 64-bit first, - * then fall back to 32-bit if that fails. + /* Documentation/DMA-API-HOWTO.txt tells drivers to try 64-bit + * first, then fall back to 32-bit if that fails. * We are just "encouraging" 32-bit DMA masks here since we can * never allow IOMMU bypass unless we add special support for ZX1. */ @@ -872,7 +708,7 @@ static int sba_dma_supported( struct device *dev, u64 mask) * @size: number of bytes to map in driver buffer. * @direction: R/W or both. * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static dma_addr_t sba_map_single(struct device *dev, void *addr, size_t size, @@ -902,11 +738,11 @@ sba_map_single(struct device *dev, void *addr, size_t size, ioc->msingle_calls++; ioc->msingle_pages += size >> IOVP_SHIFT; #endif - pide = sba_alloc_range(ioc, size); + pide = sba_alloc_range(ioc, dev, size); iovp = (dma_addr_t) pide << IOVP_SHIFT; DBG_RUN("%s() 0x%p -> 0x%lx\n", - __FUNCTION__, addr, (long) iovp | offset); + __func__, addr, (long) iovp | offset); pdir_start = &(ioc->pdir_base[pide]); @@ -951,7 +787,7 @@ sba_map_single(struct device *dev, void *addr, size_t size, * @size: number of bytes mapped in driver buffer. * @direction: R/W or both. * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, @@ -964,13 +800,13 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, unsigned long flags; dma_addr_t offset; - DBG_RUN("%s() iovp 0x%lx/%x\n", __FUNCTION__, (long) iova, size); + DBG_RUN("%s() iovp 0x%lx/%x\n", __func__, (long) iova, size); ioc = GET_IOC(dev); offset = iova & ~IOVP_MASK; iova ^= offset; /* clear offset bits */ size += offset; - size = ROUNDUP(size, IOVP_SIZE); + size = ALIGN(size, IOVP_SIZE); spin_lock_irqsave(&ioc->res_lock, flags); @@ -1027,7 +863,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, * @size: number of bytes mapped in driver buffer. * @dma_handle: IOVA of new buffer. * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static void *sba_alloc_consistent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t gfp) @@ -1037,7 +873,7 @@ static void *sba_alloc_consistent(struct device *hwdev, size_t size, if (!hwdev) { /* only support PCI */ *dma_handle = 0; - return 0; + return NULL; } ret = (void *) __get_free_pages(gfp, get_order(size)); @@ -1058,7 +894,7 @@ static void *sba_alloc_consistent(struct device *hwdev, size_t size, * @vaddr: virtual address IOVA of "consistent" buffer. * @dma_handler: IO virtual address of "consistent" buffer. * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static void sba_free_consistent(struct device *hwdev, size_t size, void *vaddr, @@ -1093,7 +929,7 @@ int dump_run_sg = 0; * @nents: number of entries in list * @direction: R/W or both. * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, @@ -1103,7 +939,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int coalesced, filled = 0; unsigned long flags; - DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents); + DBG_RUN_SG("%s() START %d entries\n", __func__, nents); ioc = GET_IOC(dev); @@ -1138,7 +974,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, ** w/o this association, we wouldn't have coherent DMA! ** Access to the virtual address is what forces a two pass algorithm. */ - coalesced = iommu_coalesce_chunks(ioc, sglist, nents, sba_alloc_range); + coalesced = iommu_coalesce_chunks(ioc, dev, sglist, nents, sba_alloc_range); /* ** Program the I/O Pdir @@ -1164,7 +1000,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, spin_unlock_irqrestore(&ioc->res_lock, flags); - DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled); + DBG_RUN_SG("%s() DONE %d mappings\n", __func__, filled); return filled; } @@ -1177,7 +1013,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, * @nents: number of entries in list * @direction: R/W or both. * - * See Documentation/DMA-mapping.txt + * See Documentation/DMA-API-HOWTO.txt */ static void sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, @@ -1189,7 +1025,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, #endif DBG_RUN_SG("%s() START %d entries, %p,%x\n", - __FUNCTION__, nents, sg_virt_addr(sglist), sglist->length); + __func__, nents, sg_virt_addr(sglist), sglist->length); ioc = GET_IOC(dev); @@ -1213,7 +1049,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, ++sglist; } - DBG_RUN_SG("%s() DONE (nents %d)\n", __FUNCTION__, nents); + DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents); #ifdef ASSERT_PDIR_SANITY spin_lock_irqsave(&ioc->res_lock, flags); @@ -1284,7 +1120,7 @@ sba_alloc_pdir(unsigned int pdir_size) pdir_base = __get_free_pages(GFP_KERNEL, pdir_order); if (NULL == (void *) pdir_base) { panic("%s() could not allocate I/O Page Table\n", - __FUNCTION__); + __func__); } /* If this is not PA8700 (PCX-W2) @@ -1372,31 +1208,49 @@ sba_alloc_pdir(unsigned int pdir_size) return (void *) pdir_base; } -static struct device *next_device(struct klist_iter *i) +struct ibase_data_struct { + struct ioc *ioc; + int ioc_num; +}; + +static int setup_ibase_imask_callback(struct device *dev, void *data) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; + /* lba_set_iregs() is in drivers/parisc/lba_pci.c */ + extern void lba_set_iregs(struct parisc_device *, u32, u32); + struct parisc_device *lba = to_parisc_device(dev); + struct ibase_data_struct *ibd = data; + int rope_num = (lba->hpa.start >> 13) & 0xf; + if (rope_num >> 3 == ibd->ioc_num) + lba_set_iregs(lba, ibd->ioc->ibase, ibd->ioc->imask); + return 0; } /* setup Mercury or Elroy IBASE/IMASK registers. */ static void setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num) { - /* lba_set_iregs() is in drivers/parisc/lba_pci.c */ - extern void lba_set_iregs(struct parisc_device *, u32, u32); - struct device *dev; - struct klist_iter i; - - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *lba = to_parisc_device(dev); - int rope_num = (lba->hpa.start >> 13) & 0xf; - if (rope_num >> 3 == ioc_num) - lba_set_iregs(lba, ioc->ibase, ioc->imask); - } - klist_iter_exit(&i); + struct ibase_data_struct ibase_data = { + .ioc = ioc, + .ioc_num = ioc_num, + }; + + device_for_each_child(&sba->dev, &ibase_data, + setup_ibase_imask_callback); } +#ifdef SBA_AGP_SUPPORT +static int +sba_ioc_find_quicksilver(struct device *dev, void *data) +{ + int *agp_found = data; + struct parisc_device *lba = to_parisc_device(dev); + + if (IS_QUICKSILVER(lba)) + *agp_found = 1; + return 0; +} +#endif + static void sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) { @@ -1427,7 +1281,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64); DBG_INIT("%s() hpa 0x%p IOV %dMB (%d bits)\n", - __FUNCTION__, ioc->ioc_hpa, iova_space_size >> 20, + __func__, ioc->ioc_hpa, iova_space_size >> 20, iov_order + PAGE_SHIFT); ioc->pdir_base = (void *) __get_free_pages(GFP_KERNEL, @@ -1438,7 +1292,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) memset(ioc->pdir_base, 0, ioc->pdir_size); DBG_INIT("%s() pdir %p size %x\n", - __FUNCTION__, ioc->pdir_base, ioc->pdir_size); + __func__, ioc->pdir_base, ioc->pdir_size); #ifdef SBA_HINT_SUPPORT ioc->hint_shift_pdir = iov_order + PAGE_SHIFT; @@ -1498,6 +1352,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) WRITE_REG(ioc->ibase | 31, ioc->ioc_hpa + IOC_PCOM); #ifdef SBA_AGP_SUPPORT + /* ** If an AGP device is present, only use half of the IOV space ** for PCI DMA. Unfortunately we can't know ahead of time @@ -1506,28 +1361,22 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ** We program the next pdir index after we stop w/ a key for ** the GART code to handshake on. */ - device=NULL; - for (lba = sba->child; lba; lba = lba->sibling) { - if (IS_QUICKSILVER(lba)) - break; - } + device_for_each_child(&sba->dev, &agp_found, sba_ioc_find_quicksilver); - if (lba) { - DBG_INIT("%s: Reserving half of IOVA space for AGP GART support\n", __FUNCTION__); + if (agp_found && sba_reserve_agpgart) { + printk(KERN_INFO "%s: reserving %dMb of IOVA space for agpgart\n", + __func__, (iova_space_size/2) >> 20); ioc->pdir_size /= 2; - ((u64 *)ioc->pdir_base)[PDIR_INDEX(iova_space_size/2)] = SBA_IOMMU_COOKIE; - } else { - DBG_INIT("%s: No GART needed - no AGP controller found\n", __FUNCTION__); + ioc->pdir_base[PDIR_INDEX(iova_space_size/2)] = SBA_AGPGART_COOKIE; } -#endif /* 0 */ - +#endif /*SBA_AGP_SUPPORT*/ } static void sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) { u32 iova_space_size, iova_space_mask; - unsigned int pdir_size, iov_order; + unsigned int pdir_size, iov_order, tcnfg; /* ** Determine IOVA Space size from memory size. @@ -1543,7 +1392,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ** for DMA hints - ergo only 30 bits max. */ - iova_space_size = (u32) (num_physpages/global_ioc_cnt); + iova_space_size = (u32) (totalram_pages/global_ioc_cnt); /* limit IOVA space size to 1MB-1GB */ if (iova_space_size < (1 << (20 - PAGE_SHIFT))) { @@ -1566,16 +1415,16 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64); DBG_INIT("%s() hpa 0x%lx mem %ldMB IOV %dMB (%d bits)\n", - __FUNCTION__, + __func__, ioc->ioc_hpa, - (unsigned long) num_physpages >> (20 - PAGE_SHIFT), + (unsigned long) totalram_pages >> (20 - PAGE_SHIFT), iova_space_size>>20, iov_order + PAGE_SHIFT); ioc->pdir_base = sba_alloc_pdir(pdir_size); DBG_INIT("%s() pdir %p size %x\n", - __FUNCTION__, ioc->pdir_base, pdir_size); + __func__, ioc->pdir_base, pdir_size); #ifdef SBA_HINT_SUPPORT /* FIXME : DMA HINTs not used */ @@ -1603,7 +1452,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) #endif DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n", - __FUNCTION__, ioc->ibase, ioc->imask); + __func__, ioc->ibase, ioc->imask); /* ** FIXME: Hint registers are programmed with default hint @@ -1619,8 +1468,19 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa+IOC_IBASE); WRITE_REG(ioc->imask, ioc->ioc_hpa+IOC_IMASK); - /* Set I/O PDIR Page size to 4K */ - WRITE_REG(0, ioc->ioc_hpa+IOC_TCNFG); + /* Set I/O PDIR Page size to system page size */ + switch (PAGE_SHIFT) { + case 12: tcnfg = 0; break; /* 4K */ + case 13: tcnfg = 1; break; /* 8K */ + case 14: tcnfg = 2; break; /* 16K */ + case 16: tcnfg = 3; break; /* 64K */ + default: + panic(__FILE__ "Unsupported system page size %d", + 1 << PAGE_SHIFT); + break; + } + /* Set I/O PDIR Page size to PAGE_SIZE (4k/16k/...) */ + WRITE_REG(tcnfg, ioc->ioc_hpa+IOC_TCNFG); /* ** Clear I/O TLB of any possible entries. @@ -1630,7 +1490,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->ibase = 0; /* used by SBA_IOVA and related macros */ - DBG_INIT("%s() DONE\n", __FUNCTION__); + DBG_INIT("%s() DONE\n", __func__); } @@ -1701,10 +1561,10 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa, } #endif - if (!IS_PLUTO(sba_dev->iodc)) { + if (!IS_PLUTO(sba_dev->dev)) { ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL); DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->", - __FUNCTION__, sba_dev->sba_hpa, ioc_ctl); + __func__, sba_dev->sba_hpa, ioc_ctl); ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC | IOC_CTRL_CE); ioc_ctl |= IOC_CTRL_DD | IOC_CTRL_D4 | IOC_CTRL_TC; /* j6700 v1.6 firmware sets 0x294f */ @@ -1718,9 +1578,8 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa, #endif } /* if !PLUTO */ - if (IS_ASTRO(sba_dev->iodc)) { + if (IS_ASTRO(sba_dev->dev)) { int err; - /* PAT_PDC (L-class) also reports the same goofy base */ sba_dev->ioc[0].ioc_hpa = ioc_remap(sba_dev, ASTRO_IOC_OFFSET); num_ioc = 1; @@ -1730,13 +1589,9 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa, err = request_resource(&iomem_resource, &(sba_dev->chip_resv)); BUG_ON(err < 0); - } else if (IS_PLUTO(sba_dev->iodc)) { + } else if (IS_PLUTO(sba_dev->dev)) { int err; - /* We use a negative value for IOC HPA so it gets - * corrected when we add it with IKE's IOC offset. - * Doesnt look clean, but fewer code. - */ sba_dev->ioc[0].ioc_hpa = ioc_remap(sba_dev, PLUTO_IOC_OFFSET); num_ioc = 1; @@ -1752,14 +1607,14 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa, err = request_resource(&iomem_resource, &(sba_dev->iommu_resv)); WARN_ON(err < 0); } else { - /* IS_IKE (ie N-class, L3000, L1500) */ + /* IKE, REO */ sba_dev->ioc[0].ioc_hpa = ioc_remap(sba_dev, IKE_IOC_OFFSET(0)); sba_dev->ioc[1].ioc_hpa = ioc_remap(sba_dev, IKE_IOC_OFFSET(1)); num_ioc = 2; /* TODO - LOOKUP Ike/Stretch chipset mem map */ } - /* XXX: What about Reo? */ + /* XXX: What about Reo Grande? */ sba_dev->num_ioc = num_ioc; for (i = 0; i < num_ioc; i++) { @@ -1774,7 +1629,7 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa, * Overrides bit 1 in DMA Hint Sets. * Improves netperf UDP_STREAM by ~10% for bcm5701. */ - if (IS_PLUTO(sba_dev->iodc)) { + if (IS_PLUTO(sba_dev->dev)) { void __iomem *rope_cfg; unsigned long cfg_val; @@ -1803,7 +1658,7 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa, READ_REG(sba_dev->ioc[i].ioc_hpa + 0x400) ); - if (IS_PLUTO(sba_dev->iodc)) { + if (IS_PLUTO(sba_dev->dev)) { sba_ioc_init_pluto(sba_dev->dev, &(sba_dev->ioc[i]), i); } else { sba_ioc_init(sba_dev->dev, &(sba_dev->ioc[i]), i); @@ -1840,7 +1695,7 @@ sba_common_init(struct sba_device *sba_dev) res_size >>= 3; /* convert bit count to byte count */ DBG_INIT("%s() res_size 0x%x\n", - __FUNCTION__, res_size); + __func__, res_size); sba_dev->ioc[i].res_size = res_size; sba_dev->ioc[i].res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size)); @@ -1853,7 +1708,7 @@ sba_common_init(struct sba_device *sba_dev) if (NULL == sba_dev->ioc[i].res_map) { panic("%s:%s() could not allocate resource map\n", - __FILE__, __FUNCTION__ ); + __FILE__, __func__ ); } memset(sba_dev->ioc[i].res_map, 0, res_size); @@ -1890,7 +1745,7 @@ sba_common_init(struct sba_device *sba_dev) #endif DBG_INIT("%s() %d res_map %x %p\n", - __FUNCTION__, i, res_size, sba_dev->ioc[i].res_map); + __func__, i, res_size, sba_dev->ioc[i].res_map); } spin_lock_init(&sba_dev->sba_lock); @@ -1989,7 +1844,7 @@ sba_proc_open(struct inode *i, struct file *f) return single_open(f, &sba_proc_info, NULL); } -static struct file_operations sba_proc_fops = { +static const struct file_operations sba_proc_fops = { .owner = THIS_MODULE, .open = sba_proc_open, .read = seq_read, @@ -2021,7 +1876,7 @@ sba_proc_bitmap_open(struct inode *i, struct file *f) return single_open(f, &sba_proc_bitmap_info, NULL); } -static struct file_operations sba_proc_bitmap_fops = { +static const struct file_operations sba_proc_bitmap_fops = { .owner = THIS_MODULE, .open = sba_proc_bitmap_open, .read = seq_read, @@ -2039,7 +1894,7 @@ static struct parisc_device_id sba_tbl[] = { { 0, } }; -int sba_driver_callback(struct parisc_device *); +static int sba_driver_callback(struct parisc_device *); static struct parisc_driver sba_driver = { .name = MODULE_NAME, @@ -2052,22 +1907,23 @@ static struct parisc_driver sba_driver = { ** If so, initialize the chip and tell other partners in crime they ** have work to do. */ -int -sba_driver_callback(struct parisc_device *dev) +static int sba_driver_callback(struct parisc_device *dev) { struct sba_device *sba_dev; u32 func_class; int i; char *version; void __iomem *sba_addr = ioremap_nocache(dev->hpa.start, SBA_FUNC_SIZE); - struct proc_dir_entry *info_entry, *bitmap_entry, *root; +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *root; +#endif sba_dump_ranges(sba_addr); /* Read HW Rev First */ func_class = READ_REG(sba_addr + SBA_FCLASS); - if (IS_ASTRO(&dev->id)) { + if (IS_ASTRO(dev)) { unsigned long fclass; static char astro_rev[]="Astro ?.?"; @@ -2078,11 +1934,11 @@ sba_driver_callback(struct parisc_device *dev) astro_rev[8] = '0' + (char) ((fclass & 0x18) >> 3); version = astro_rev; - } else if (IS_IKE(&dev->id)) { + } else if (IS_IKE(dev)) { static char ike_rev[] = "Ike rev ?"; ike_rev[8] = '0' + (char) (func_class & 0xff); version = ike_rev; - } else if (IS_PLUTO(&dev->id)) { + } else if (IS_PLUTO(dev)) { static char pluto_rev[]="Pluto ?.?"; pluto_rev[6] = '0' + (char) ((func_class & 0xf0) >> 4); pluto_rev[8] = '0' + (char) (func_class & 0x0f); @@ -2097,12 +1953,12 @@ sba_driver_callback(struct parisc_device *dev) global_ioc_cnt = count_parisc_driver(&sba_driver); /* Astro and Pluto have one IOC per SBA */ - if ((!IS_ASTRO(&dev->id)) || (!IS_PLUTO(&dev->id))) + if ((!IS_ASTRO(dev)) || (!IS_PLUTO(dev))) global_ioc_cnt *= 2; } - printk(KERN_INFO "%s found %s at 0x%lx\n", - MODULE_NAME, version, dev->hpa.start); + printk(KERN_INFO "%s found %s at 0x%llx\n", + MODULE_NAME, version, (unsigned long long)dev->hpa.start); sba_dev = kzalloc(sizeof(struct sba_device), GFP_KERNEL); if (!sba_dev) { @@ -2117,7 +1973,6 @@ sba_driver_callback(struct parisc_device *dev) sba_dev->dev = dev; sba_dev->hw_rev = func_class; - sba_dev->iodc = &dev->id; sba_dev->name = dev->name; sba_dev->sba_hpa = sba_addr; @@ -2139,18 +1994,10 @@ sba_driver_callback(struct parisc_device *dev) break; } - info_entry = create_proc_entry("sba_iommu", 0, root); - bitmap_entry = create_proc_entry("sba_iommu-bitmap", 0, root); - - if (info_entry) - info_entry->proc_fops = &sba_proc_fops; - - if (bitmap_entry) - bitmap_entry->proc_fops = &sba_proc_bitmap_fops; + proc_create("sba_iommu", 0, root, &sba_proc_fops); + proc_create("sba_iommu-bitmap", 0, root, &sba_proc_bitmap_fops); #endif - parisc_vmerge_boundary = IOVP_SIZE; - parisc_vmerge_max_size = IOVP_SIZE * BITS_PER_LONG; parisc_has_iommu(); return 0; } @@ -2176,7 +2023,7 @@ void __init sba_init(void) void * sba_get_iommu(struct parisc_device *pci_hba) { struct parisc_device *sba_dev = parisc_parent(pci_hba); - struct sba_device *sba = sba_dev->dev.driver_data; + struct sba_device *sba = dev_get_drvdata(&sba_dev->dev); char t = sba_dev->id.hw_type; int iocnum = (pci_hba->hw_path >> 3); /* rope # */ @@ -2197,7 +2044,7 @@ void * sba_get_iommu(struct parisc_device *pci_hba) void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) { struct parisc_device *sba_dev = parisc_parent(pci_hba); - struct sba_device *sba = sba_dev->dev.driver_data; + struct sba_device *sba = dev_get_drvdata(&sba_dev->dev); char t = sba_dev->id.hw_type; int i; int rope = (pci_hba->hw_path & (ROPES_PER_IOC-1)); /* rope # */ @@ -2223,6 +2070,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) r->start = (base & ~1UL) | PCI_F_EXTEND; size = ~ READ_REG32(reg + LMMIO_DIRECT0_MASK); r->end = r->start + size; + r->flags = IORESOURCE_MEM; } } @@ -2239,7 +2087,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r ) { struct parisc_device *sba_dev = parisc_parent(pci_hba); - struct sba_device *sba = sba_dev->dev.driver_data; + struct sba_device *sba = dev_get_drvdata(&sba_dev->dev); char t = sba_dev->id.hw_type; int base, size; int rope = (pci_hba->hw_path & (ROPES_PER_IOC-1)); /* rope # */ @@ -2259,4 +2107,5 @@ void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r ) size = (~READ_REG32(sba->sba_hpa + LMMIO_DIST_MASK)) / ROPES_PER_IOC; r->start += rope * (size + 1); /* adjust base for this rope */ r->end = r->start + size; + r->flags = IORESOURCE_MEM; } diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index 4ee26a6d9e2..a042d065a0c 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -73,6 +73,7 @@ #include <linux/termios.h> #include <linux/tty.h> #include <linux/serial_core.h> +#include <linux/serial_8250.h> #include <linux/delay.h> #include <asm/io.h> @@ -94,7 +95,7 @@ static struct superio_device sio_dev; #define PFX SUPERIO ": " static irqreturn_t -superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) +superio_interrupt(int parent_irq, void *devp) { u8 results; u8 local_irq; @@ -138,7 +139,7 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) } /* Call the appropriate device's interrupt */ - __do_IRQ(local_irq, regs); + generic_handle_irq(local_irq); /* set EOI - forces a new interrupt if a lower priority device * still needs service. @@ -154,6 +155,7 @@ superio_init(struct pci_dev *pcidev) struct superio_device *sio = &sio_dev; struct pci_dev *pdev = sio->lio_pdev; u16 word; + int ret; if (sio->suckyio_irq_enabled) return; @@ -167,7 +169,7 @@ superio_init(struct pci_dev *pcidev) /* ...then properly fixup the USB to point at suckyio PIC */ sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev); - printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i) \n", + printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i)\n", pci_name(pdev), pdev->irq); pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base); @@ -199,7 +201,8 @@ superio_init(struct pci_dev *pcidev) pci_write_config_word (pdev, PCI_COMMAND, word); pci_set_master (pdev); - pci_enable_device(pdev); + ret = pci_enable_device(pdev); + BUG_ON(ret < 0); /* not too much we can do about this... */ /* * Next project is programming the onboard interrupt controllers. @@ -271,7 +274,7 @@ superio_init(struct pci_dev *pcidev) else printk(KERN_ERR PFX "USB regulator not initialized!\n"); - if (request_irq(pdev->irq, superio_interrupt, IRQF_DISABLED, + if (request_irq(pdev->irq, superio_interrupt, 0, SUPERIO, (void *)sio)) { printk(KERN_ERR PFX "could not get irq\n"); @@ -283,8 +286,9 @@ superio_init(struct pci_dev *pcidev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO, superio_init); -static void superio_disable_irq(unsigned int irq) +static void superio_mask_irq(struct irq_data *d) { + unsigned int irq = d->irq; u8 r8; if ((irq < 1) || (irq == 2) || (irq > 7)) { @@ -300,8 +304,9 @@ static void superio_disable_irq(unsigned int irq) outb (r8,IC_PIC1+1); } -static void superio_enable_irq(unsigned int irq) +static void superio_unmask_irq(struct irq_data *d) { + unsigned int irq = d->irq; u8 r8; if ((irq < 1) || (irq == 2) || (irq > 7)) { @@ -316,20 +321,10 @@ static void superio_enable_irq(unsigned int irq) outb (r8,IC_PIC1+1); } -static unsigned int superio_startup_irq(unsigned int irq) -{ - superio_enable_irq(irq); - return 0; -} - -static struct hw_interrupt_type superio_interrupt_type = { - .typename = SUPERIO, - .startup = superio_startup_irq, - .shutdown = superio_disable_irq, - .enable = superio_enable_irq, - .disable = superio_disable_irq, - .ack = no_ack_irq, - .end = no_end_irq, +static struct irq_chip superio_interrupt_type = { + .name = SUPERIO, + .irq_unmask = superio_unmask_irq, + .irq_mask = superio_mask_irq, }; #ifdef DEBUG_SUPERIO_INIT @@ -353,14 +348,15 @@ int superio_fixup_irq(struct pci_dev *pcidev) BUG(); return -1; } - printk("superio_fixup_irq(%s) ven 0x%x dev 0x%x from %p\n", + printk("superio_fixup_irq(%s) ven 0x%x dev 0x%x from %pf\n", pci_name(pcidev), pcidev->vendor, pcidev->device, __builtin_return_address(0)); #endif for (i = 0; i < 16; i++) { - irq_desc[i].chip = &superio_interrupt_type; + irq_set_chip_and_handler(i, &superio_interrupt_type, + handle_simple_irq); } /* @@ -389,7 +385,7 @@ int superio_fixup_irq(struct pci_dev *pcidev) return local_irq; } -static void __devinit superio_serial_init(void) +static void __init superio_serial_init(void) { #ifdef CONFIG_SERIAL_8250 int retval; @@ -400,7 +396,6 @@ static void __devinit superio_serial_init(void) serial_port.type = PORT_16550A; serial_port.uartclk = 115200*16; serial_port.fifosize = 16; - spin_lock_init(&serial_port.lock); /* serial port #1 */ serial_port.iobase = sio_dev.sp1_base; @@ -423,14 +418,15 @@ static void __devinit superio_serial_init(void) } -static void __devinit superio_parport_init(void) +static void __init superio_parport_init(void) { #ifdef CONFIG_PARPORT_PC if (!parport_pc_probe_port(sio_dev.pp_base, 0 /*base_hi*/, PAR_IRQ, PARPORT_DMA_NONE /* dma */, - NULL /*struct pci_dev* */) ) + NULL /*struct pci_dev* */, + 0 /* shared irq flags */)) printk(KERN_WARNING PFX "Probing parallel port failed.\n"); #endif /* CONFIG_PARPORT_PC */ @@ -450,7 +446,7 @@ static void superio_fixup_pci(struct pci_dev *pdev) DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci); -static int __devinit +static int __init superio_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct superio_device *sio = &sio_dev; @@ -485,7 +481,7 @@ superio_probe(struct pci_dev *dev, const struct pci_device_id *id) return -ENODEV; } -static struct pci_device_id superio_tbl[] = { +static const struct pci_device_id superio_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO) }, { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_USB) }, { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415) }, @@ -498,15 +494,4 @@ static struct pci_driver superio_driver = { .probe = superio_probe, }; -static int __init superio_modinit(void) -{ - return pci_register_driver(&superio_driver); -} - -static void __exit superio_exit(void) -{ - pci_unregister_driver(&superio_driver); -} - -module_init(superio_modinit); -module_exit(superio_exit); +module_pci_driver(superio_driver); diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c index 813c2c24ab1..da9d5ad1353 100644 --- a/drivers/parisc/wax.c +++ b/drivers/parisc/wax.c @@ -68,8 +68,7 @@ wax_init_irq(struct gsc_asic *wax) // gsc_writel(0xFFFFFFFF, base+0x2000); /* RS232-B on Wax */ } -int __init -wax_init_chip(struct parisc_device *dev) +static int __init wax_init_chip(struct parisc_device *dev) { struct gsc_asic *wax; struct parisc_device *parent; @@ -93,7 +92,7 @@ wax_init_chip(struct parisc_device *dev) dev->irq = gsc_claim_irq(&gsc_irq, WAX_GSC_IRQ); if (dev->irq < 0) { printk(KERN_ERR "%s(): cannot get GSC irq\n", - __FUNCTION__); + __func__); kfree(wax); return -EBUSY; } |
