From 0c050f6b7e2e079c774fcaee218c71a079e4971c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:31:22 -0500 Subject: [PATCH] Import 2.3.45pre1 --- Makefile | 2 +- arch/alpha/kernel/pci_iommu.c | 205 +- arch/arm/kernel/armksyms.c | 7 + arch/arm/kernel/entry-common.S | 51 +- arch/arm/kernel/irq.c | 12 +- arch/arm/kernel/semaphore.c | 171 +- arch/arm/mm/Makefile | 4 +- arch/arm/mm/consistent.c | 102 + arch/arm/mm/proc-arm6,7.S | 2 +- arch/arm/nwfpe/fpmodule.c | 36 +- arch/arm/nwfpe/fpsr.h | 10 +- arch/i386/boot/bootsect.S | 25 +- arch/i386/kernel/pci-pc.c | 4 +- arch/ia64/config.in | 2 + arch/ia64/ia32/ia32_entry.S | 2 +- arch/ia64/ia32/ia32_signal.c | 22 +- arch/ia64/ia32/sys_ia32.c | 57 +- arch/ia64/kernel/efi.c | 3 - arch/ia64/kernel/entry.S | 33 +- arch/ia64/kernel/gate.S | 1 + arch/ia64/kernel/head.S | 5 +- arch/ia64/kernel/irq.c | 18 +- arch/ia64/kernel/irq_lock.c | 2 +- arch/ia64/kernel/pci-dma.c | 2 +- arch/ia64/kernel/pci.c | 11 - arch/ia64/kernel/smp.c | 8 +- arch/ia64/kernel/sys_ia64.c | 4 +- arch/ia64/lib/Makefile | 2 +- arch/ia64/tools/print_offsets.c | 1 + arch/ppc/coffboot/misc.S | 2 +- arch/ppc/configs/common_defconfig | 66 +- arch/ppc/configs/gemini_defconfig | 13 +- arch/ppc/defconfig | 66 +- arch/ppc/kernel/entry.S | 33 +- arch/ppc/kernel/head.S | 234 +- arch/ppc/kernel/irq.c | 23 +- arch/ppc/kernel/misc.S | 32 + arch/ppc/kernel/mk_defs.c | 6 +- arch/ppc/kernel/open_pic.c | 6 +- arch/ppc/kernel/pmac_pic.c | 21 - arch/ppc/kernel/pmac_setup.c | 5 + arch/ppc/kernel/pmac_time.c | 4 +- arch/ppc/kernel/ppc_asm.h | 22 + arch/ppc/kernel/ppc_asm.tmpl | 33 + arch/ppc/kernel/ppc_ksyms.c | 5 +- arch/ppc/kernel/process.c | 50 +- arch/ppc/kernel/prom.c | 63 +- arch/ppc/kernel/setup.c | 3 +- arch/ppc/kernel/smp.c | 1 - arch/ppc/kernel/syscalls.c | 17 +- arch/ppc/kernel/traps.c | 42 +- arch/ppc/lib/string.S | 385 +- arch/ppc/mm/init.c | 4 +- arch/ppc/xmon/start.c | 61 +- arch/sparc/kernel/ioport.c | 4 +- arch/sparc/kernel/pcic.c | 6 +- arch/sparc/mm/sun4c.c | 4 +- arch/sparc/mm/swift.S | 6 +- drivers/acorn/char/keyb_ps2.c | 3 +- drivers/block/loop.c | 50 +- drivers/char/nvram.c | 2 +- drivers/macintosh/mac_keyb.c | 5 +- drivers/macintosh/macserial.c | 1 - drivers/net/3c59x.c | 14 +- drivers/net/8139too.c | 1812 ++++++++ drivers/net/Config.in | 15 +- drivers/net/Makefile | 3 +- drivers/net/a2065.c | 148 +- drivers/net/arcnet/arc-rimi.c | 13 +- drivers/net/arcnet/arcnet.c | 137 +- drivers/net/arcnet/com20020-isa.c | 7 +- drivers/net/arcnet/com20020-pci.c | 8 +- drivers/net/arcnet/com90io.c | 11 +- drivers/net/arcnet/com90xx.c | 45 +- drivers/net/arcnet/rfc1201.c | 8 +- drivers/net/bmac.c | 327 +- drivers/net/de4x5.c | 2 +- drivers/net/eepro100.c | 249 +- drivers/net/epic100.c | 14 +- drivers/net/gmac.c | 106 +- drivers/net/mace.c | 100 +- drivers/net/ncr885e.c | 46 +- drivers/net/pcmcia/3c574_cs.c | 71 +- drivers/net/pcmcia/3c575_cb.c | 250 +- drivers/net/pcmcia/3c589_cs.c | 48 +- drivers/net/pcmcia/aironet4500_cs.c | 9 +- drivers/net/pcmcia/netwave_cs.c | 82 +- drivers/net/pcmcia/nmclan_cs.c | 99 +- drivers/net/pcmcia/smc91c92_cs.c | 93 +- drivers/net/pcmcia/tulip_cb.c | 106 +- drivers/net/pcmcia/wavelan_cs.c | 221 +- drivers/net/pcmcia/wavelan_cs.h | 5 +- drivers/net/pcmcia/xirc2ps_cs.c | 86 +- drivers/net/rcpci45.c | 39 +- drivers/net/{rtl8139.c => rtl8129.c} | 3 + drivers/net/seeq8005.c | 95 +- drivers/net/smc-mca.c | 5 +- drivers/net/smc9194.c | 241 +- drivers/net/strip.c | 28 +- drivers/net/wan/cycx_x25.c | 40 +- drivers/net/wan/lapbether.c | 15 +- drivers/net/wan/sbni.c | 73 +- drivers/net/wan/sbni.h | 2 +- drivers/net/wan/x25_asy.c | 63 +- drivers/net/wan/z85230.c | 376 +- drivers/net/wan/z85230.h | 6 +- drivers/net/wavelan.c | 6045 ++++++++++++------------- drivers/net/znet.c | 90 +- drivers/scsi/qla1280.c | 5 +- drivers/scsi/qlogicisp.c | 1 + drivers/sound/dmasound.c | 104 +- drivers/usb/keybdev.c | 4 +- drivers/video/aty128fb.c | 7 +- drivers/video/atyfb.c | 2 +- drivers/video/igafb.c | 8 +- fs/Config.in | 4 +- fs/adfs/file.c | 4 + fs/adfs/inode.c | 32 +- fs/adfs/map.c | 10 - fs/attr.c | 2 + fs/hpfs/namei.c | 15 +- fs/nfsd/nfsfh.c | 2 +- fs/nfsd/vfs.c | 10 - fs/open.c | 6 - include/asm-alpha/pgtable.h | 5 +- include/asm-arm/hardirq.h | 5 +- include/asm-arm/io.h | 19 +- include/asm-arm/md.h | 13 - include/asm-arm/pci.h | 150 +- include/asm-arm/pgtable.h | 5 +- include/asm-arm/proc-armo/semaphore.h | 170 +- include/asm-arm/proc-armv/locks.h | 134 + include/asm-arm/proc-armv/semaphore.h | 117 - include/asm-arm/semaphore.h | 219 +- include/asm-arm/softirq.h | 65 +- include/asm-i386/pgtable.h | 7 +- include/asm-ia64/dma.h | 2 +- include/asm-ia64/fpswa.h | 2 +- include/asm-ia64/hardirq.h | 4 + include/asm-ia64/mmu_context.h | 5 + include/asm-ia64/offsets.h | 7 +- include/asm-ia64/pgtable.h | 21 +- include/asm-ia64/ptrace.h | 8 +- include/asm-ia64/semaphore.h | 7 - include/asm-ia64/smp.h | 4 +- include/asm-ia64/softirq.h | 138 +- include/asm-ia64/types.h | 44 +- include/asm-m68k/pgtable.h | 4 +- include/asm-mips/pgtable.h | 4 +- include/asm-ppc/elf.h | 5 + include/asm-ppc/hardirq.h | 33 +- include/asm-ppc/page.h | 2 +- include/asm-ppc/pgtable.h | 3 +- include/asm-ppc/posix_types.h | 4 +- include/asm-ppc/processor.h | 7 +- include/asm-ppc/smp.h | 2 +- include/asm-ppc/softirq.h | 113 +- include/asm-ppc/spinlock.h | 1 + include/asm-ppc/types.h | 6 + include/asm-sh/pgtable.h | 7 +- include/asm-sparc64/floppy.h | 6 +- include/asm-sparc64/pgtable.h | 3 +- include/linux/adfs_fs_i.h | 2 +- include/linux/i2c-id.h | 2 + include/linux/kmod.h | 1 + include/linux/netdevice.h | 2 +- kernel/ksyms.c | 1 + kernel/ptrace.c | 1 + mm/memory.c | 4 + mm/mmap.c | 15 +- net/core/dev.c | 9 +- net/ipv6/af_inet6.c | 4 +- net/khttpd/sockets.c | 2 - net/netsyms.c | 1 + scripts/tkcond.c | 1 + 175 files changed, 8618 insertions(+), 6332 deletions(-) create mode 100644 arch/arm/mm/consistent.c create mode 100644 drivers/net/8139too.c rename drivers/net/{rtl8139.c => rtl8129.c} (99%) delete mode 100644 include/asm-arm/md.h create mode 100644 include/asm-arm/proc-armv/locks.h delete mode 100644 include/asm-arm/proc-armv/semaphore.h diff --git a/Makefile b/Makefile index 4be320a0f0f8..980b840f140c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 3 -SUBLEVEL = 44 +SUBLEVEL = 45 EXTRAVERSION = ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c index 8faa669010a2..14a127c14f71 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c @@ -16,7 +16,6 @@ #define DEBUG_ALLOC 0 - #if DEBUG_ALLOC > 0 # define DBGA(args...) printk(KERN_DEBUG ##args) #else @@ -40,6 +39,20 @@ calc_npages(long bytes) { return (bytes + PAGE_SIZE - 1) >> PAGE_SHIFT; } + +static inline long +calc_order(long size) +{ + int order; + + size = (size-1) >> (PAGE_SHIFT-1); + order = -1; + do { + size >>= 1; + order++; + } while (size); + return order; +} struct pci_iommu_arena * iommu_arena_new(dma_addr_t base, unsigned long window_size, @@ -173,10 +186,6 @@ pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size) ret = arena->dma_base + dma_ofs * PAGE_SIZE; ret += (unsigned long)cpu_addr & ~PAGE_MASK; - /* ??? This shouldn't have been needed, since the entries - we've just modified were not in the iommu tlb. */ - alpha_mv.mv_pci_tbi(hose, ret, ret + size - 1); - DBGA("pci_map_single: [%p,%lx] np %ld -> sg %x from %p\n", cpu_addr, size, npages, ret, __builtin_return_address(0)); @@ -239,11 +248,12 @@ void * pci_alloc_consistent(struct pci_dev *pdev, long size, dma_addr_t *dma_addrp) { void *cpu_addr; + long order = calc_order(size); - cpu_addr = kmalloc(size, GFP_ATOMIC); + cpu_addr = (void *)__get_free_pages(GFP_ATOMIC, order); if (! cpu_addr) { - printk(KERN_INFO "dma_alloc_consistent: " - "kmalloc failed from %p\n", + printk(KERN_INFO "pci_alloc_consistent: " + "get_free_pages failed from %p\n", __builtin_return_address(0)); /* ??? Really atomic allocation? Otherwise we could play with vmalloc and sg if we can't find contiguous memory. */ @@ -253,11 +263,11 @@ pci_alloc_consistent(struct pci_dev *pdev, long size, dma_addr_t *dma_addrp) *dma_addrp = pci_map_single(pdev, cpu_addr, size); if (*dma_addrp == 0) { - kfree_s(cpu_addr, size); + free_pages((unsigned long)cpu_addr, order); return NULL; } - DBGA2("dma_alloc_consistent: %lx -> [%p,%x] from %p\n", + DBGA2("pci_alloc_consistent: %lx -> [%p,%x] from %p\n", size, cpu_addr, *dma_addrp, __builtin_return_address(0)); return cpu_addr; @@ -275,32 +285,33 @@ pci_free_consistent(struct pci_dev *pdev, long size, void *cpu_addr, dma_addr_t dma_addr) { pci_unmap_single(pdev, dma_addr, size); - kfree_s(cpu_addr, size); + free_pages((unsigned long)cpu_addr, calc_order(size)); - DBGA2("dma_free_consistent: [%x,%lx] from %p\n", + DBGA2("pci_free_consistent: [%x,%lx] from %p\n", dma_addr, size, __builtin_return_address(0)); } /* Classify the elements of the scatterlist. Write dma_address of each element with: - 0 : Not mergable. - 1 : Followers all physically adjacent. - [23]: Followers all virtually adjacent. - -1 : Not leader. + 0 : Followers all physically adjacent. + 1 : Followers all virtually adjacent. + -1 : Not leader, physically adjacent to previous. + -2 : Not leader, virtually adjacent to previous. Write dma_length of each leader with the combined lengths of the mergable followers. */ static inline void -sg_classify(struct scatterlist *sg, struct scatterlist *end) +sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok) { unsigned long next_vaddr; struct scatterlist *leader; + long leader_flag, leader_length; leader = sg; - leader->dma_address = 0; - leader->dma_length = leader->length; - next_vaddr = (unsigned long)leader->address + leader->length; + leader_flag = 0; + leader_length = leader->length; + next_vaddr = (unsigned long)leader->address + leader_length; for (++sg; sg < end; ++sg) { unsigned long addr, len; @@ -309,20 +320,24 @@ sg_classify(struct scatterlist *sg, struct scatterlist *end) if (next_vaddr == addr) { sg->dma_address = -1; - leader->dma_address |= 1; - leader->dma_length += len; - } else if (((next_vaddr | addr) & ~PAGE_MASK) == 0) { - sg->dma_address = -1; - leader->dma_address |= 2; - leader->dma_length += len; + leader_length += len; + } else if (((next_vaddr | addr) & ~PAGE_MASK) == 0 && virt_ok) { + sg->dma_address = -2; + leader_flag = 1; + leader_length += len; } else { + leader->dma_address = leader_flag; + leader->dma_length = leader_length; leader = sg; - leader->dma_address = 0; - leader->dma_length = len; + leader_flag = 0; + leader_length = len; } next_vaddr = addr + len; } + + leader->dma_address = leader_flag; + leader->dma_length = leader_length; } /* Given a scatterlist leader, choose an allocation method and fill @@ -334,21 +349,21 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end, dma_addr_t max_dma) { unsigned long paddr = virt_to_phys(leader->address); - unsigned long size = leader->dma_length; + long size = leader->dma_length; struct scatterlist *sg; unsigned long *ptes; long npages, dma_ofs, i; /* If everything is physically contiguous, and the addresses fall into the direct-map window, use it. */ - if (leader->dma_address < 2 + if (leader->dma_address == 0 && paddr + size + __direct_map_base - 1 <= max_dma && paddr + size <= __direct_map_size) { out->dma_address = paddr + __direct_map_base; out->dma_length = size; - DBGA2("sg_fill: [%p,%lx] -> direct %x\n", - leader->address, size, out->dma_address); + DBGA(" sg_fill: [%p,%lx] -> direct %x\n", + leader->address, size, out->dma_address); return 0; } @@ -365,48 +380,70 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end, out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr; out->dma_length = size; - DBGA("sg_fill: [%p,%lx] -> sg %x\n", - leader->address, size, out->dma_address); + DBGA(" sg_fill: [%p,%lx] -> sg %x np %ld\n", + leader->address, size, out->dma_address, npages); ptes = &arena->ptes[dma_ofs]; sg = leader; - do { - paddr = virt_to_phys(sg->address); - npages = calc_npages((paddr & ~PAGE_MASK) + sg->length); + if (0 && leader->dma_address == 0) { + /* All physically contiguous. We already have the + length, all we need is to fill in the ptes. */ - DBGA(" (%ld) [%p,%x]\n", - sg - leader, sg->address, sg->length); - - paddr &= PAGE_MASK; + paddr = virt_to_phys(sg->address) & PAGE_MASK; for (i = 0; i < npages; ++i, paddr += PAGE_SIZE) *ptes++ = mk_iommu_pte(paddr); - ++sg; - } while (sg < end && sg->dma_address == -1); +#if DEBUG_ALLOC > 0 + DBGA(" (0) [%p,%x] np %ld\n", + sg->address, sg->length, npages); + for (++sg; sg < end && (int) sg->dma_address < 0; ++sg) + DBGA(" (%ld) [%p,%x] cont\n", + sg - leader, sg->address, sg->length); +#endif + } else { + /* All virtually contiguous. We need to find the + length of each physically contiguous subsegment + to fill in the ptes. */ + do { + struct scatterlist *last_sg = sg; + + size = sg->length; + paddr = virt_to_phys(sg->address); + + while (sg+1 < end && (int) sg[1].dma_address == -1) { + size += sg[1].length; + sg++; + } + + npages = calc_npages((paddr & ~PAGE_MASK) + size); + + paddr &= PAGE_MASK; + for (i = 0; i < npages; ++i, paddr += PAGE_SIZE) + *ptes++ = mk_iommu_pte(paddr); + +#if DEBUG_ALLOC > 0 + DBGA(" (%ld) [%p,%x] np %ld\n", + last_sg - leader, last_sg->address, + last_sg->length, npages); + while (++last_sg <= sg) { + DBGA(" (%ld) [%p,%x] cont\n", + last_sg - leader, last_sg->address, + last_sg->length); + } +#endif + } while (++sg < end && (int) sg->dma_address < 0); + } return 1; } -/* TODO: Only use the iommu when it helps. Non-mergable scatterlist - entries might as well use direct mappings. */ - int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents) { struct scatterlist *start, *end, *out; struct pci_controler *hose; struct pci_iommu_arena *arena; - dma_addr_t max_dma, fstart, fend; - - /* If pci_tbi is not available, we must not be able to control - an iommu. Direct map everything, no merging. */ - if (! alpha_mv.mv_pci_tbi) { - for (end = sg + nents; sg < end; ++sg) { - sg->dma_address = virt_to_bus(sg->address); - sg->dma_length = sg->length; - } - return nents; - } + dma_addr_t max_dma; /* Fast path single entry scatterlists. */ if (nents == 1) { @@ -416,50 +453,42 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents) return sg->dma_address != 0; } - hose = pdev ? pdev->sysdata : pci_isa_hose; - max_dma = pdev ? pdev->dma_mask : 0x00ffffff; - arena = hose->sg_pci; - if (!arena || arena->dma_base + arena->size > max_dma) - arena = hose->sg_isa; start = sg; end = sg + nents; - fstart = -1; - fend = 0; - + /* First, prepare information about the entries. */ - sg_classify(sg, end); + sg_classify(sg, end, alpha_mv.mv_pci_tbi != 0); + + /* Second, figure out where we're going to map things. */ + if (alpha_mv.mv_pci_tbi) { + hose = pdev ? pdev->sysdata : pci_isa_hose; + max_dma = pdev ? pdev->dma_mask : 0x00ffffff; + arena = hose->sg_pci; + if (!arena || arena->dma_base + arena->size > max_dma) + arena = hose->sg_isa; + } else { + max_dma = -1; + arena = NULL; + hose = NULL; + } - /* Second, iterate over the scatterlist leaders and allocate + /* Third, iterate over the scatterlist leaders and allocate dma space as needed. */ for (out = sg; sg < end; ++sg) { int ret; - if (sg->dma_address == -1) + if ((int) sg->dma_address < 0) continue; ret = sg_fill(sg, end, out, arena, max_dma); if (ret < 0) goto error; - else if (ret > 0) { - dma_addr_t ts, te; - - ts = out->dma_address; - te = ts + out->dma_length - 1; - if (fstart > ts) - fstart = ts; - if (fend < te) - fend = te; - } out++; } - /* ??? This shouldn't have been needed, since the entries - we've just modified were not in the iommu tlb. */ - if (fend) - alpha_mv.mv_pci_tbi(hose, fstart, fend); - if (out - start == 0) printk(KERN_INFO "pci_map_sg failed: no entries?\n"); + DBGA("pci_map_sg: %ld entries\n", out - start); return out - start; @@ -496,9 +525,11 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents) arena = hose->sg_pci; if (!arena || arena->dma_base + arena->size > max_dma) arena = hose->sg_isa; + + DBGA("pci_unmap_sg: %d entries\n", nents); + fstart = -1; fend = 0; - for (end = sg + nents; sg < end; ++sg) { unsigned long addr, size; @@ -508,7 +539,8 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents) if (addr >= __direct_map_base && addr < __direct_map_base + __direct_map_size) { /* Nothing to do. */ - DBGA2("pci_unmap_sg: direct [%lx,%lx]\n", addr, size); + DBGA(" (%ld) direct [%lx,%lx]\n", + sg - end + nents, addr, size); } else { long npages, ofs; dma_addr_t tend; @@ -523,7 +555,8 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents) if (fend < tend) fend = tend; - DBGA2("pci_unmap_sg: sg [%lx,%lx]\n", addr, size); + DBGA(" (%ld) sg [%lx,%lx]\n", + sg - end + nents, addr, size); } } if (fend) diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 0caf4bf26057..63d4631a4b2b 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -188,6 +188,10 @@ EXPORT_SYMBOL(uaccess_kernel); EXPORT_SYMBOL(uaccess_user); #endif +EXPORT_SYMBOL(consistent_alloc); +EXPORT_SYMBOL(consistent_free); +EXPORT_SYMBOL(consistent_sync); + /* gcc lib functions */ EXPORT_SYMBOL_NOVERS(__gcc_bcmp); EXPORT_SYMBOL_NOVERS(__ashldi3); @@ -234,5 +238,8 @@ EXPORT_SYMBOL_NOVERS(__down_failed); EXPORT_SYMBOL_NOVERS(__down_interruptible_failed); EXPORT_SYMBOL_NOVERS(__down_trylock_failed); EXPORT_SYMBOL_NOVERS(__up_wakeup); +EXPORT_SYMBOL_NOVERS(__down_read_failed); +EXPORT_SYMBOL_NOVERS(__down_write_failed); +EXPORT_SYMBOL_NOVERS(__rwsem_wake); EXPORT_SYMBOL(get_wchan); diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 2be1a6012160..5dc61c6d7de7 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -15,26 +15,28 @@ #define HARVARD_CACHE #endif + .macro get_softirq, rd +#ifdef __SMP__ +#error SMP not supported +#else + ldr \rd, __softirq_state +#endif + .endm + .globl ret_from_sys_call .align 5 fast_syscall_return: - str r0, [sp, #S_R0 + S_OFF] @ returned r0 + str r0, [sp, #S_R0 + S_OFF] @ returned r0 slow_syscall_return: add sp, sp, #S_OFF -ret_from_sys_call: -#ifdef HARVARD_CACHE - ldr r0, bh_data - ldr r4, bh_data+4 -#else - adr r0, bh_data - ldmia r0, {r0, r4} -#endif - ldr r0, [r0] - ldr r1, [r4] +ret_from_sys_call: @ external entry + get_softirq r0 + ldmia r0, {r0, r1} + mov r4, #1 @ flag this as being syscall return tst r0, r1 - blne SYMBOL_NAME(do_bottom_half) -ret_with_reschedule: + blne SYMBOL_NAME(do_softirq) +ret_with_reschedule: @ external entry (__irq_usr) get_current_task r5 ldr r0, [r5, #TSK_NEED_RESCHED] ldr r1, [r5, #TSK_SIGPENDING] @@ -43,30 +45,23 @@ ret_with_reschedule: teq r1, #0 @ check for signals bne ret_signal -ret_from_all: restore_user_regs +ret_from_all: restore_user_regs @ internal -ret_signal: mov r1, sp +ret_signal: mov r1, sp @ internal adrsvc al, lr, ret_from_all mov r2, r4 b SYMBOL_NAME(do_signal) -ret_reschedule: adrsvc al, lr, ret_with_reschedule +ret_reschedule: adrsvc al, lr, ret_with_reschedule @ internal b SYMBOL_NAME(schedule) .globl ret_from_exception -ret_from_exception: -#ifdef HARVARD_CACHE - ldr r0, bh_data - ldr r1, bh_data + 4 -#else - adr r0, bh_data +ret_from_exception: @ external entry + get_softirq r0 ldmia r0, {r0, r1} -#endif - ldr r0, [r0] - ldr r1, [r1] mov r4, #0 tst r0, r1 - blne SYMBOL_NAME(do_bottom_half) + blne SYMBOL_NAME(do_softirq) ldr r0, [sp, #S_PSR] tst r0, #3 @ returning to user mode? beq ret_with_reschedule @@ -147,8 +142,8 @@ vector_swi: save_user_regs .align 5 -bh_data: .word SYMBOL_NAME(bh_mask) - .word SYMBOL_NAME(bh_active) +__softirq_state: + .word SYMBOL_NAME(softirq_state) ENTRY(sys_call_table) #include "calls.S" diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index f6c310905dd9..6e3c863d5f78 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -237,16 +237,8 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) irq_exit(cpu, irq); - /* - * This should be conditional: we should really get - * a return code from the irq handler to tell us - * whether the handler wants us to do software bottom - * half handling or not.. - */ - if (1) { - if (bh_active & bh_mask) - do_bottom_half(); - } + if (softirq_state[cpu].active & softirq_state[cpu].mask) + do_softirq(); } #if defined(CONFIG_ARCH_ACORN) diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c index 71bf85e093e3..a2ec71526b0e 100644 --- a/arch/arm/kernel/semaphore.c +++ b/arch/arm/kernel/semaphore.c @@ -164,6 +164,126 @@ int __down_trylock(struct semaphore * sem) return 1; } +struct rw_semaphore *down_read_failed_biased(struct rw_semaphore *sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + add_wait_queue(&sem->wait, &wait); /* put ourselves at the head of the list */ + + for (;;) { + if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0)) + break; + set_task_state(tsk, TASK_UNINTERRUPTIBLE); + if (!sem->read_bias_granted) + schedule(); + } + + remove_wait_queue(&sem->wait, &wait); + tsk->state = TASK_RUNNING; + + return sem; +} + +struct rw_semaphore *down_write_failed_biased(struct rw_semaphore *sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */ + + for (;;) { + if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0)) + break; + set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + if (!sem->write_bias_granted) + schedule(); + } + + remove_wait_queue(&sem->write_bias_wait, &wait); + tsk->state = TASK_RUNNING; + + /* if the lock is currently unbiased, awaken the sleepers + * FIXME: this wakes up the readers early in a bit of a + * stampede -> bad! + */ + if (atomic_read(&sem->count) >= 0) + wake_up(&sem->wait); + + return sem; +} + +/* Wait for the lock to become unbiased. Readers + * are non-exclusive. =) + */ +struct rw_semaphore *down_read_failed(struct rw_semaphore *sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + /* this takes care of granting the lock */ + __up_op_read(sem, __rwsem_wake); + + add_wait_queue(&sem->wait, &wait); + + while (atomic_read(&sem->count) < 0) { + set_task_state(tsk, TASK_UNINTERRUPTIBLE); + if (atomic_read(&sem->count) >= 0) + break; + schedule(); + } + + remove_wait_queue(&sem->wait, &wait); + tsk->state = TASK_RUNNING; + + return sem; +} + +/* Wait for the lock to become unbiased. Since we're + * a writer, we'll make ourselves exclusive. + */ +struct rw_semaphore *down_write_failed(struct rw_semaphore *sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + /* this takes care of granting the lock */ + __up_op_write(sem, __rwsem_wake); + + add_wait_queue_exclusive(&sem->wait, &wait); + + while (atomic_read(&sem->count) < 0) { + set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + if (atomic_read(&sem->count) >= 0) + break; /* we must attempt to aquire or bias the lock */ schedule(); + } + + remove_wait_queue(&sem->wait, &wait); + tsk->state = TASK_RUNNING; + + return sem; +} + +/* Called when someone has done an up that transitioned from + * negative to non-negative, meaning that the lock has been + * granted to whomever owned the bias. + */ +struct rw_semaphore *rwsem_wake_readers(struct rw_semaphore *sem) +{ + if (xchg(&sem->read_bias_granted, 1)) + BUG(); + wake_up(&sem->wait); + return sem; +} + +struct rw_semaphore *rwsem_wake_writer(struct rw_semaphore *sem) +{ + if (xchg(&sem->write_bias_granted, 1)) + BUG(); + wake_up(&sem->write_bias_wait); + return sem; +} + /* * The semaphore operations have a special calling sequence that * allow us to do a simpler in-line version of them. These routines @@ -174,30 +294,65 @@ int __down_trylock(struct semaphore * sem) * registers (r0 to r3, ip and lr) except r0 in the cases where it * is used as a return value.. */ -asm(".align 5 +asm(" .section .text.lock, \"ax\" + .align 5 .globl __down_failed __down_failed: stmfd sp!, {r0 - r3, ip, lr} bl __down - ldmfd sp!, {r0 - r3, ip, pc}"); + ldmfd sp!, {r0 - r3, ip, pc} -asm(".align 5 + .align 5 .globl __down_interruptible_failed __down_interruptible_failed: stmfd sp!, {r1 - r3, ip, lr} bl __down_interruptible - ldmfd sp!, {r1 - r3, ip, pc}"); + ldmfd sp!, {r1 - r3, ip, pc} -asm(".align 5 + .align 5 .globl __down_trylock_failed __down_trylock_failed: stmfd sp!, {r1 - r3, ip, lr} bl __down_trylock - ldmfd sp!, {r1 - r3, ip, pc}"); + ldmfd sp!, {r1 - r3, ip, pc} -asm(".align 5 + .align 5 .globl __up_wakeup __up_wakeup: stmfd sp!, {r0 - r3, ip, lr} bl __up - ldmfd sp!, {r0 - r3, ip, pc}"); + ldmfd sp!, {r0 - r3, ip, pc} + + .align 5 + .globl __down_read_failed +__down_read_failed: + stmfd sp!, {r0 - r3, ip, lr} + bcc 1f + bl down_read_failed_biased + ldmfd sp!, {r0 - r3, ip, pc} +1: bl down_read_failed + /***/ + + .align 5 + .globl __down_write_failed +__down_write_failed: + stmfd sp!, {r0 - r3, ip, lr} + bcc 1f + bl down_write_failed_biased + ldmfd sp!, {r0 - r3, ip, pc} +1: bl down_write_failed + /***/ + + .align 5 + .globl __rwsem_wake +__rwsem_wake: + stmfd sp!, {r0 - r3, ip, lr} + beq 1f + bl rwsem_wake_readers + ldmfd sp!, {r0 - r3, ip, pc} +1: bl rwsem_wake_writer + ldmfd sp!, {r0 - r3, ip, pc} + + .previous + "); + diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index b9bffb7c95b6..1c02473bbd36 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -8,8 +8,8 @@ # Note 2! The CFLAGS definition is now in the main makefile... O_TARGET := mm.o -O_OBJS := init.o extable.o fault-$(PROCESSOR).o mm-$(PROCESSOR).o \ - small_page.o +O_OBJS := consistent.o extable.o fault-$(PROCESSOR).o init.o \ + mm-$(PROCESSOR).o small_page.o ifeq ($(CONFIG_CPU_26),y) O_OBJS += proc-arm2,3.o diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c new file mode 100644 index 000000000000..4fece516d9c8 --- /dev/null +++ b/arch/arm/mm/consistent.c @@ -0,0 +1,102 @@ +/* + * Dynamic DMA mapping support. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Pure 2^n version of get_order */ +extern __inline__ int __get_order(unsigned long size) +{ + int order; + + size = (size-1) >> (PAGE_SHIFT-1); + order = -1; + do { + size >>= 1; + order++; + } while (size); + return order; +} + +/* + * This allocates one page of cache-coherent memory space and returns + * both the virtual and a "dma" address to that space. It is not clear + * whether this could be called from an interrupt context or not. For + * now, we expressly forbid it, especially as some of the stuff we do + * here is not interrupt context safe. + */ +void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle) +{ + int order; + unsigned long page; + struct vm_struct *area; + void *ret; + + if (in_interrupt()) + BUG(); + + order = __get_order(size); + + page = __get_free_pages(gfp, order); + if (!page) + goto no_page; + + memset((void *)page, 0, PAGE_SIZE << order); + clean_cache_area(page, PAGE_SIZE << order); + + *dma_handle = virt_to_bus((void *)page); + + area = get_vm_area(size, VM_IOREMAP); /* maybe new type? */ + if (!area) + goto no_area; + + ret = __ioremap(virt_to_phys((void *)page), PAGE_SIZE << order, 0); + if (ret) + return ret; + +no_area: + free_pages(page, order); +no_page: + BUG(); + return NULL; +} + +/* + * free a page as defined by the above mapping. We expressly forbid + * calling this from interrupt context. + */ +void consistent_free(void *vaddr) +{ + if (in_interrupt()) + BUG(); + + __iounmap(vaddr); +} + +/* + * make an area consistent. + */ +void consistent_sync(void *vaddr, size_t size, int rw) +{ + switch (rw) { + case 0: + BUG(); + case 1: /* invalidate only */ + dma_cache_inv(vaddr, size); + break; + case 2: /* writeback only */ + dma_cache_wback(vaddr, size); + break; + case 3: /* writeback and invalidate */ + dma_cache_wback_inv(vaddr, size); + break; + } +} diff --git a/arch/arm/mm/proc-arm6,7.S b/arch/arm/mm/proc-arm6,7.S index 23508c197ed1..b83f05a05469 100644 --- a/arch/arm/mm/proc-arm6,7.S +++ b/arch/arm/mm/proc-arm6,7.S @@ -103,9 +103,9 @@ msg: .ascii "DA*%p=%p\n\0" .align ENTRY(cpu_arm6_data_abort) -Ldata_simple: ldr r4, [r0] @ read instruction causing problem mov r2, r4, lsr #19 @ r2 b1 = L +Ldata_simple: and r2, r2, #2 @ check read/write bit mrc p15, 0, r0, c6, c0, 0 @ get FAR mrc p15, 0, r1, c5, c0, 0 @ get FSR diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c index b9ca935ebf79..9d4f1570d500 100644 --- a/arch/arm/nwfpe/fpmodule.c +++ b/arch/arm/nwfpe/fpmodule.c @@ -128,23 +128,41 @@ cumulative exceptions flag byte are set and we return. void float_raise(signed char flags) { + register unsigned int fpsr, cumulativeTraps; + #ifdef CONFIG_DEBUG_USER printk(KERN_DEBUG "NWFPE: %s[%d] takes exception %08x at %p from %08x\n", current->comm, current->pid, flags, __builtin_return_address(0), userRegisters[15]); #endif + /* Keep SoftFloat exception flags up to date. */ float_exception_flags |= flags; - if (readFPSR() & (flags << 16)) - { - /* raise exception */ + + /* Read fpsr and initialize the cumulativeTraps. */ + fpsr = readFPSR(); + cumulativeTraps = 0; + + /* For each type of exception, the cumulative trap exception bit is only + set if the corresponding trap enable bit is not set. */ + if ((!(fpsr & BIT_IXE)) && (flags & BIT_IXC)) + cumulativeTraps |= BIT_IXC; + if ((!(fpsr & BIT_UFE)) && (flags & BIT_UFC)) + cumulativeTraps |= BIT_UFC; + if ((!(fpsr & BIT_OFE)) && (flags & BIT_OFC)) + cumulativeTraps |= BIT_OFC; + if ((!(fpsr & BIT_DZE)) && (flags & BIT_DZC)) + cumulativeTraps |= BIT_DZC; + if ((!(fpsr & BIT_IOE)) && (flags & BIT_IOC)) + cumulativeTraps |= BIT_IOC; + + /* Set the cumulative exceptions flags. */ + if (cumulativeTraps) + writeFPSR(fpsr | cumulativeTraps); + + /* Raise an exception if necessary. */ + if (fpsr & (flags << 16)) fp_send_sig(SIGFPE, current, 1); - } - else - { - /* set the cumulative exceptions flags */ - writeFPSR(flags); - } } module_init(fpe_init); diff --git a/arch/arm/nwfpe/fpsr.h b/arch/arm/nwfpe/fpsr.h index f40f3872c199..6dafb0f5243c 100644 --- a/arch/arm/nwfpe/fpsr.h +++ b/arch/arm/nwfpe/fpsr.h @@ -63,12 +63,12 @@ typedef unsigned int FPCR; /* type for floating point control register */ #define MASK_SYSTEM_CONTROL 0x0000ff00 #define MASK_TRAP_STRICT 0x00001f00 -#define BIT_AC 0x00100000 /* use alternative C-flag definition +#define BIT_AC 0x00001000 /* use alternative C-flag definition for compares */ -#define BIT_EP 0x00080000 /* use expanded packed decimal format */ -#define BIT_SO 0x00040000 /* select synchronous operation of FPA */ -#define BIT_NE 0x00020000 /* NaN exception bit */ -#define BIT_ND 0x00010000 /* no denormalized numbers bit */ +#define BIT_EP 0x00000800 /* use expanded packed decimal format */ +#define BIT_SO 0x00000400 /* select synchronous operation of FPA */ +#define BIT_NE 0x00000200 /* NaN exception bit */ +#define BIT_ND 0x00000100 /* no denormalized numbers bit */ /* CUMULATIVE EXCEPTION FLAGS BYTE ---------------------------------- */ diff --git a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S index 4a9d59908cd0..f345ea1004cf 100644 --- a/arch/i386/boot/bootsect.S +++ b/arch/i386/boot/bootsect.S @@ -106,9 +106,8 @@ go: movw $0x4000-12, %di # 0x4000 is an arbitrary value >= pushw %ds ldsw %fs:(%bx), %si # ds:si is source movb $6, %cl # copy 12 bytes - cld pushw %di # di = 0x4000-12. - rep + rep # don't need cld -> done on line 66 movsw popw %di popw %ds @@ -140,20 +139,7 @@ load_setup: jmp load_setup ok_load_setup: -# Get disk drive parameters, specifically nr of sectors/track. - -#if 0 - -# bde - the Phoenix BIOS manual says function 0x08 only works for fixed -# disks. It doesn't work for one of my BIOS's (1987 Award). It was -# fatal not to check the error code. - - xorb %dl, %dl - movb $0x08, %ah # AH=8 is get drive parameters - int $0x13 - xorb %ch, %ch - -#else +# Get disk drive parameters, specifically number of sectors/track. # It seems that there is no BIOS call to get the number of sectors. # Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18 @@ -176,7 +162,6 @@ probe_loop: movw $0x0201, %ax # service 2, 1 sector int $0x13 jc probe_loop # try next value -#endif got_sectors: movw $INITSEG, %ax @@ -200,11 +185,11 @@ got_sectors: # Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8) # depending on the number of sectors we pretend to know we have. - movw %cs:root_dev, %ax + movw root_dev, %ax orw %ax, %ax jne root_defined - movw %cs:sectors, %bx + movw sectors, %bx movw $0x0208, %ax # /dev/ps0 - 1.2Mb cmpw $15, %bx je root_defined @@ -219,7 +204,7 @@ got_sectors: movb $0, %al # /dev/fd0 - autodetect root_defined: - movw %ax, %cs:root_dev + movw %ax, root_dev # After that (everything loaded), we jump to the setup-routine # loaded directly after the bootblock: diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c index 5308572d9057..d5b2b0062f70 100644 --- a/arch/i386/kernel/pci-pc.c +++ b/arch/i386/kernel/pci-pc.c @@ -1057,8 +1057,8 @@ static void __init pcibios_irq_peer_trick(struct irq_routing_table *rt) static unsigned int pcibios_irq_mask = 0xfff8; static unsigned pcibios_irq_penalty[16] = { - 1000, 1000, 1000, 10, 10, 0, 0, 10, - 0, 0, 0, 0, 10, 100, 100, 100 + 10000, 10000, 10000, 100, 100, 0, 0, 100, + 0, 0, 0, 0, 100, 1000, 1000, 1000 }; static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *rt, int pin, int assign) diff --git a/arch/ia64/config.in b/arch/ia64/config.in index d006c1d05a7e..2d2388590c68 100644 --- a/arch/ia64/config.in +++ b/arch/ia64/config.in @@ -3,6 +3,8 @@ mainmenu_name "Kernel configuration of Linux for IA-64 machines" mainmenu_option next_comment comment 'General setup' +define_bool CONFIG_IA64 y + choice 'IA-64 system type' \ "Generic CONFIG_IA64_GENERIC \ HP-simulator CONFIG_IA64_HP_SIM \ diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S index 1342e64f0125..82ba58129beb 100644 --- a/arch/ia64/ia32/ia32_entry.S +++ b/arch/ia64/ia32/ia32_entry.S @@ -144,7 +144,7 @@ ia32_syscall_table: data8 sys32_settimeofday data8 sys_getgroups /* 80 */ data8 sys_setgroups - data8 sys_ni_syscall + data8 old_select data8 sys_symlink data8 sys_ni_syscall data8 sys_readlink /* 85 */ diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c index ed443ee66dde..2c2c53741e20 100644 --- a/arch/ia64/ia32/ia32_signal.c +++ b/arch/ia64/ia32/ia32_signal.c @@ -342,7 +342,16 @@ ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info, } asmlinkage int -sys32_sigreturn(int arg1, int arg2, int arg3, int arg4, int arg5, unsigned long stack) +sys32_sigreturn( +int arg0, +int arg1, +int arg2, +int arg3, +int arg4, +int arg5, +int arg6, +int arg7, +unsigned long stack) { struct pt_regs *regs = (struct pt_regs *) &stack; struct sigframe_ia32 *frame = (struct sigframe_ia32 *)(regs->r12- 8); @@ -375,7 +384,16 @@ badframe: } asmlinkage int -sys32_rt_sigreturn(int arg1, int arg2, int arg3, int arg4, int arg5, unsigned long stack) +sys32_rt_sigreturn( +int arg0, +int arg1, +int arg2, +int arg3, +int arg4, +int arg5, +int arg6, +int arg7, +unsigned long stack) { struct pt_regs *regs = (struct pt_regs *) &stack; struct rt_sigframe_ia32 *frame = (struct rt_sigframe_ia32 *)(regs->r12 - 4); diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 7b4c4995eb92..d61f1cfe5e14 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -240,18 +240,29 @@ do_mmap_fake(struct file *file, unsigned long addr, unsigned long len, return -EINVAL; if (prot & PROT_WRITE) prot |= PROT_EXEC; +#ifdef DDD +#else // DDD + prot |= PROT_WRITE; +#endif // DDD front = NULL; back = NULL; if ((baddr = (addr & PAGE_MASK)) != addr && get_user(c, (char *)baddr) == 0) { front = kmalloc(addr - baddr, GFP_KERNEL); memcpy(front, (void *)baddr, addr - baddr); } - if ((addr + len) & ~PAGE_MASK && get_user(c, (char *)(addr + len)) == 0) { +#ifndef DDD + if (addr) +#endif + if (((addr + len) & ~PAGE_MASK) && get_user(c, (char *)(addr + len)) == 0) { back = kmalloc(PAGE_SIZE - ((addr + len) & ~PAGE_MASK), GFP_KERNEL); memcpy(back, addr + len, PAGE_SIZE - ((addr + len) & ~PAGE_MASK)); } if ((r = do_mmap(0, baddr, len + (addr - baddr), prot, flags | MAP_ANONYMOUS, 0)) < 0) return(r); +#ifndef DDD + if (addr == 0) + addr = r; +#endif // DDD if (back) { memcpy(addr + len, back, PAGE_SIZE - ((addr + len) & ~PAGE_MASK)); kfree(back); @@ -315,7 +326,11 @@ sys32_mmap(struct mmap_arg_struct *arg) } a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); +#ifdef DDD if ((a.flags & MAP_FIXED) && ((a.addr & ~PAGE_MASK) || (a.offset & ~PAGE_MASK))) { +#else // DDD + if (1) { +#endif // DDD unlock_kernel(); up(¤t->mm->mmap_sem); error = do_mmap_fake(file, a.addr, a.len, a.prot, a.flags, a.offset); @@ -665,7 +680,7 @@ struct dirent32 { }; static void -xlate_dirent(void *dirent, long n) +xlate_dirent(void *dirent64, void *dirent32, long n) { long off; struct dirent *dirp; @@ -673,9 +688,9 @@ xlate_dirent(void *dirent, long n) off = 0; while (off < n) { - dirp = (struct dirent *)(dirent + off); + dirp = (struct dirent *)(dirent64 + off); + dirp32 = (struct dirent32 *)(dirent32 + off); off += dirp->d_reclen; - dirp32 = (struct dirent32 *)dirp; dirp32->d_ino = dirp->d_ino; dirp32->d_off = (unsigned int)dirp->d_off; dirp32->d_reclen = dirp->d_reclen; @@ -685,26 +700,27 @@ xlate_dirent(void *dirent, long n) } asmlinkage long -sys32_getdents(unsigned int fd, void * dirent, unsigned int count) +sys32_getdents(unsigned int fd, void * dirent32, unsigned int count) { long n; + void *dirent64; - if ((n = sys_getdents(fd, dirent, count)) < 0) + dirent64 = (unsigned long)(dirent32 + (sizeof(long) - 1)) & ~(sizeof(long) - 1); + if ((n = sys_getdents(fd, dirent64, count - (dirent64 - dirent32))) < 0) return(n); - xlate_dirent(dirent, n); + xlate_dirent(dirent64, dirent32, n); return(n); } asmlinkage int -sys32_readdir(unsigned int fd, void * dirent, unsigned int count) +sys32_readdir(unsigned int fd, void * dirent32, unsigned int count) { int n; - struct dirent *dirp; + struct dirent dirent64; - if ((n = old_readdir(fd, dirent, count)) < 0) + if ((n = old_readdir(fd, &dirent64, count)) < 0) return(n); - dirp = (struct dirent *)dirent; - xlate_dirent(dirent, dirp->d_reclen); + xlate_dirent(&dirent64, dirent32, dirent64.d_reclen); return(n); } @@ -809,6 +825,23 @@ out_nofds: return ret; } +struct sel_arg_struct { + unsigned int n; + unsigned int inp; + unsigned int outp; + unsigned int exp; + unsigned int tvp; +}; + +asmlinkage int old_select(struct sel_arg_struct *arg) +{ + struct sel_arg_struct a; + + if (copy_from_user(&a, arg, sizeof(a))) + return -EFAULT; + return sys32_select(a.n, a.inp, a.outp, a.exp, a.tvp); +} + struct rusage32 { struct timeval32 ru_utime; struct timeval32 ru_stime; diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index dd7de2ab079e..6e0d09ea7f91 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -15,7 +15,6 @@ * * Implemented EFI runtime services and virtual mode calls. --davidm */ -#include #include #include #include @@ -166,14 +165,12 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg) case EFI_BOOT_SERVICES_CODE: case EFI_BOOT_SERVICES_DATA: case EFI_CONVENTIONAL_MEMORY: -#ifndef CONFIG_IA64_VIRTUAL_MEM_MAP if (md->phys_addr > 1024*1024*1024UL) { printk("Warning: ignoring %luMB of memory above 1GB!\n", md->num_pages >> 8); md->type = EFI_UNUSABLE_MEMORY; continue; } -#endif curr.start = PAGE_OFFSET + md->phys_addr; curr.end = curr.start + (md->num_pages << 12); diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 87e77c67733e..47b972cb492f 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -496,18 +496,27 @@ ia64_ret_from_syscall: (p7) br.cond.spnt.few handle_syscall_error // handle potential syscall failure ia64_leave_kernel: - // check & deliver software interrupts (bottom half handlers): + // check & deliver software interrupts: - movl r2=bh_active // sheesh, why aren't these two in - movl r3=bh_mask // a struct?? +#ifdef CONFIG_SMP + adds r2=IA64_TASK_PROCESSOR_OFFSET,r13 + movl r3=softirq_state ;; - ld8 r2=[r2] - ld8 r3=[r3] + ld4 r2=[r2] + ;; + shladd r3=r2,3,r3 +#else + movl r3=softirq_state +#endif + ;; + ld8 r2=[r3] // r3 is guaranteed to be 8-byte aligned! + ;; + shr r3=r2,32 ;; and r2=r2,r3 ;; - cmp.ne p6,p7=r2,r0 // any soft interrupts ready for delivery? -(p6) br.call.dpnt.few rp=invoke_do_bottom_half + cmp4.ne p6,p7=r2,r0 +(p6) br.call.spnt.many rp=invoke_do_softirq 1: (pKern) br.cond.dpnt.many restore_all // yup -> skip check for rescheduling & signal delivery @@ -751,20 +760,20 @@ invoke_schedule_tail: #endif /* CONFIG_SMP */ /* - * Invoke do_bottom_half() while preserving in0-in7, which may be needed + * Invoke do_softirq() while preserving in0-in7, which may be needed * in case a system call gets restarted. */ - .proc invoke_do_bottom_half -invoke_do_bottom_half: + .proc invoke_do_softirq +invoke_do_softirq: alloc loc0=ar.pfs,8,2,0,0 mov loc1=rp ;; - br.call.sptk.few rp=do_bottom_half + br.call.sptk.few rp=do_softirq .ret9: mov ar.pfs=loc0 mov rp=loc1 br.ret.sptk.many rp - .endp invoke_do_bottom_half + .endp invoke_do_softirq /* * Invoke schedule() while preserving in0-in7, which may be needed diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S index 24dc10ee4e00..65de8e589712 100644 --- a/arch/ia64/kernel/gate.S +++ b/arch/ia64/kernel/gate.S @@ -132,6 +132,7 @@ back_from_setup_rbs: ld8 r8=[base0] // restore (perhaps modified) CFM0, EC0, and CPL0 cmp.ne p8,p0=r14,r15 // do we need to restore the rbs? (p8) br.cond.spnt.few restore_rbs // yup -> (clobbers r14 and r16) + ;; back_from_restore_rbs: { and r9=0x7f,r8 // r9 <- CFM0.sof diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index 50d965e029f0..35a52628ae09 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -133,6 +133,7 @@ alive_msg: #endif /* CONFIG_IA64_EARLY_PRINTK */ alloc r2=ar.pfs,8,0,2,0 + ;; #ifdef CONFIG_SMP (isAP) br.call.sptk.few rp=smp_callin .ret1: @@ -174,7 +175,7 @@ ia64_save_debug_regs: st8.nta [in0]=r16,8 st8.nta [r19]=r17,8 br.cloop.sptk.few 1b - + ;; mov ar.lc=r20 // restore ar.lc br.ret.sptk.few b0 .endp ia64_save_debug_regs @@ -197,7 +198,7 @@ ia64_load_debug_regs: mov dbr[r18]=r16 mov ibr[r18]=r17 br.cloop.sptk.few 1b - + ;; mov ar.lc=r20 // restore ar.lc br.ret.sptk.few b0 .endp ia64_load_debug_regs diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index 01c20113757f..5efe501645fc 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -128,6 +128,18 @@ get_irq_list (char *buf) return p - buf; } +int usbfix; + +static int __init +usbfix_option (char *str) +{ + printk("irq: enabling USB workaround\n"); + usbfix = 1; + return 1; +} + +__setup("usbfix", usbfix_option); + /* * That's where the IVT branches when we get an external * interrupt. This branches to the correct hardware IRQ handler via @@ -146,7 +158,8 @@ ia64_handle_irq (unsigned long irq, struct pt_regs *regs) unsigned long eoi_ptr; # ifdef CONFIG_USB - disable_usb(); + if (usbfix) + disable_usb(); # endif /* * Stop IPIs by getting the ivr_read_lock @@ -170,7 +183,8 @@ ia64_handle_irq (unsigned long irq, struct pt_regs *regs) spin_unlock(&ivr_read_lock); # ifdef CONFIG_USB - reenable_usb(); + if (usbfix) + reenable_usb(); # endif # ifndef CONFIG_SMP diff --git a/arch/ia64/kernel/irq_lock.c b/arch/ia64/kernel/irq_lock.c index 9c512dd4ef74..4a2ead673840 100644 --- a/arch/ia64/kernel/irq_lock.c +++ b/arch/ia64/kernel/irq_lock.c @@ -26,7 +26,7 @@ int global_irq_holder = NO_PROC_ID; spinlock_t global_irq_lock; atomic_t global_irq_count; atomic_t global_bh_count; -atomic_t global_bh_lock; +spinlock_t global_bh_lock; #define INIT_STUCK (1<<26) diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c index f86f45537587..9989356d3eba 100644 --- a/arch/ia64/kernel/pci-dma.c +++ b/arch/ia64/kernel/pci-dma.c @@ -21,7 +21,7 @@ extern __inline__ unsigned long get_order (unsigned long size) { - unsigned long order = ia64_fls(size); + unsigned long order = ia64_fls(size - 1) + 1; printk ("get_order: size=%lu, order=%lu\n", size, order); diff --git a/arch/ia64/kernel/pci.c b/arch/ia64/kernel/pci.c index 3bceeed8e1ad..4acc7f04182d 100644 --- a/arch/ia64/kernel/pci.c +++ b/arch/ia64/kernel/pci.c @@ -226,14 +226,3 @@ void pcibios_align_resource (void *data, struct resource *res, unsigned long size) { } - -#if 0 /*def CONFIG_PROC_FS*/ -/* - * This is an ugly hack to get a (weak) unresolved reference to something that is - * in drivers/pci/proc.c. Without this, the file does not get linked in at all - * (I suspect the reason this isn't needed on Linux/x86 is that most people compile - * with module support, in which case the EXPORT_SYMBOL() stuff will ensure the - * code gets linked in. Sigh... --davidm 99/12/20. - */ -asm ("data8 proc_bus_pci_add"); -#endif diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c index 48a3d68b4b85..ed5d594a63b0 100644 --- a/arch/ia64/kernel/smp.c +++ b/arch/ia64/kernel/smp.c @@ -57,7 +57,7 @@ spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; unsigned long cpu_online_map = 1; #endif -volatile int cpu_number_map[NR_CPUS] = { -1, }; /* SAPIC ID -> Logical ID */ +volatile int __cpu_number_map[NR_CPUS] = { -1, }; /* SAPIC ID -> Logical ID */ volatile int __cpu_logical_map[NR_CPUS] = { -1, }; /* logical ID -> SAPIC ID */ int smp_num_cpus = 1; int bootstrap_processor = -1; /* SAPIC ID of BSP */ @@ -586,7 +586,7 @@ smp_boot_one_cpu(int cpuid, int cpunum) alive: /* Remember the AP data */ - cpu_number_map[cpuid] = cpunum; + __cpu_number_map[cpuid] = cpunum; #ifdef CONFIG_KDB cpu_online_map |= (1<processor = bootstrap_processor; diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index 18a498a09ed5..f06d3bea8e3a 100644 --- a/arch/ia64/kernel/sys_ia64.c +++ b/arch/ia64/kernel/sys_ia64.c @@ -2,8 +2,8 @@ * This file contains various system calls that have different calling * conventions on different platforms. * - * Copyright (C) 1999 Hewlett-Packard Co - * Copyright (C) 1999 David Mosberger-Tang + * Copyright (C) 1999-2000 Hewlett-Packard Co + * Copyright (C) 1999-2000 David Mosberger-Tang */ #include #include diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile index 8a958174799d..88a4aadd4797 100644 --- a/arch/ia64/lib/Makefile +++ b/arch/ia64/lib/Makefile @@ -3,7 +3,7 @@ # .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $@ + $(CC) -D__ASSEMBLY__ $(AFLAGS) -c $< -o $@ OBJS = __divdi3.o __divsi3.o __udivdi3.o __udivsi3.o \ __moddi3.o __modsi3.o __umoddi3.o __umodsi3.o \ diff --git a/arch/ia64/tools/print_offsets.c b/arch/ia64/tools/print_offsets.c index 85b15aae1ffe..f1b298e21122 100644 --- a/arch/ia64/tools/print_offsets.c +++ b/arch/ia64/tools/print_offsets.c @@ -47,6 +47,7 @@ tab[] = { "IA64_TASK_FLAGS_OFFSET", offsetof (struct task_struct, flags) }, { "IA64_TASK_SIGPENDING_OFFSET", offsetof (struct task_struct, sigpending) }, { "IA64_TASK_NEED_RESCHED_OFFSET", offsetof (struct task_struct, need_resched) }, + { "IA64_TASK_PROCESSOR_OFFSET", offsetof (struct task_struct, processor) }, { "IA64_TASK_THREAD_OFFSET", offsetof (struct task_struct, thread) }, { "IA64_TASK_THREAD_KSP_OFFSET", offsetof (struct task_struct, thread.ksp) }, { "IA64_TASK_PID_OFFSET", offsetof (struct task_struct, pid) }, diff --git a/arch/ppc/coffboot/misc.S b/arch/ppc/coffboot/misc.S index 7defc69e870d..05639bdd1c24 100644 --- a/arch/ppc/coffboot/misc.S +++ b/arch/ppc/coffboot/misc.S @@ -9,7 +9,7 @@ .text /* - * Use the BAT0 registers to map the 1st 8MB of RAM to + * Use the BAT3 registers to map the 1st 8MB of RAM to * the address given as the 1st argument. */ .globl setup_bats diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig index ac258f16e74b..17217702f868 100644 --- a/arch/ppc/configs/common_defconfig +++ b/arch/ppc/configs/common_defconfig @@ -24,7 +24,7 @@ CONFIG_ALL_PPC=y # CONFIG_GEMINI is not set # CONFIG_APUS is not set # CONFIG_SMP is not set -# CONFIG_ALTIVEC is not set +CONFIG_ALTIVEC=y # # Loadable module support @@ -76,7 +76,7 @@ CONFIG_BOOTX_TEXT=y # # Block devices # -CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_DEV_FD is not set CONFIG_BLK_DEV_IDE=y # @@ -178,9 +178,12 @@ CONFIG_SCSI=y # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=y +CONFIG_ST_EXTRA_DEVS=2 CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_SR_EXTRA_DEVS=2 CONFIG_CHR_DEV_SG=y # @@ -239,6 +242,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20 # CONFIG_SCSI_QLOGIC_FAS is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_SEAGATE is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_T128 is not set @@ -275,6 +279,7 @@ CONFIG_NETDEVICES=y CONFIG_NET_ETHERNET=y CONFIG_MACE=y CONFIG_BMAC=y +CONFIG_GMAC=y # CONFIG_NCR885E is not set # CONFIG_OAKNET is not set # CONFIG_NET_VENDOR_3COM is not set @@ -472,6 +477,7 @@ CONFIG_USB=y # USB Controllers # # CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set CONFIG_USB_OHCI=y # @@ -491,8 +497,7 @@ CONFIG_USB_OHCI=y # CONFIG_USB_IBMCAM is not set # CONFIG_USB_OV511 is not set # CONFIG_USB_DC2XX is not set -CONFIG_USB_SCSI=m -CONFIG_USB_SCSI_DEBUG=y +# CONFIG_USB_STORAGE is not set # CONFIG_USB_DABUSB is not set # @@ -513,11 +518,15 @@ CONFIG_USB_MOUSE=y # # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set +CONFIG_HFS_FS=y # CONFIG_BFS_FS is not set -# CONFIG_FAT_FS is not set +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=y # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set CONFIG_ISO9660_FS=y @@ -549,10 +558,51 @@ CONFIG_LOCKD=y # # Partition Types # -# CONFIG_PARTITION_ADVANCED is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set CONFIG_MAC_PARTITION=y CONFIG_MSDOS_PARTITION=y -# CONFIG_NLS is not set +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +CONFIG_NLS=y + +# +# Native Language Support +# +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set # # Sound diff --git a/arch/ppc/configs/gemini_defconfig b/arch/ppc/configs/gemini_defconfig index 6fe267c9a184..90cc5b71f3dc 100644 --- a/arch/ppc/configs/gemini_defconfig +++ b/arch/ppc/configs/gemini_defconfig @@ -24,7 +24,7 @@ CONFIG_6xx=y CONFIG_GEMINI=y # CONFIG_APUS is not set # CONFIG_SMP is not set -# CONFIG_ALTIVEC is not set +CONFIG_ALTIVEC=y CONFIG_MACH_SPECIFIC=y # @@ -87,7 +87,6 @@ CONFIG_KERNEL_ELF=y # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_XD is not set # CONFIG_BLK_DEV_DAC960 is not set -CONFIG_PARIDE_PARPORT=y # CONFIG_PARIDE is not set # CONFIG_BLK_DEV_IDE_MODES is not set # CONFIG_BLK_DEV_HD is not set @@ -151,9 +150,12 @@ CONFIG_SCSI=y # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 # CONFIG_CHR_DEV_ST is not set +CONFIG_ST_EXTRA_DEVS=2 CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_SR_EXTRA_DEVS=2 # CONFIG_CHR_DEV_SG is not set # @@ -208,6 +210,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20 # CONFIG_SCSI_QLOGIC_FAS is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_SEAGATE is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_T128 is not set @@ -216,6 +219,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20 # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_MESH is not set # CONFIG_SCSI_MAC53C94 is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # # IEEE 1394 (FireWire) support @@ -242,6 +246,7 @@ CONFIG_NETDEVICES=y CONFIG_NET_ETHERNET=y # CONFIG_MACE is not set # CONFIG_BMAC is not set +# CONFIG_GMAC is not set CONFIG_NCR885E=y # CONFIG_OAKNET is not set # CONFIG_NET_VENDOR_3COM is not set @@ -369,6 +374,7 @@ CONFIG_UNIX98_PTY_COUNT=256 # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -405,10 +411,7 @@ CONFIG_LOCKD=y # Partition Types # # CONFIG_PARTITION_ADVANCED is not set -CONFIG_MAC_PARTITION=y CONFIG_MSDOS_PARTITION=y -# CONFIG_SGI_PARTITION is not set -# CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set # diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig index ac258f16e74b..17217702f868 100644 --- a/arch/ppc/defconfig +++ b/arch/ppc/defconfig @@ -24,7 +24,7 @@ CONFIG_ALL_PPC=y # CONFIG_GEMINI is not set # CONFIG_APUS is not set # CONFIG_SMP is not set -# CONFIG_ALTIVEC is not set +CONFIG_ALTIVEC=y # # Loadable module support @@ -76,7 +76,7 @@ CONFIG_BOOTX_TEXT=y # # Block devices # -CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_DEV_FD is not set CONFIG_BLK_DEV_IDE=y # @@ -178,9 +178,12 @@ CONFIG_SCSI=y # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=y +CONFIG_ST_EXTRA_DEVS=2 CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_SR_EXTRA_DEVS=2 CONFIG_CHR_DEV_SG=y # @@ -239,6 +242,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20 # CONFIG_SCSI_QLOGIC_FAS is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_SEAGATE is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_T128 is not set @@ -275,6 +279,7 @@ CONFIG_NETDEVICES=y CONFIG_NET_ETHERNET=y CONFIG_MACE=y CONFIG_BMAC=y +CONFIG_GMAC=y # CONFIG_NCR885E is not set # CONFIG_OAKNET is not set # CONFIG_NET_VENDOR_3COM is not set @@ -472,6 +477,7 @@ CONFIG_USB=y # USB Controllers # # CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set CONFIG_USB_OHCI=y # @@ -491,8 +497,7 @@ CONFIG_USB_OHCI=y # CONFIG_USB_IBMCAM is not set # CONFIG_USB_OV511 is not set # CONFIG_USB_DC2XX is not set -CONFIG_USB_SCSI=m -CONFIG_USB_SCSI_DEBUG=y +# CONFIG_USB_STORAGE is not set # CONFIG_USB_DABUSB is not set # @@ -513,11 +518,15 @@ CONFIG_USB_MOUSE=y # # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set +CONFIG_HFS_FS=y # CONFIG_BFS_FS is not set -# CONFIG_FAT_FS is not set +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=y # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set CONFIG_ISO9660_FS=y @@ -549,10 +558,51 @@ CONFIG_LOCKD=y # # Partition Types # -# CONFIG_PARTITION_ADVANCED is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set CONFIG_MAC_PARTITION=y CONFIG_MSDOS_PARTITION=y -# CONFIG_NLS is not set +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +CONFIG_NLS=y + +# +# Native Language Support +# +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set # # Sound diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index 2d1238a6baf3..013812afc4da 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -176,7 +176,7 @@ ret_from_syscall_2: 7: .string "syscall %d(%x, %x, %x, %x, %x, " 77: .string "%x, %x), current=%p\n" 79: .string " -> %x\n" - .align 2 + .align 2,0 #endif /* @@ -209,6 +209,9 @@ _GLOBAL(_switch) mflr r20 /* Return to switch caller */ mfmsr r22 li r0,MSR_FP /* Disable floating-point */ +#ifdef CONFIG_ALTIVEC + oris r0,r0,MSR_VEC@h +#endif /* CONFIG_ALTIVEC */ andc r22,r22,r0 stw r20,_NIP(r1) stw r22,_MSR(r1) @@ -274,7 +277,7 @@ _GLOBAL(_switch) SYNC rfi -#ifdef __SMP__ +#ifdef CONFIG_SMP .globl ret_from_smpfork ret_from_smpfork: bl schedule_tail @@ -310,22 +313,32 @@ ret_from_except: lwz r5,_MSR(r1) andi. r5,r5,MSR_EE beq 2f + .globl lost_irq_ret +lost_irq_ret: 3: lis r4,ppc_n_lost_interrupts@ha lwz r4,ppc_n_lost_interrupts@l(r4) cmpi 0,r4,0 beq+ 1f addi r3,r1,STACK_FRAME_OVERHEAD bl do_IRQ - .globl lost_irq_ret -lost_irq_ret: b 3b -1: lis r4,bh_mask@ha - lwz r4,bh_mask@l(r4) - lis r5,bh_active@ha - lwz r5,bh_active@l(r5) - and. r4,r4,r5 +1: lis r4,softirq_state@ha + addi r4,r4,softirq_state@l +#ifdef CONFIG_SMP + /* get processor # */ + lwz r3,PROCESSOR(r2) +#ifndef CONFIG_PPC64 + slwi r3,r3,5 +#else +#error not 64-bit ready +#endif + add r4,r4,r3 +#endif /* CONFIG_SMP */ + lwz r5,0(r4) + lwz r4,4(r4) + and. r5,r5,r4 beq+ 2f - bl do_bottom_half + bl do_softirq .globl do_bottom_half_ret do_bottom_half_ret: 2: /* disable interrupts */ diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index 8b56c635cba3..dd16b8c27174 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -460,8 +460,24 @@ SystemCall: STD_EXCEPTION(0xd00, SingleStep, SingleStepException) STD_EXCEPTION(0xe00, Trap_0e, UnknownException) -#ifdef CONFIG_ALTIVEC - STD_EXCEPTION(0xf20, AltiVec, AltiVecUnavailable) +#ifndef CONFIG_ALTIVEC + STD_EXCEPTION(0xf00, Trap_0f, UnknownException) +#else +/* + * The Altivec unavailable trap is at 0x0f20. Foo. + * We effectively remap it to 0x3000. + */ + . = 0xf00 + b Trap_0f +trap_0f_cont: + addi r3,r1,STACK_FRAME_OVERHEAD + li r20,MSR_KERNEL + bl transfer_to_handler + .long UnknownException + .long ret_from_except + + . = 0xf20 + b AltiVecUnavailable #endif /* CONFIG_ALTIVEC */ /* @@ -674,6 +690,21 @@ DataStoreTLBMiss: . = 0x3000 +#ifdef CONFIG_ALTIVEC +AltiVecUnavailable: + EXCEPTION_PROLOG + bne load_up_altivec /* if from user, just load it up */ + li r20,MSR_KERNEL + bl transfer_to_handler /* if from kernel, take a trap */ + .long KernelAltiVec + .long ret_from_except + +/* here are the bits of trap 0xf00 which got displaced */ +Trap_0f: + EXCEPTION_PROLOG + b trap_0f_cont +#endif /* CONFIG_ALTIVEC */ + /* * This code finishes saving the registers to the exception frame * and jumps to the appropriate handler for the exception, turning @@ -813,72 +844,134 @@ KernelFP: 86: .string "floating point used in kernel (task=%p, pc=%x)\n" .align 4 +#ifdef CONFIG_ALTIVEC +/* Note that the AltiVec support is closely modeled after the FP + * support. Changes to one are likely to be applicable to the + * other! */ +load_up_altivec: /* - * Take away the altivec regs. - * - * For now, ignore the vrsave regs and save them all - * -- Cort + * Disable AltiVec for the task which had AltiVec previously, + * and save its AltiVec registers in its thread_struct. + * Enables AltiVec for use in the kernel on return. + * On SMP we know the AltiVec units are free, since we give it up every + * switch. -- Kumar */ - .globl giveup_altivec -giveup_altivec: -#ifdef CONFIG_ALTIVEC - /* check for altivec */ - mfspr r4,PVR - srwi r4,r4,16 - cmpi 0,r4,12 - bnelr - - /* enable altivec so we can save */ - mfmsr r4 - oris r4,r4,MSR_VEC@h - mtmsr r4 + mfmsr r5 + oris r5,r5,MSR_VEC@h + SYNC + mtmsr r5 /* enable use of AltiVec now */ + SYNC +/* + * For SMP, we don't do lazy AltiVec switching because it just gets too + * horrendously complex, especially when a task switches from one CPU + * to another. Instead we call giveup_altivec in switch_to. + */ +#ifndef __SMP__ +#ifndef CONFIG_APUS + lis r6,-KERNELBASE@h +#else + lis r6,CYBERBASEp@h + lwz r6,0(r6) +#endif + addis r3,r6,last_task_used_altivec@ha + lwz r4,last_task_used_altivec@l(r3) + cmpi 0,r4,0 + beq 1f + add r4,r4,r6 + addi r4,r4,THREAD /* want THREAD of last_task_used_altivec */ + SAVE_32VR(0,r20,r4) + MFVSCR(vr0) + li r20,THREAD_VSCR + STVX(vr0,r20,r4) + lwz r5,PT_REGS(r4) + add r5,r5,r6 + lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) + lis r20,MSR_VEC@h + andc r4,r4,r20 /* disable altivec for previous task */ + stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) +1: +#endif /* __SMP__ */ + /* enable use of AltiVec after return */ + oris r23,r23,MSR_VEC@h + mfspr r5,SPRG3 /* current task's THREAD (phys) */ + li r20,THREAD_VSCR + LVX(vr0,r20,r5) + MTVSCR(vr0) + REST_32VR(0,r20,r5) +#ifndef __SMP__ + subi r4,r5,THREAD + sub r4,r4,r6 + stw r4,last_task_used_altivec@l(r3) +#endif /* __SMP__ */ + /* restore registers and return */ + lwz r3,_CCR(r21) + lwz r4,_LINK(r21) + mtcrf 0xff,r3 + mtlr r4 + REST_GPR(1, r21) + REST_4GPRS(3, r21) + /* we haven't used ctr or xer */ + mtspr SRR1,r23 + mtspr SRR0,r22 + REST_GPR(20, r21) + REST_2GPRS(22, r21) + lwz r21,GPR21(r21) + SYNC + rfi - /* make sure our tsk pointer is valid */ - cmpi 0,r3,0 - beqlr +/* + * AltiVec unavailable trap from kernel - print a message, but let + * the task use AltiVec in the kernel until it returns to user mode. + */ +KernelAltiVec: + lwz r3,_MSR(r1) + oris r3,r3,MSR_VEC@h + stw r3,_MSR(r1) /* enable use of AltiVec after return */ + lis r3,87f@h + ori r3,r3,87f@l + mr r4,r2 /* current */ + lwz r5,_NIP(r1) + bl printk + b ret_from_except +87: .string "AltiVec used in kernel (task=%p, pc=%x) \n" + .align 4 - /* save altivec regs */ - addi r4,r3,THREAD+THREAD_VRSAVE - mfspr r5,256 /* vrsave */ - stw r5,0(r4) - - /* get regs for the task */ - addi r4,r3,THREAD+PT_REGS - /* turn off the altivec bit in the tasks regs */ - lwz r5,_MSR(r4) - lis r6,MSR_VEC@h - andi. r5,r5,r6 - stw r5,_MSR(r4) - - /* we've given up the altivec - clear the pointer */ - li r3,0 - lis r4,last_task_used_altivec@h - stw r3,last_task_used_altivec@l(r4) -#endif /* CONFIG_ALTIVEC */ - blr - - .globl load_up_altivec -load_up_altivec: -#ifdef CONFIG_ALTIVEC - /* check for altivec */ - mfspr r4,PVR - srwi r4,r4,16 - cmpi 0,r4,12 - bnelr - - /* restore altivec regs */ - addi r4,r3,THREAD+THREAD_VRSAVE - lwz r5,0(r4) - mtspr 256,r5 /* vrsave */ - - /* get regs for the task */ - addi r4,r3,THREAD+PT_REGS - /* turn on the altivec bit in the tasks regs */ - lwz r5,_MSR(r4) +/* + * giveup_altivec(tsk) + * Disable AltiVec for the task given as the argument, + * and save the AltiVec registers in its thread_struct. + * Enables AltiVec for use in the kernel on return. + */ + + .globl giveup_altivec +giveup_altivec: + mfmsr r5 oris r5,r5,MSR_VEC@h - stw r5,_MSR(r4) -#endif /* CONFIG_ALTIVEC */ + SYNC + mtmsr r5 /* enable use of AltiVec now */ + SYNC + cmpi 0,r3,0 + beqlr- /* if no previous owner, done */ + addi r3,r3,THREAD /* want THREAD of task */ + lwz r5,PT_REGS(r3) + cmpi 0,r5,0 + SAVE_32VR(0, r4, r3) + MFVSCR(vr0) + li r4,THREAD_VSCR + STVX(vr0, r4, r3) + beq 1f + lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) + lis r3,MSR_VEC@h + andc r4,r4,r3 /* disable AltiVec for previous task */ + stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) +1: +#ifndef __SMP__ + li r5,0 + lis r4,last_task_used_altivec@ha + stw r5,last_task_used_altivec@l(r4) +#endif /* __SMP__ */ blr +#endif /* CONFIG_ALTIVEC */ /* * giveup_fpu(tsk) @@ -1437,17 +1530,16 @@ mmu_off: #if 0 /* That's useful debug stuff */ setup_screen_bat: + li r3,0 + mtspr DBAT1U,r3 + mtspr IBAT1U,r3 lis r3, 0x9100 -#ifdef __SMP__ - ori r3,r3,0x12 -#else - ori r3,r3,0x2 -#endif - mtspr DBAT1L, r3 - mtspr IBAT1L, r3 + ori r4,r3,0x2a + mtspr DBAT1L,r4 + mtspr IBAT1L,r4 ori r3,r3,(BL_8M<<2)|0x2 /* set up BAT registers for 604 */ - mtspr DBAT1U, r3 - mtspr IBAT1U, r3 + mtspr DBAT1U,r3 + mtspr IBAT1U,r3 blr #endif diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index 8b5f590fb780..fd77fbc367a4 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -74,8 +74,8 @@ volatile unsigned char *chrp_int_ack_special; irq_desc_t irq_desc[NR_IRQS]; int ppc_spurious_interrupts = 0; -unsigned int ppc_local_bh_count[NR_CPUS]; -unsigned int ppc_local_irq_count[NR_CPUS]; +unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS]; struct irqaction *ppc_irq_action[NR_IRQS]; unsigned int ppc_cached_irq_mask[NR_MASK_WORDS]; unsigned int ppc_lost_interrupts[NR_MASK_WORDS]; @@ -350,7 +350,6 @@ unsigned volatile int global_irq_lock; atomic_t global_irq_count; atomic_t global_bh_count; -atomic_t global_bh_lock; static void show(char * str) { @@ -361,12 +360,12 @@ static void show(char * str) printk("\n%s, CPU %d:\n", str, cpu); printk("irq: %d [%d %d]\n", atomic_read(&global_irq_count), - ppc_local_irq_count[0], - ppc_local_irq_count[1]); + local_irq_count[0], + local_irq_count[1]); printk("bh: %d [%d %d]\n", atomic_read(&global_bh_count), - ppc_local_bh_count[0], - ppc_local_bh_count[1]); + local_bh_count[0], + local_bh_count[1]); stack = (unsigned long *) &str; for (i = 40; i ; i--) { unsigned long x = *++stack; @@ -401,7 +400,7 @@ static inline void wait_on_irq(int cpu) * already executing in one.. */ if (!atomic_read(&global_irq_count)) { - if (ppc_local_bh_count[cpu] + if (local_bh_count[cpu] || !atomic_read(&global_bh_count)) break; } @@ -423,7 +422,7 @@ static inline void wait_on_irq(int cpu) continue; if (global_irq_lock) continue; - if (!ppc_local_bh_count[cpu] + if (!local_bh_count[cpu] && atomic_read(&global_bh_count)) continue; if (!test_and_set_bit(0,&global_irq_lock)) @@ -514,7 +513,7 @@ void __global_cli(void) if (flags & (1 << 15)) { int cpu = smp_processor_id(); __cli(); - if (!ppc_local_irq_count[cpu]) + if (!local_irq_count[cpu]) get_irqlock(cpu); } } @@ -523,7 +522,7 @@ void __global_sti(void) { int cpu = smp_processor_id(); - if (!ppc_local_irq_count[cpu]) + if (!local_irq_count[cpu]) release_irqlock(cpu); __sti(); } @@ -547,7 +546,7 @@ unsigned long __global_save_flags(void) retval = 2 + local_enabled; /* check for global flags if we're not in an interrupt */ - if (!ppc_local_irq_count[smp_processor_id()]) { + if (!local_irq_count[smp_processor_id()]) { if (local_enabled) retval = 1; if (global_irq_holder == (unsigned char) smp_processor_id()) diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index fde7112c7722..a543169e7afd 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -271,6 +271,38 @@ _GLOBAL(clear_page) bdnz 1b blr +/* + * Copy a whole page. We use the dcbz instruction on the destination + * to reduce memory traffic (it eliminates the unnecessary reads of + * the destination into cache). This requires that the destination + * is cacheable. + */ +_GLOBAL(copy_page) + li r0,4096/CACHE_LINE_SIZE + mtctr r0 + addi r3,r3,-4 + addi r4,r4,-4 + li r5,4 +1: dcbz r5,r3 + lwz r6,4(r4) + lwz r7,8(r4) + lwz r8,12(r4) + lwzu r9,16(r4) + stw r6,4(r3) + stw r7,8(r3) + stw r8,12(r3) + stwu r9,16(r3) + lwz r6,4(r4) + lwz r7,8(r4) + lwz r8,12(r4) + lwzu r9,16(r4) + stw r6,4(r3) + stw r7,8(r3) + stw r8,12(r3) + stwu r9,16(r3) + bdnz 1b + blr + /* * Atomic [test&set] exchange * diff --git a/arch/ppc/kernel/mk_defs.c b/arch/ppc/kernel/mk_defs.c index 34682bd2a89d..3efc7bbf9fcc 100644 --- a/arch/ppc/kernel/mk_defs.c +++ b/arch/ppc/kernel/mk_defs.c @@ -48,9 +48,11 @@ main(void) DEFINE(NEED_RESCHED, offsetof(struct task_struct, need_resched)); DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr)); - DEFINE(THREAD_VRF, offsetof(struct thread_struct, vrf)); - DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr)); +#ifdef CONFIG_ALTIVEC + DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0])); DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave)); + DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr)); +#endif /* CONFIG_ALTIVEC */ /* Interrupt register frame */ DEFINE(TASK_UNION_SIZE, sizeof(union task_union)); DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c index d4dbe05e5cdf..301a82ba8f4c 100644 --- a/arch/ppc/kernel/open_pic.c +++ b/arch/ppc/kernel/open_pic.c @@ -279,7 +279,7 @@ void __init openpic_init(int main_pic) /* Initialize the spurious interrupt */ if ( ppc_md.progress ) ppc_md.progress("openpic spurious",0x3bd); openpic_set_spurious(OPENPIC_VEC_SPURIOUS); - if ( !(_machine && (_MACH_gemini|_MACH_Pmac)) ) + if ( !(_machine & (_MACH_gemini|_MACH_Pmac)) ) { if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT, "82c59 cascade", NULL)) @@ -490,7 +490,7 @@ void openpic_enable_irq(u_int irq) /* make sure mask gets to controller before we return to user */ do { mb(); /* sync is probably useless here */ - } while(openpic_readfield(&OpenPIC->Source[irq].Vector_Priority, + } while(openpic_readfield(&ISU[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK)); } @@ -501,7 +501,7 @@ void openpic_disable_irq(u_int irq) /* make sure mask gets to controller before we return to user */ do { mb(); /* sync is probably useless here */ - } while(!openpic_readfield(&OpenPIC->Source[irq].Vector_Priority, + } while(!openpic_readfield(&ISU[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK)); } diff --git a/arch/ppc/kernel/pmac_pic.c b/arch/ppc/kernel/pmac_pic.c index d2d5e6b25d59..d13875c9fde3 100644 --- a/arch/ppc/kernel/pmac_pic.c +++ b/arch/ppc/kernel/pmac_pic.c @@ -31,8 +31,6 @@ static int max_irqs; static int max_real_irqs; static int has_openpic = 0; -#define MAXCOUNT 10000000 - #define GATWICK_IRQ_POOL_SIZE 10 static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; @@ -187,25 +185,6 @@ pmac_get_irq(struct pt_regs *regs) smp_message_recv(); return -2; /* ignore, already handled */ } - - { - unsigned int loops = MAXCOUNT; - while (test_bit(0, &global_irq_lock)) { - if (smp_processor_id() == global_irq_holder) { - printk("uh oh, interrupt while we hold global irq lock!\n"); -#ifdef CONFIG_XMON - xmon(0); -#endif - break; - } - if (loops-- == 0) { - printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder); -#ifdef CONFIG_XMON - xmon(0); -#endif - } - } - } #endif /* __SMP__ */ /* Yeah, I know, this could be a separate do_IRQ function */ diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c index e1c1815acf2f..5fef07e89e8f 100644 --- a/arch/ppc/kernel/pmac_setup.c +++ b/arch/ppc/kernel/pmac_setup.c @@ -60,6 +60,7 @@ #include #include #include +#include #include "time.h" #include "local_irq.h" @@ -440,6 +441,7 @@ kdev_t __init find_ide_boot(void) { char *p; int n; + kdev_t __init pmac_find_ide_boot(char *bootdevice, int n); if (bootdevice == NULL) return 0; @@ -695,9 +697,12 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, #ifdef CONFIG_BOOTX_TEXT extern void drawchar(char c); extern void drawstring(const char *c); +extern boot_infos_t *disp_bi; void pmac_progress(char *s, unsigned short hex) { + if (disp_bi == 0) + return; drawstring(s); drawchar('\n'); } diff --git a/arch/ppc/kernel/pmac_time.c b/arch/ppc/kernel/pmac_time.c index 1c935a625655..3b7dd283f9d5 100644 --- a/arch/ppc/kernel/pmac_time.c +++ b/arch/ppc/kernel/pmac_time.c @@ -71,8 +71,8 @@ unsigned long pmac_get_rtc_time(void) if (req.reply_len != 7) printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", req.reply_len); - return (unsigned long)(req.reply[1] << 24) + (req.reply[2] << 16) - + (req.reply[3] << 8) + (unsigned long)req.reply[4] - RTC_OFFSET; + return (req.reply[3] << 24) + (req.reply[4] << 16) + + (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET; #endif /* CONFIG_ADB_CUDA */ #ifdef CONFIG_ADB_PMU case SYS_CTRLER_PMU: diff --git a/arch/ppc/kernel/ppc_asm.h b/arch/ppc/kernel/ppc_asm.h index 2b999ab36878..d9093c9e1990 100644 --- a/arch/ppc/kernel/ppc_asm.h +++ b/arch/ppc/kernel/ppc_asm.h @@ -44,6 +44,28 @@ #define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base) #define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base) +/* + * Once a version of gas that understands the AltiVec instructions + * is freely available, we can do this the normal way... - paulus + */ +#define LVX(r,a,b) .long (31<<26)+((r)<<21)+((a)<<16)+((b)<<11)+(103<<1) +#define STVX(r,a,b) .long (31<<26)+((r)<<21)+((a)<<16)+((b)<<11)+(231<<1) +#define MFVSCR(r) .long (4<<26)+((r)<<21)+(1540<<1) +#define MTVSCR(r) .long (4<<26)+((r)<<11)+(802<<1) + +#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); STVX(n,b,base) +#define SAVE_2VR(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base) +#define SAVE_4VR(n,b,base) SAVE_2VR(n,b,base); SAVE_2VR(n+2,b,base) +#define SAVE_8VR(n,b,base) SAVE_4VR(n,b,base); SAVE_4VR(n+4,b,base) +#define SAVE_16VR(n,b,base) SAVE_8VR(n,b,base); SAVE_8VR(n+8,b,base) +#define SAVE_32VR(n,b,base) SAVE_16VR(n,b,base); SAVE_16VR(n+16,b,base) +#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); LVX(n,b,base) +#define REST_2VR(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base) +#define REST_4VR(n,b,base) REST_2VR(n,b,base); REST_2VR(n+2,b,base) +#define REST_8VR(n,b,base) REST_4VR(n,b,base); REST_4VR(n+4,b,base) +#define REST_16VR(n,b,base) REST_8VR(n,b,base); REST_8VR(n+8,b,base) +#define REST_32VR(n,b,base) REST_16VR(n,b,base); REST_16VR(n+16,b,base) + #define SYNC \ sync; \ isync diff --git a/arch/ppc/kernel/ppc_asm.tmpl b/arch/ppc/kernel/ppc_asm.tmpl index 94a5bd74c489..c35192bb4fe6 100644 --- a/arch/ppc/kernel/ppc_asm.tmpl +++ b/arch/ppc/kernel/ppc_asm.tmpl @@ -80,3 +80,36 @@ #define fr29 29 #define fr30 30 #define fr31 31 + +#define vr0 0 +#define vr1 1 +#define vr2 2 +#define vr3 3 +#define vr4 4 +#define vr5 5 +#define vr6 6 +#define vr7 7 +#define vr8 8 +#define vr9 9 +#define vr10 10 +#define vr11 11 +#define vr12 12 +#define vr13 13 +#define vr14 14 +#define vr15 15 +#define vr16 16 +#define vr17 17 +#define vr18 18 +#define vr19 19 +#define vr20 20 +#define vr21 21 +#define vr22 22 +#define vr23 23 +#define vr24 24 +#define vr25 25 +#define vr26 26 +#define vr27 27 +#define vr28 28 +#define vr29 29 +#define vr30 30 +#define vr31 31 diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 9a5444a51fac..d81f0056a8e8 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -72,8 +72,8 @@ EXPORT_SYMBOL(do_lost_interrupts); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(disable_irq_nosync); -EXPORT_SYMBOL(ppc_local_irq_count); -EXPORT_SYMBOL(ppc_local_bh_count); +EXPORT_SYMBOL(local_irq_count); +EXPORT_SYMBOL(local_bh_count); #ifdef __SMP__ EXPORT_SYMBOL(kernel_flag); #endif /* __SMP__ */ @@ -272,4 +272,3 @@ EXPORT_SYMBOL(ppc_irq_dispatch_handler); EXPORT_SYMBOL(decrementer_count); EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(console_drivers); -EXPORT_SYMBOL(do_bottom_half); diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index ed98ba6f0486..3b30f50efa22 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -140,15 +140,31 @@ int check_stack(struct task_struct *tsk) } #endif /* defined(CHECK_STACK) */ +#ifdef CONFIG_ALTIVEC int -dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) +dump_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs) { - if (regs->msr & MSR_FP) - giveup_fpu(current); - memcpy(fpregs, ¤t->thread.fpr[0], sizeof(*fpregs)); + if (regs->msr & MSR_VEC) + giveup_altivec(current); + memcpy(vrregs, ¤t->thread.vr[0], sizeof(*vrregs)); return 1; } +void +enable_kernel_altivec(void) +{ +#ifdef __SMP__ + if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) + giveup_altivec(current); + else + giveup_altivec(NULL): /* just enable AltiVec for kernel - force */ +#else + giveup_altivec(last_task_used_altivec); +#endif /* __SMP __ */ + printk("MSR_VEC in enable_altivec_kernel\n"); +} +#endif /* CONFIG_ALTIVEC */ + void enable_kernel_fp(void) { @@ -162,6 +178,15 @@ enable_kernel_fp(void) #endif /* __SMP__ */ } +int +dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) +{ + if (regs->msr & MSR_FP) + giveup_fpu(current); + memcpy(fpregs, ¤t->thread.fpr[0], sizeof(*fpregs)); + return 1; +} + void _switch_to(struct task_struct *prev, struct task_struct *new, struct task_struct **last) @@ -194,6 +219,7 @@ _switch_to(struct task_struct *prev, struct task_struct *new, */ if ( prev->thread.regs && (prev->thread.regs->msr & MSR_FP) ) giveup_fpu(prev); +#ifdef CONFIG_ALTIVEC /* * If the previous thread 1) has some altivec regs it wants saved * (has bits in vrsave set) and 2) used altivec in the last quantum @@ -206,6 +232,7 @@ _switch_to(struct task_struct *prev, struct task_struct *new, if ( (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)) && prev->thread.vrsave ) giveup_altivec(prev); +#endif /* CONFIG_ALTIVEC */ prev->last_processor = prev->processor; current_set[smp_processor_id()] = new; #endif /* __SMP__ */ @@ -337,13 +364,18 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, p->thread.fpscr = current->thread.fpscr; childregs->msr &= ~MSR_FP; +#ifdef CONFIG_ALTIVEC + /* + * copy altiVec info - assume lazy altiVec switch + * - kumar + */ if (regs->msr & MSR_VEC) giveup_altivec(current); - if ( p->thread.vrsave ) - memcpy(&p->thread.vrf, ¤t->thread.vrf, sizeof(p->thread.vrf)); + + memcpy(&p->thread.vr, ¤t->thread.vr, sizeof(p->thread.vr)); p->thread.vscr = current->thread.vscr; - p->thread.vrsave = current->thread.vrsave; childregs->msr &= ~MSR_VEC; +#endif /* CONFIG_ALTIVEC */ #ifdef __SMP__ p->last_processor = NO_PROC_ID; @@ -463,6 +495,10 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, goto out; if (regs->msr & MSR_FP) giveup_fpu(current); +#ifdef CONFIG_ALTIVEC + if (regs->msr & MSR_VEC) + giveup_altivec(current); +#endif /* CONFIG_ALTIVEC */ error = do_execve(filename, (char **) a1, (char **) a2, regs); putname(filename); out: diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c index a52bdd804a98..b86e2a153e66 100644 --- a/arch/ppc/kernel/prom.c +++ b/arch/ppc/kernel/prom.c @@ -802,42 +802,19 @@ setup_disp_fake_bi(ihandle dp) { unsigned int len; int width = 640, height = 480, depth = 8, pitch; - unsigned address; + unsigned address; boot_infos_t* bi; unsigned long offset = reloc_offset(); - prom_print(RELOC("Initing fake screen\n")); + prom_print(RELOC("Initializing fake screen\n")); - len = 0; + call_prom(RELOC("getprop"), 4, 1, dp, RELOC("width"), &width, sizeof(width)); + call_prom(RELOC("getprop"), 4, 1, dp, RELOC("height"), &height, sizeof(height)); call_prom(RELOC("getprop"), 4, 1, dp, RELOC("depth"), &len, sizeof(len)); - if (len == 0) - prom_print(RELOC("Warning: assuming display depth = 8\n")); - else - depth = len; - width = len = 0; - call_prom(RELOC("getprop"), 4, 1, dp, RELOC("width"), &len, sizeof(len)); - width = len; - if (width == 0) { - prom_print(RELOC("Failed to get width\n")); - return; - } - height = len = 0; - call_prom(RELOC("getprop"), 4, 1, dp, RELOC("height"), &len, sizeof(len)); - height = len; - if (height == 0) { - prom_print(RELOC("Failed to get height\n")); - return; - } - pitch = len = 0; + pitch = width * ((depth + 7) / 8); call_prom(RELOC("getprop"), 4, 1, dp, RELOC("linebytes"), &len, sizeof(len)); - pitch = len; - if (pitch == 0) { - prom_print(RELOC("Failed to get pitch\n")); - return; - } - address = len = 0; + address = 0; call_prom(RELOC("getprop"), 4, 1, dp, RELOC("address"), &len, sizeof(len)); - address = len; if (address == 0) { prom_print(RELOC("Failed to get address\n")); return; @@ -846,22 +823,22 @@ setup_disp_fake_bi(ihandle dp) /* kludge for valkyrie */ if (strcmp(dp->name, "valkyrie") == 0) address += 0x1000; - } #endif - RELOC(disp_bi) = &fake_bi; - bi = PTRRELOC((&fake_bi)); - RELOC(g_loc_X) = 0; - RELOC(g_loc_Y) = 0; - RELOC(g_max_loc_X) = width / 8; - RELOC(g_max_loc_Y) = height / 16; - bi->logicalDisplayBase = (unsigned char *)address; - bi->dispDeviceBase = (unsigned char *)address; - bi->dispDeviceRowBytes = pitch; - bi->dispDeviceDepth = depth; - bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0; - bi->dispDeviceRect[2] = width; - bi->dispDeviceRect[3] = height; + RELOC(disp_bi) = &fake_bi; + bi = PTRRELOC((&fake_bi)); + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y) = 0; + RELOC(g_max_loc_X) = width / 8; + RELOC(g_max_loc_Y) = height / 16; + bi->logicalDisplayBase = (unsigned char *)address; + bi->dispDeviceBase = (unsigned char *)address; + bi->dispDeviceRowBytes = pitch; + bi->dispDeviceDepth = depth; + bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0; + bi->dispDeviceRect[2] = width; + bi->dispDeviceRect[3] = height; + RELOC(disp_bi) = 0; } #endif diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 19ce0a25e185..7502ad08e82a 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -221,7 +221,7 @@ int get_cpuinfo(char *buffer) if ( i ) len += sprintf(len+buffer,"\n"); len += sprintf(len+buffer,"processor\t: %lu\n",i); - len += sprintf(len+buffer,"cpu\t\t: "); + len += sprintf(len+buffer,"cpu\t\t: "); pvr = GET_PVR; @@ -656,7 +656,6 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_BOOTX_TEXT map_bootx_text(); - prom_print("identify machine\n"); #endif #ifdef CONFIG_XMON diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index 386764ddd058..83dff9246181 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -53,7 +53,6 @@ unsigned int prof_counter[NR_CPUS]; cycles_t cacheflush_time; /* all cpu mappings are 1-1 -- Cort */ -int cpu_number_map[NR_CPUS] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,}; volatile unsigned long cpu_callin_map[NR_CPUS] = {0,}; int start_secondary(void *); diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c index e1a3fdcbbe14..e31b34cc9a4f 100644 --- a/arch/ppc/kernel/syscalls.c +++ b/arch/ppc/kernel/syscalls.c @@ -252,14 +252,13 @@ asmlinkage int sys_pause(void) asmlinkage int sys_uname(struct old_utsname * name) { - int err; - - if (!name) - return -EFAULT; + int err = -EFAULT; + down_read(&uts_sem); - err = copy_to_user(name, &system_utsname, sizeof (*name)); - up(&uts_sem); - return err ? -EFAULT : 0; + if (name && !copy_to_user(name, &system_utsname, sizeof (*name))) + err = 0; + up_read(&uts_sem); + return err; } asmlinkage int sys_olduname(struct oldold_utsname * name) @@ -282,8 +281,8 @@ asmlinkage int sys_olduname(struct oldold_utsname * name) error -= __put_user(0,name->version+__OLD_UTS_LEN); error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); error = __put_user(0,name->machine+__OLD_UTS_LEN); - error = error ? -EFAULT : 0; - up(&uts_sem); + up_read(&uts_sem); + error = error ? -EFAULT : 0; return error; } diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 5cc34c5a5a51..ac7f47602d77 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -118,11 +118,11 @@ MachineCheckException(struct pt_regs *regs) default: printk("Unknown values in msr\n"); } + show_regs(regs); + print_backtrace((unsigned long *)regs->gpr[1]); #if defined(CONFIG_XMON) || defined(CONFIG_KGDB) debugger(regs); #endif - show_regs(regs); - print_backtrace((unsigned long *)regs->gpr[1]); panic("machine check"); } _exception(SIGSEGV, regs); @@ -142,44 +142,6 @@ SMIException(struct pt_regs *regs) panic("System Management Interrupt"); } -#if defined(CONFIG_ALTIVEC) -void -AltiVecUnavailable(struct pt_regs *regs) -{ - /* - * This should be changed so we don't take a trap if coming - * back when last_task_used_altivec == current. We should also - * allow the kernel to use the altivec regs on UP to store tasks - * regs during switch - * -- Cort - */ - if ( regs->msr & MSR_VEC ) - { - show_regs(regs); - panic("AltiVec trap with Altivec enabled!\n"); - } - - if ( !user_mode(regs) ) - { - show_regs(regs); - panic("Kernel Used Altivec with MSR_VEC off!\n"); - } - - if ( last_task_used_altivec != current ) - { - if ( last_task_used_altivec ) - giveup_altivec(current); - load_up_altivec(current); - /* on SMP we always save/restore on switch */ -#ifndef __SMP__ - last_task_used_altivec = current; -#endif - } - /* enable altivec for the task on return */ - regs->msr |= MSR_VEC; -} -#endif /* CONFIG_ALTIVEC */ - void UnknownException(struct pt_regs *regs) { diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S index 4ab90f8b748c..1c4f1f78edf7 100644 --- a/arch/ppc/lib/string.S +++ b/arch/ppc/lib/string.S @@ -12,6 +12,11 @@ #include #include +CACHELINE_BYTES = 32 +LG_CACHELINE_BYTES = 5 +CACHELINE_MASK = 0x1f +CACHELINE_WORDS = 8 + .globl strcpy strcpy: addi r5,r3,-1 @@ -70,6 +75,55 @@ strlen: subf r3,r3,r4 blr +/* + * Use dcbz on the complete cache lines in the destination + * to set them to zero. This requires that the destination + * area is cacheable. -- paulus + */ + .globl cacheable_memzero +cacheable_memzero: + mr r5,r4 + li r4,0 + addi r6,r3,-4 + cmplwi 0,r5,4 + blt 7f + stwu r4,4(r6) + beqlr + andi. r0,r6,3 + add r5,r0,r5 + subf r6,r0,r6 + clrlwi r7,r6,32-LG_CACHELINE_BYTES + add r8,r7,r5 + srwi r9,r8,LG_CACHELINE_BYTES + addic. r9,r9,-1 /* total number of complete cachelines */ + ble 2f + xori r0,r7,CACHELINE_MASK & ~3 + srwi. r0,r0,2 + beq 3f + mtctr r0 +4: stwu r4,4(r6) + bdnz 4b +3: mtctr r9 + li r7,4 +10: dcbz r7,r6 + addi r6,r6,CACHELINE_BYTES + bdnz 10b + clrlwi r5,r8,32-LG_CACHELINE_BYTES + addi r5,r5,4 +2: srwi r0,r5,2 + mtctr r0 + bdz 6f +1: stwu r4,4(r6) + bdnz 1b +6: andi. r5,r5,3 +7: cmpwi 0,r5,0 + beqlr + mtctr r5 + addi r6,r6,3 +8: stbu r4,1(r6) + bdnz 8b + blr + .globl memset memset: rlwimi r4,r4,8,16,23 @@ -82,7 +136,7 @@ memset: andi. r0,r6,3 add r5,r0,r5 subf r6,r0,r6 - rlwinm r0,r5,32-2,2,31 + srwi r0,r5,2 mtctr r0 bdz 6f 1: stwu r4,4(r6) @@ -103,6 +157,87 @@ bcopy: mr r4,r6 b memcpy +/* + * This version uses dcbz on the complete cache lines in the + * destination area to reduce memory traffic. This requires that + * the destination area is cacheable. + * We only use this version if the source and dest don't overlap. + * -- paulus. + */ + .global cacheable_memcpy +cacheable_memcpy: + add r7,r3,r5 /* test if the src & dst overlap */ + add r8,r4,r5 + cmplw 0,r4,r7 + cmplw 1,r3,r8 + crand 0,0,4 /* cr0.lt &= cr1.lt */ + blt memcpy /* if regions overlap */ + + addi r4,r4,-4 + addi r6,r3,-4 + neg r0,r3 + andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */ + beq 58f + + cmplw 0,r5,r0 /* is this more than total to do? */ + blt 63f /* if not much to do */ + andi. r8,r0,3 /* get it word-aligned first */ + subf r5,r0,r5 + mtctr r8 + beq+ 61f +70: lbz r9,4(r4) /* do some bytes */ + stb r9,4(r6) + addi r4,r4,1 + addi r6,r6,1 + bdnz 70b +61: srwi. r0,r0,2 + mtctr r0 + beq 58f +72: lwzu r9,4(r4) /* do some words */ + stwu r9,4(r6) + bdnz 72b + +58: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */ + clrlwi r5,r5,32-LG_CACHELINE_BYTES + li r11,4 + mtctr r0 + beq 63f +53: dcbz r11,r6 + lwz r7,4(r4) + lwz r8,8(r4) + lwz r9,12(r4) + lwzu r10,16(r4) + stw r7,4(r6) + stw r8,8(r6) + stw r9,12(r6) + stwu r10,16(r6) + lwz r7,4(r4) + lwz r8,8(r4) + lwz r9,12(r4) + lwzu r10,16(r4) + stw r7,4(r6) + stw r8,8(r6) + stw r9,12(r6) + stwu r10,16(r6) + bdnz 53b + +63: srwi. r0,r5,2 + mtctr r0 + beq 64f +30: lwzu r0,4(r4) + stwu r0,4(r6) + bdnz 30b + +64: andi. r0,r5,3 + mtctr r0 + beq+ 65f +40: lbz r0,4(r4) + stb r0,4(r6) + addi r4,r4,1 + addi r6,r6,1 + bdnz 40b +65: blr + .globl memmove memmove: cmplw 0,r3,r4 @@ -111,7 +246,7 @@ memmove: .globl memcpy memcpy: - rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ + srwi. r7,r5,3 addi r6,r3,-4 addi r4,r4,-4 beq 2f /* if less than 8 bytes to do */ @@ -218,106 +353,167 @@ memchr: .globl __copy_tofrom_user __copy_tofrom_user: - srwi. r7,r5,3 - addi r6,r3,-4 addi r4,r4,-4 - li r3,0 /* success return value */ - beq 2f /* if less than 8 bytes to do */ - andi. r0,r6,3 /* get dest word aligned */ - mtctr r7 - bne 5f -1: lwz r7,4(r4) -11: lwzu r8,8(r4) -12: stw r7,4(r6) -13: stwu r8,8(r6) - bdnz 1b - andi. r5,r5,7 -2: cmplwi 0,r5,4 - blt 3f -14: lwzu r0,4(r4) - addi r5,r5,-4 -15: stwu r0,4(r6) -3: cmpwi 0,r5,0 /* do 1 byte at a time for the remainder */ - beqlr - mtctr r5 - addi r4,r4,3 - addi r6,r6,3 -4: lbzu r0,1(r4) -16: stbu r0,1(r6) - bdnz 4b - blr -5: subfic r0,r0,4 /* copy bytes until we have the */ - mtctr r0 /* destination 4-byte aligned */ - subf r5,r0,r5 -6: lbz r7,4(r4) + addi r6,r3,-4 + neg r0,r3 + andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */ + beq 58f + + cmplw 0,r5,r0 /* is this more than total to do? */ + blt 63f /* if not much to do */ + andi. r8,r0,3 /* get it word-aligned first */ + mtctr r8 + beq+ 61f +70: lbz r9,4(r4) /* do some bytes */ +71: stb r9,4(r6) addi r4,r4,1 -17: stb r7,4(r6) addi r6,r6,1 - bdnz 6b - srwi. r7,r5,3 - beq 2b - mtctr r7 - b 1b -/* we come here on a fault in the 8-byte-at-a-time loop */ -88: subi r4,r4,8 /* compensate for the lwzu */ -98: mfctr r0 - rlwimi r5,r0,3,0,28 /* use the byte-at-a-time loop to */ - b 3b /* copy up to the byte at fault */ -/* here on a write fault in the single-word copy */ -96: subi r4,r4,4 - b 3b -/* here on a read fault in the initial single-byte copy */ -90: mfctr r3 - add r3,r3,r5 - b 70f -/* here on a read fault in the final single-byte copy */ -99: mfctr r3 - subi r6,r6,3 -/* clear out the rest of the destination: r3 bytes starting at 4(r6) */ -70: li r0,0 - mr. r5,r3 - beq 76f -71: andi. r4,r6,3 - beq 72f -77: stb r0,4(r6) + bdnz 70b +61: subf r5,r0,r5 + srwi. r0,r0,2 + mtctr r0 + beq 58f +72: lwzu r9,4(r4) /* do some words */ +73: stwu r9,4(r6) + bdnz 72b + +58: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */ + clrlwi r5,r5,32-LG_CACHELINE_BYTES + li r11,4 + mtctr r0 + beq 63f +53: dcbz r11,r6 +10: lwz r7,4(r4) +11: lwz r8,8(r4) +12: lwz r9,12(r4) +13: lwzu r10,16(r4) +14: stw r7,4(r6) +15: stw r8,8(r6) +16: stw r9,12(r6) +17: stwu r10,16(r6) +20: lwz r7,4(r4) +21: lwz r8,8(r4) +22: lwz r9,12(r4) +23: lwzu r10,16(r4) +24: stw r7,4(r6) +25: stw r8,8(r6) +26: stw r9,12(r6) +27: stwu r10,16(r6) + bdnz 53b + +63: srwi. r0,r5,2 + mtctr r0 + beq 64f +30: lwzu r0,4(r4) +31: stwu r0,4(r6) + bdnz 30b + +64: andi. r0,r5,3 + mtctr r0 + beq+ 65f +40: lbz r0,4(r4) +41: stb r0,4(r6) + addi r4,r4,1 addi r6,r6,1 - addic. r5,r5,-1 - bne 71b -72: srwi. r7,r5,2 - beq 73f - mtctr r7 -74: stwu r0,4(r6) - bdnz 74b -73: andi. r5,r5,3 - beq 76f - mtctr r5 - addi r6,r6,3 -75: stbu r0,1(r6) - bdnz 75b -76: blr -/* here on a write fault in the initial single-byte copy */ -80: mfctr r3 - add r3,r3,r5 - blr -/* here on a write fault in the final single-byte copy */ -81: mfctr r3 + bdnz 40b +65: li r3,0 blr +/* read fault, initial single-byte copy */ +100: li r4,0 + b 90f +/* write fault, initial single-byte copy */ +101: li r4,1 +90: subf r5,r8,r5 + li r3,0 + b 99f +/* read fault, initial word copy */ +102: li r4,0 + b 91f +/* write fault, initial word copy */ +103: li r4,1 +91: li r3,2 + b 99f +/* read fault in 2nd half of cacheline loop */ +106: addi r5,r5,-16 +/* read fault in 1st half of cacheline loop */ +104: li r4,0 + b 92f +/* write fault in 2nd half of cacheline loop */ +107: addi r5,r5,-16 +/* fault on dcbz (effectively a write fault) */ +/* or write fault in 1st half of cacheline loop */ +105: li r4,1 +92: li r3,LG_CACHELINE_BYTES + b 99f +/* read fault in final word loop */ +108: li r4,0 + b 93f +/* write fault in final word loop */ +109: li r4,1 +93: andi. r5,r5,3 + li r3,2 + b 99f +/* read fault in final byte loop */ +110: li r4,0 + b 94f +/* write fault in final byte loop */ +111: li r4,1 +94: li r5,0 + li r3,0 +/* + * At this stage the number of bytes not copied is + * r5 + (ctr << r3), and r4 is 0 for read or 1 for write. + */ +99: mfctr r0 + slw r3,r0,r3 + add r3,r3,r5 + cmpwi 0,r4,0 + bne 120f +/* for read fault, clear out the destination: r3 bytes starting at 4(r6) */ + srwi. r0,r3,2 + li r9,0 + mtctr r0 + beq 113f +112: stwu r9,4(r6) + bdnz 112b +113: andi. r0,r3,3 + mtctr r0 + beq 120f +114: stb r9,4(r6) + addi r6,r6,1 + bdnz 114b +120: blr + .section __ex_table,"a" .align 2 - .long 1b,98b - .long 11b,98b - .long 12b,88b - .long 13b,88b - .long 14b,3b - .long 15b,96b - .long 4b,99b - .long 16b,81b - .long 6b,90b - .long 17b,80b - .long 77b,76b - .long 74b,76b - .long 75b,76b + .long 70b,100b + .long 71b,101b + .long 72b,102b + .long 73b,103b + .long 53b,105b + .long 10b,104b + .long 11b,104b + .long 12b,104b + .long 13b,104b + .long 14b,105b + .long 15b,105b + .long 16b,105b + .long 17b,105b + .long 20b,106b + .long 21b,106b + .long 22b,106b + .long 23b,106b + .long 24b,107b + .long 25b,107b + .long 26b,107b + .long 27b,107b + .long 30b,108b + .long 31b,109b + .long 40b,110b + .long 41b,111b + .long 112b,120b + .long 114b,120b .text .globl __clear_user @@ -334,7 +530,6 @@ __clear_user: andi. r0,r6,3 add r4,r0,r4 subf r6,r0,r6 - /*rlwinm r0,r4,32-2,2,31*/ srwi r0,r4,2 mtctr r0 bdz 6f diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 216527e34344..25d728fdda3d 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -1107,7 +1107,7 @@ unsigned long __init find_available_memory(void) */ void __init paging_init(void) { - unsigned int zones_size[MAX_NR_ZONES], i; + unsigned long zones_size[MAX_NR_ZONES], i; /* * Grab some memory for bad_page and bad_pagetable to use. @@ -1197,7 +1197,7 @@ unsigned long __init *pmac_find_end_of_memory(void) unsigned long a, total; /* max amount of RAM we allow -- Cort */ -#define RAM_LIMIT (64<<20) +#define RAM_LIMIT (768<<20) memory_node = find_devices("memory"); if (memory_node == NULL) { diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c index f25060c942db..8e924699fa83 100644 --- a/arch/ppc/xmon/start.c +++ b/arch/ppc/xmon/start.c @@ -115,42 +115,41 @@ extern void pmu_poll(void); int xmon_write(void *handle, void *ptr, int nb) { - char *p = ptr; - int i, c, ct; + char *p = ptr; + int i, c, ct; #ifdef CONFIG_BOOTX_TEXT - if (use_screen) { - /* write it on the screen */ - for (i = 0; i < nb; ++i) - drawchar(*p++); - return nb; - } + if (use_screen) { + /* write it on the screen */ + for (i = 0; i < nb; ++i) + drawchar(*p++); + return nb; + } #endif - if (!scc_initialized) - xmon_init_scc(); - for (i = 0; i < nb; ++i) { - ct = 0; - while ((*sccc & TXRDY) == 0) + if (!scc_initialized) + xmon_init_scc(); + ct = 0; + for (i = 0; i < nb; ++i) { + while ((*sccc & TXRDY) == 0) { #ifdef CONFIG_ADB - if (sys_ctrler == SYS_CTRLER_PMU) - pmu_poll(); -#else - ; + if (sys_ctrler == SYS_CTRLER_PMU) + pmu_poll(); #endif /* CONFIG_ADB */ - c = p[i]; - if (c == '\n' && !ct) { - c = '\r'; - ct = 1; - --i; - } else { - if (console) - printk("%c", c); - ct = 0; + } + c = p[i]; + if (c == '\n' && !ct) { + c = '\r'; + ct = 1; + --i; + } else { + if (console) + printk("%c", c); + ct = 0; + } + buf_access(); + *sccd = c; } - buf_access(); - *sccd = c; - } - return i; + return i; } int xmon_wants_key; @@ -285,7 +284,7 @@ xmon_init_scc() { int i, x; - if (macio_node != 0) { + if (via_modem && macio_node != 0) { unsigned int t0; feature_set(macio_node, FEATURE_Modem_power); diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 336ae208ff71..f746f824b5a5 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -1,4 +1,4 @@ -/* $Id: ioport.c,v 1.31 2000/02/06 22:55:32 zaitcev Exp $ +/* $Id: ioport.c,v 1.32 2000/02/12 03:04:48 zaitcev Exp $ * ioport.c: Simple io mapping allocator. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -562,7 +562,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t n, void *p, dma_addr_t ba) { int x; for (x = 0; x < n; x += PAGE_SIZE) { - (*_sparc_unmapioaddr)(p + n); + (*_sparc_unmapioaddr)((unsigned long)p + n); } } diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index b504e2412306..335eba2083c5 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -1,4 +1,4 @@ -/* $Id: pcic.c,v 1.12 2000/01/22 07:35:25 zaitcev Exp $ +/* $Id: pcic.c,v 1.13 2000/02/12 03:05:37 zaitcev Exp $ * pcic.c: Sparc/PCI controller support * * Copyright (C) 1998 V. Roganov and G. Raiko @@ -784,6 +784,7 @@ void __init pci_time_init(void) static __inline__ unsigned long do_gettimeoffset(void) { + struct tasklet_struct *t; unsigned long offset = 0; /* @@ -794,7 +795,8 @@ static __inline__ unsigned long do_gettimeoffset(void) readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW; count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100); - if(test_bit(TIMER_BH, &bh_active)) + t = &bh_task_vec[TIMER_BH]; + if (test_bit(TASKLET_STATE_SCHED, &t->state)) offset = 1000000; return offset + count; } diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 715bdb864f53..ae5d5e3714cc 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.187 2000/02/08 07:46:01 davem Exp $ +/* $Id: sun4c.c,v 1.188 2000/02/12 03:07:35 zaitcev Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -591,7 +591,7 @@ static unsigned long sun4c_translate_dvma(unsigned long busa) return (pte << PAGE_SHIFT) + PAGE_OFFSET; } -static unsigned long sun4c_unmap_dma_area(unsigned long busa, int len) +static void sun4c_unmap_dma_area(unsigned long busa, int len) { /* Fortunately for us, bus_addr == uncached_virt in sun4c. */ /* XXX Implement this */ diff --git a/arch/sparc/mm/swift.S b/arch/sparc/mm/swift.S index e9fe43293568..914f3071de21 100644 --- a/arch/sparc/mm/swift.S +++ b/arch/sparc/mm/swift.S @@ -1,4 +1,4 @@ -/* $Id: swift.S,v 1.3 1999/11/14 06:13:56 zaitcev Exp $ +/* $Id: swift.S,v 1.4 2000/02/12 03:08:47 zaitcev Exp $ * swift.S: MicroSparc-II mmu/cache operations. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -41,10 +41,10 @@ swift_flush_chunk: swift_flush_page_to_ram: sethi %hi(0x2000), %o0 1: subcc %o0, 0x10, %o0 - sta %g0, [%o0] ASI_M_TXTC_TAG + add %o0, %o0, %o1 sta %g0, [%o0] ASI_M_DATAC_TAG bne 1b - nop + sta %g0, [%o1] ASI_M_TXTC_TAG retl nop #else diff --git a/drivers/acorn/char/keyb_ps2.c b/drivers/acorn/char/keyb_ps2.c index d915a42918d0..306feb2e90fb 100644 --- a/drivers/acorn/char/keyb_ps2.c +++ b/drivers/acorn/char/keyb_ps2.c @@ -28,6 +28,7 @@ #include #include +extern struct tasklet_struct keyboard_tasklet; extern void kbd_reset_kdown(void); int kbd_read_mask; @@ -318,7 +319,7 @@ static void ps2kbd_rx(int irq, void *dev_id, struct pt_regs *regs) while (inb(IOMD_KCTRL) & (1 << 5)) handle_rawcode(inb(IOMD_KARTRX)); - mark_bh(KEYBOARD_BH); + tasklet_schedule(&keyboard_tasklet); } static void ps2kbd_tx(int irq, void *dev_id, struct pt_regs *regs) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index dd742cbc4a1d..9eab534aac0f 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -40,10 +40,10 @@ * it passes the underlying device's block number instead of the * offset. This makes it change for a given block when the file is * moved/restored/copied and also doesn't work over NFS. - * AV, Feb 11, 2000: for files we pass the page index now. It should fix the - * problem above. Since the granularity is PAGE_CACHE_SIZE now it seems to - * be correct way. OTOH, taking the thing from x86 to Alpha may become - * interesting, so we might want to rethink it. + * AV, Feb 12, 2000: we pass the logical block number now. It fixes the + * problem above. Encryption modules that used to rely on the old scheme + * should just call ->i_mapping->bmap() to calculate the physical block + * number. */ #include @@ -164,7 +164,8 @@ static void figure_loop_size(struct loop_device *lo) loop_sizes[lo->lo_number] = size; } -static int lo_send(struct loop_device *lo, char *data, int len, loff_t pos) +static int lo_send(struct loop_device *lo, char *data, int len, loff_t pos, + int blksize) { struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */ struct address_space *mapping = lo->lo_dentry->d_inode->i_mapping; @@ -177,6 +178,7 @@ static int lo_send(struct loop_device *lo, char *data, int len, loff_t pos) index = pos >> PAGE_CACHE_SHIFT; offset = pos & (PAGE_CACHE_SIZE - 1); while (len > 0) { + int IV = index * (PAGE_CACHE_SIZE/blksize) + offset/blksize; size = PAGE_CACHE_SIZE - offset; if (size > len) size = len; @@ -187,7 +189,7 @@ static int lo_send(struct loop_device *lo, char *data, int len, loff_t pos) if (aops->prepare_write(page, offset, offset+size)) goto unlock; kaddr = (char*)page_address(page); - if ((lo->transfer)(lo, WRITE, kaddr+offset, data, size, index)) + if ((lo->transfer)(lo, WRITE, kaddr+offset, data, size, IV)) goto write_fail; if (aops->commit_write(file, page, offset, offset+size)) goto unlock; @@ -217,6 +219,7 @@ fail: struct lo_read_data { struct loop_device *lo; char *data; + int blksize; }; static int lo_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size) @@ -225,12 +228,13 @@ static int lo_read_actor(read_descriptor_t * desc, struct page *page, unsigned l unsigned long count = desc->count; struct lo_read_data *p = (struct lo_read_data*)desc->buf; struct loop_device *lo = p->lo; + int IV = page->index * (PAGE_CACHE_SIZE/p->blksize) + offset/p->blksize; if (size > count) size = count; kaddr = (char*)kmap(page); - if ((lo->transfer)(lo,READ,kaddr+offset,p->data,size,page->index)) { + if ((lo->transfer)(lo,READ,kaddr+offset,p->data,size,IV)) { size = 0; printk(KERN_ERR "loop: transfer error block %ld\n",page->index); desc->error = -EINVAL; @@ -243,7 +247,8 @@ static int lo_read_actor(read_descriptor_t * desc, struct page *page, unsigned l return size; } -static int lo_receive(struct loop_device *lo, char *data, int len, loff_t pos) +static int lo_receive(struct loop_device *lo, char *data, int len, loff_t pos, + int blksize) { struct file *file = lo->lo_backing_file; struct lo_read_data cookie; @@ -251,6 +256,7 @@ static int lo_receive(struct loop_device *lo, char *data, int len, loff_t pos) cookie.lo = lo; cookie.data = data; + cookie.blksize = blksize; desc.written = 0; desc.count = len; desc.buf = (char*)&cookie; @@ -287,8 +293,6 @@ repeat: dest_addr = current_request->buffer; len = current_request->current_nr_sectors << 9; - if (lo->lo_flags & LO_FLAGS_DO_BMAP) - goto file_backed; blksize = BLOCK_SIZE; if (blksize_size[MAJOR(lo->lo_device)]) { @@ -296,6 +300,10 @@ repeat: if (!blksize) blksize = BLOCK_SIZE; } + + if (lo->lo_flags & LO_FLAGS_DO_BMAP) + goto file_backed; + if (blksize < 512) { block = current_request->sector * (512/blksize); offset = 0; @@ -357,10 +365,10 @@ file_backed: pos = ((loff_t)current_request->sector << 9) + lo->lo_offset; spin_unlock_irq(&io_request_lock); if (current_request->cmd == WRITE) { - if (lo_send(lo, dest_addr, len, pos)) + if (lo_send(lo, dest_addr, len, pos, blksize)) goto error_out_lock; } else { - if (lo_receive(lo, dest_addr, len, pos)) + if (lo_receive(lo, dest_addr, len, pos, blksize)) goto error_out_lock; } done: @@ -416,6 +424,7 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg) a file structure */ lo->lo_backing_file = NULL; } else if (S_ISREG(inode->i_mode)) { + struct address_space_operations *aops; /* Backed by a regular file - we need to hold onto a file structure for this file. Friggin' NFS can't live without it on write and for reading we use do_generic_file_read(), @@ -444,16 +453,23 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg) lo->lo_backing_file = NULL; } } + aops = lo->lo_dentry->d_inode->i_mapping->a_ops; + /* + * If we can't read - sorry. If we only can't write - well, + * it's going to be read-only. + */ + if (!aops->readpage) + error = -EINVAL; + else if (!aops->prepare_write || !aops->commit_write) + lo->lo_flags |= LO_FLAGS_READ_ONLY; } if (error) goto out_putf; - if (IS_RDONLY (inode) || is_read_only(lo->lo_device)) { + if (IS_RDONLY (inode) || is_read_only(lo->lo_device)) lo->lo_flags |= LO_FLAGS_READ_ONLY; - set_device_ro(dev, 1); - } else { - set_device_ro(dev, 0); - } + + set_device_ro(dev, (lo->lo_flags & LO_FLAGS_READ_ONLY)!=0); lo->lo_dentry = dget(file->f_dentry); lo->transfer = NULL; diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index e49144c1a219..c61a6e6a9477 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -38,7 +38,7 @@ /* select machine configuration */ #if defined(CONFIG_ATARI) #define MACH ATARI -#elif defined(__i386__) /* and others?? */ +#elif defined(__i386__) || defined(__arm__) /* and others?? */ #define MACH PC #else #error Cannot build nvram driver for this machine configuration. diff --git a/drivers/macintosh/mac_keyb.c b/drivers/macintosh/mac_keyb.c index 2ba5baac21cf..04999bb4cefd 100644 --- a/drivers/macintosh/mac_keyb.c +++ b/drivers/macintosh/mac_keyb.c @@ -391,16 +391,17 @@ input_keycode(int keycode, int repeat) case 0x39: handle_scancode(0x39, 1); handle_scancode(0x39, 0); - mark_bh(KEYBOARD_BH); + tasklet_schedule(&keyboard_tasklet); return; case 0x47: /*case 0xc7:*/ - mark_bh(KEYBOARD_BH); + tasklet_schedule(&keyboard_tasklet); break; } } handle_scancode(keycode, !up_flag); + tasklet_schedule(&keyboard_tasklet); } static void diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c index 2555d5383680..94ec60e1c4bf 100644 --- a/drivers/macintosh/macserial.c +++ b/drivers/macintosh/macserial.c @@ -2796,7 +2796,6 @@ static struct console sercons = { void __init serial_console_init(void) { register_console(&sercons); - return kmem_start; } #endif /* ifdef CONFIG_SERIAL_CONSOLE */ diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 781084dbf6d8..b5be783380ae 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -403,8 +403,6 @@ struct vortex_private { struct sk_buff* rx_skbuff[RX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE]; struct net_device *next_module; - void *priv_addr; - dma_addr_t ring_dma; unsigned int cur_rx, cur_tx; /* The next free ring entry */ unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ struct net_device_stats stats; @@ -769,13 +767,11 @@ static struct net_device *vortex_probe1(struct pci_dev *pdev, vp->pci_devfn = pdev == NULL ? 0 : pdev->devfn; vp->pdev = pdev; - vp->priv_addr = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE - + sizeof(struct boom_tx_desc) * TX_RING_SIZE - + 15, &vp->ring_dma); - /* Make sure rings are 16 byte aligned. */ - vp->rx_ring = (void *)(((long)vp->priv_addr + 15) & ~15); + /* Makes sure rings are at least 16 byte aligned. */ + vp->rx_ring = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE + + sizeof(struct boom_tx_desc) * TX_RING_SIZE, + &vp->rx_ring_dma); vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE); - vp->rx_ring_dma = (vp->ring_dma + 15) & ~15; vp->tx_ring_dma = vp->rx_ring_dma + sizeof(struct boom_rx_desc) * RX_RING_SIZE; /* The lower four bits are the media type. */ @@ -2062,7 +2058,7 @@ static void __exit vortex_cleanup_module (void) kfree(root_vortex_dev); pci_free_consistent(vp->pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE + sizeof(struct boom_tx_desc) * TX_RING_SIZE - + 15, vp->priv_addr, vp->ring_dma); + + 15, vp->rx_ring, vp->rx_ring_dma); kfree(vp); root_vortex_dev = next_dev; } diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c new file mode 100644 index 000000000000..d6a7f66df97a --- /dev/null +++ b/drivers/net/8139too.c @@ -0,0 +1,1812 @@ +/* + + 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. + + Copyright 2000 Jeff Garzik + Originally: Written 1997-1999 by Donald Becker. + + This software may be used and distributed according to the terms + of the GNU Public License, incorporated herein by reference. + + Contributors: + + Donald Becker - he wrote the original driver, kudos to him! + (but please don't e-mail him for support, this isn't his driver) + + Tigran Aivazian - bug fixes, skbuff free cleanup + + Martin Mares - suggestions for PCI cleanup + + David S. Miller - PCI DMA and softnet updates + +----------------------------------------------------------------------------- + + Theory of Operation + +I. Board Compatibility + +This device driver is designed for the RealTek RTL8139 series, the RealTek +Fast Ethernet controllers for PCI and CardBus. This chip is used on many +low-end boards, sometimes with its markings changed. + + +II. Board-specific settings + +PCI bus devices are configured by the system at boot time, so no jumpers +need to be set on the board. The system BIOS will assign the +PCI INTA signal to a (preferably otherwise unused) system IRQ line. + +III. Driver operation + +IIIa. Rx Ring buffers + +The receive unit uses a single linear ring buffer rather than the more +common (and more efficient) descriptor-based architecture. Incoming frames +are sequentially stored into the Rx region, and the host copies them into +skbuffs. + +Comment: While it is theoretically possible to process many frames in place, +any delay in Rx processing would cause us to drop frames. More importantly, +the Linux protocol stack is not designed to operate in this manner. + +IIIb. Tx operation + +The RTL8139 uses a fixed set of four Tx descriptors in register space. +In a stunningly bad design choice, Tx frames must be 32 bit aligned. Linux +aligns the IP header on word boundaries, and 14 byte ethernet header means +that almost all frames will need to be copied to an alignment buffer. + +IVb. References + +http://www.realtek.com.tw/cn/cn.html +http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html + +IVc. Errata + +1) The RTL-8139 has a serious problem with motherboards which do +posted MMIO writes to PCI space. This driver works around the +problem by having an MMIO register write be immediately followed by +an MMIO register read. + +2) The RTL-8129 is only supported in Donald Becker's rtl8139 driver. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define RTL8139_VERSION "0.9.0" +#define RTL8139_MODULE_NAME "8139too" +#define RTL8139_DRIVER_NAME RTL8139_MODULE_NAME " Fast Ethernet driver " RTL8139_VERSION +#define PFX RTL8139_MODULE_NAME ": " + +#undef RTL8139_DEBUG /* define to 1 to enable copious debugging info */ + +#ifdef RTL8139_DEBUG +/* note: prints function name for you */ +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +#define RTL8139_NDEBUG 0 /* define to 1 to disable lightweight runtime checks */ +#if RTL8139_NDEBUG +#define assert(expr) +#else +#define assert(expr) \ + if(!(expr)) { \ + printk( "Assertion failed! %s,%s,%s,line=%d\n", \ + #expr,__FILE__,__FUNCTION__,__LINE__); \ + } +#endif + +#define arraysize(x) (sizeof(x)/sizeof(*(x))) + + +#ifndef PCI_GET_DRIVER_DATA + #define PCI_GET_DRIVER_DATA(pdev) ((pdev)->driver_data) + #define PCI_SET_DRIVER_DATA(pdev,data) (((pdev)->driver_data) = (data)) +#endif /* PCI_GET_DRIVER_DATA */ + + +/* A few user-configurable values. */ +/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ +static int max_interrupt_work = 20; + +/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). + The RTL chips use a 64 element hash table based on the Ethernet CRC. */ +static int multicast_filter_limit = 32; + +/* Size of the in-memory receive ring. */ +#define RX_BUF_LEN_IDX 2 /* 0==8K, 1==16K, 2==32K, 3==64K */ +#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX) +/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ +#define TX_BUF_SIZE 1536 + +/* PCI Tuning Parameters + Threshold is bytes transferred to chip before transmission starts. */ +#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ + +/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024. */ +#define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */ +#define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */ +#define TX_DMA_BURST 4 /* Calculate as 16<if_port value. */ + unsigned int media2:4; /* Secondary monitored media port. */ + unsigned int medialock:1; /* Don't sense media type. */ + unsigned int mediasense:1; /* Media sensing in progress. */ +}; + +MODULE_AUTHOR ("Jeff Garzik "); +MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); +MODULE_PARM (multicast_filter_limit, "i"); +MODULE_PARM (max_interrupt_work, "i"); +MODULE_PARM (debug, "i"); + +static int read_eeprom (void *ioaddr, int location, int addr_len); +static int rtl8139_open (struct net_device *dev); +static int mdio_read (struct net_device *dev, int phy_id, int location); +static void mdio_write (struct net_device *dev, int phy_id, int location, + int val); +static void rtl8139_timer (unsigned long data); +static void rtl8139_tx_timeout (struct net_device *dev); +static void rtl8139_init_ring (struct net_device *dev); +static int rtl8139_start_xmit (struct sk_buff *skb, + struct net_device *dev); +static void rtl8139_interrupt (int irq, void *dev_instance, + struct pt_regs *regs); +static int rtl8139_close (struct net_device *dev); +static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); +static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); +static inline u32 ether_crc (int length, unsigned char *data); +static void rtl8139_set_rx_mode (struct net_device *dev); + +/* read after write, to avoid rtl8139 bug w/ posted MMIO writes */ +#define RTL_W8(reg, val8) do { writeb (val8, ioaddr + reg); readb (ioaddr + reg); } while (0) +#define RTL_W16(reg, val16) do { writew (val16, ioaddr + reg); readw (ioaddr + reg); } while (0) +#define RTL_W32(reg, val32) do { writel (val32, ioaddr + reg); readl (ioaddr + reg); } while (0) +#define RTL_R8(reg) readb (ioaddr + reg) +#define RTL_R16(reg) readw (ioaddr + reg) +#define RTL_R32(reg) readl (ioaddr + reg) + + +static const char * __devinit rtl8139_name_from_chip (chip_t chip) +{ + int i; + + for (i = 0; i < arraysize (chip_info); i++) + if (chip == chip_info[i].chip) + return chip_info[i].name; + + return "unknown"; +} + + +static int __devinit rtl8139_init_pci (struct pci_dev *pdev, void **ioaddr_out) +{ + void *ioaddr = NULL; + u8 tmp8; + int rc; + u32 pio_start, pio_end, pio_flags; + u32 mmio_start, mmio_end, mmio_flags; + + DPRINTK ("ENTER\n"); + + assert (pdev != NULL); + assert (ioaddr_out != NULL); + + *ioaddr_out = NULL; + + pio_start = pci_resource_start (pdev, 0); + pio_end = pci_resource_end (pdev, 0); + pio_flags = pci_resource_flags (pdev, 0); + + mmio_start = pci_resource_start (pdev, 1); + mmio_end = pci_resource_end (pdev, 1); + mmio_flags = pci_resource_flags (pdev, 1); + + /* make sure PCI base addr 0 is PIO */ + if (pio_start == 0 || pio_end <= pio_start || + (!(pio_flags & IORESOURCE_IO))) { + printk (KERN_ERR PFX "no PIO resource, aborting\n"); + return -ENODEV; + } + + /* make sure PCI base addr 1 is MMIO */ + if (mmio_start == 0 || mmio_end <= mmio_start || + (!(mmio_flags & IORESOURCE_MEM))) { + printk (KERN_ERR PFX "no MMIO resource, aborting\n"); + return -ENODEV; + } + + /* make sure our PIO region in PCI space is available */ + if (!request_region (pio_start, RTL_IO_SIZE, RTL8139_MODULE_NAME)) { + printk (KERN_ERR PFX "no I/O resource available, aborting\n"); + return -EBUSY; + } + + /* make sure our MMIO region in PCI space is available */ + if (!request_mem_region (mmio_start, RTL_IO_SIZE, RTL8139_MODULE_NAME)) { + release_region (pio_start, RTL_IO_SIZE); + printk (KERN_ERR PFX "no mem resource available, aborting\n"); + return -EBUSY; + } + + /* enable device (incl. PCI PM wakeup), and bus-mastering */ + pci_enable_device (pdev); + pci_set_master (pdev); + + /* ioremap MMIO region */ + ioaddr = ioremap (mmio_start, RTL_IO_SIZE); + if (ioaddr == NULL) { + printk (KERN_ERR PFX "cannot remap MMIO, aborting\n"); + rc = -EIO; + goto err_out; + } + + /* Bring the chip out of low-power mode. */ + RTL_W8 (Config1, 0x00); + + /* make sure chip thinks PIO and MMIO are enabled */ + tmp8 = RTL_R8 (Config1); + if ((tmp8 & Cfg1_PIO) == 0) { + printk (KERN_ERR PFX "PIO not enabled, Cfg1=%02X, aborting\n", tmp8); + rc = -EIO; + goto err_out; + } + if ((tmp8 & Cfg1_MMIO) == 0) { + printk (KERN_ERR PFX "MMIO not enabled, Cfg1=%02X, aborting\n", tmp8); + rc = -EIO; + goto err_out; + } + + /* sanity checks -- ensure PIO and MMIO registers agree */ + assert (inb (pio_start+Config0) == RTL_R8 (Config0)); + assert (inb (pio_start+Config1) == RTL_R8 (Config1)); + assert (inb (pio_start+TxConfig) == RTL_R8 (TxConfig)); + assert (inb (pio_start+RxConfig) == RTL_R8 (RxConfig)); + + DPRINTK ("EXIT, returning 0\n"); + *ioaddr_out = ioaddr; + return 0; + +err_out: + if (ioaddr) + iounmap (ioaddr); + release_region (pio_start, RTL_IO_SIZE); + release_mem_region (mmio_start, RTL_IO_SIZE); + DPRINTK ("EXIT, returning %d\n", rc); + return rc; +} + + +static int __devinit rtl8139_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct net_device *dev; + struct rtl8139_private *tp; + int i, addr_len, option = -1; + void *ioaddr = NULL; + + DPRINTK ("ENTER\n"); + + assert (pdev != NULL); + assert (ent != NULL); + + i = rtl8139_init_pci (pdev, &ioaddr); + if (i < 0) { + DPRINTK ("EXIT, returning %d\n", i); + return i; + } + + assert (ioaddr != NULL); + + /* dev zeroed in init_etherdev */ + dev = init_etherdev (NULL, sizeof (*tp) + PRIV_ALIGN); + if (dev == NULL) { + iounmap (ioaddr); + printk (KERN_ERR PFX "unable to alloc new ethernet\n"); + DPRINTK ("EXIT, returning -ENOMEM\n"); + return -ENOMEM; + } + + addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; + for (i = 0; i < 3; i++) + ((u16 *) (dev->dev_addr))[i] = + le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); + + /* The Rtl8139-specific entries in the device structure. */ + dev->open = rtl8139_open; + dev->hard_start_xmit = rtl8139_start_xmit; + dev->stop = rtl8139_close; + dev->get_stats = rtl8139_get_stats; + dev->set_multicast_list = rtl8139_set_rx_mode; + dev->do_ioctl = mii_ioctl; + dev->tx_timeout = rtl8139_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; + + dev->irq = pdev->irq; + dev->base_addr = pci_resource_start (pdev, 1); + + dev->priv = tp = (void *) + (((long)dev->priv + PRIV_ALIGN) & ~PRIV_ALIGN); + + printk (KERN_INFO "%s: %s at 0x%lx, IRQ %d, " + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", + dev->name, rtl8139_name_from_chip(ent->driver_data), + dev->base_addr, dev->irq, + dev->dev_addr[0], dev->dev_addr[1], + dev->dev_addr[2], dev->dev_addr[3], + dev->dev_addr[4], dev->dev_addr[5]); + + /* tp zeroed in init_etherdev */ + tp->drv_flags = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | RTL8139_CAPS; + tp->pci_dev = pdev; + tp->chip = ent->driver_data; + tp->mmio_addr = ioaddr; + tp->lock = SPIN_LOCK_UNLOCKED; + + PCI_SET_DRIVER_DATA (pdev, dev); + + tp->phys[0] = 32; + + /* Put the chip into low-power mode. */ + RTL_W8 (Cfg9346, 0xC0); + RTL_W8 (Config1, 0x03); /* Enable PM & PCI VPD */ + RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ + + /* The lower four bits are the media type. */ + if (option > 0) { + tp->full_duplex = (option & 0x200) ? 1 : 0; + tp->default_port = option & 15; + if (tp->default_port) + tp->medialock = 1; + } + + if (tp->full_duplex) { + printk (KERN_INFO + "%s: Media type forced to Full Duplex.\n", + dev->name); + mdio_write (dev, tp->phys[0], 4, 0x141); + tp->duplex_lock = 1; + } + + DPRINTK ("EXIT - returning 0\n"); + return 0; +} + + +static void __devexit rtl8139_remove_one (struct pci_dev *pdev) +{ + struct net_device *dev = PCI_GET_DRIVER_DATA (pdev); + struct rtl8139_private *np; + + DPRINTK ("ENTER\n"); + + assert (dev != NULL); + + np = (struct rtl8139_private *) (dev->priv); + assert (np != NULL); + + unregister_netdev (dev); + + iounmap (np->mmio_addr); + release_region (pci_resource_start (pdev, 0), RTL_IO_SIZE); + release_mem_region (pci_resource_start (pdev, 1), RTL_IO_SIZE); + +#ifndef RTL8139_NDEBUG + /* poison memory before freeing */ + memset (dev, 0xC0, + sizeof (struct net_device) + + sizeof (struct rtl8139_private) + + PRIV_ALIGN); +#endif + + kfree (dev); + + DPRINTK ("EXIT\n"); +} + + +/* Serial EEPROM section. */ + +/* EEPROM_Ctrl bits. */ +#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ +#define EE_CS 0x08 /* EEPROM chip select. */ +#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ +#define EE_WRITE_0 0x00 +#define EE_WRITE_1 0x02 +#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ +#define EE_ENB (0x80 | EE_CS) + +/* Delay between EEPROM clock transitions. + No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. + */ + +#define eeprom_delay() readl(ee_addr) + +/* The EEPROM commands include the alway-set leading bit. */ +#define EE_WRITE_CMD (5) +#define EE_READ_CMD (6) +#define EE_ERASE_CMD (7) + +static int __devinit read_eeprom (void *ioaddr, int location, int addr_len) +{ + int i; + unsigned retval = 0; + void *ee_addr = ioaddr + Cfg9346; + int read_cmd = location | (EE_READ_CMD << addr_len); + + DPRINTK ("ENTER\n"); + + writeb (EE_ENB & ~EE_CS, ee_addr); + writeb (EE_ENB, ee_addr); + eeprom_delay (); + + /* Shift the read command bits out. */ + for (i = 4 + addr_len; i >= 0; i--) { + int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + writeb (EE_ENB | dataval, ee_addr); + eeprom_delay (); + writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); + eeprom_delay (); + } + writeb (EE_ENB, ee_addr); + eeprom_delay (); + + for (i = 16; i > 0; i--) { + writeb (EE_ENB | EE_SHIFT_CLK, ee_addr); + eeprom_delay (); + retval = + (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 : + 0); + writeb (EE_ENB, ee_addr); + eeprom_delay (); + } + + /* Terminate the EEPROM access. */ + writeb (~EE_CS, ee_addr); + eeprom_delay (); + + DPRINTK ("EXIT - returning %d\n", retval); + return retval; +} + +/* MII serial management: mostly bogus for now. */ +/* Read and write the MII management registers using software-generated + serial MDIO protocol. + The maximum data clock rate is 2.5 Mhz. The minimum timing is usually + met by back-to-back PCI I/O cycles, but we insert a delay to avoid + "overclocking" issues. */ +#define MDIO_DIR 0x80 +#define MDIO_DATA_OUT 0x04 +#define MDIO_DATA_IN 0x02 +#define MDIO_CLK 0x01 +#define MDIO_WRITE0 (MDIO_DIR) +#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) + +#define mdio_delay() readb(mdio_addr) + + +static char mii_2_8139_map[8] = { + BasicModeCtrl, + BasicModeStatus, + 0, + 0, + NWayAdvert, + NWayLPAR, + NWayExpansion, + 0 +}; + + +/* Syncronize the MII management interface by shifting 32 one bits out. */ +static void mdio_sync (void *mdio_addr) +{ + int i; + + DPRINTK ("ENTER\n"); + + for (i = 32; i >= 0; i--) { + writeb (MDIO_WRITE1, mdio_addr); + mdio_delay (); + writeb (MDIO_WRITE1 | MDIO_CLK, mdio_addr); + mdio_delay (); + } + + DPRINTK ("EXIT\n"); +} + + +static int mdio_read (struct net_device *dev, int phy_id, int location) +{ + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + void *mdio_addr = tp->mmio_addr + Config4; + int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; + int retval = 0; + int i; + + DPRINTK ("ENTER\n"); + + if (phy_id > 31) { /* Really a 8139. Use internal registers. */ + DPRINTK ("EXIT after directly using 8139 internal regs\n"); + return location < 8 && mii_2_8139_map[location] ? + readw (tp->mmio_addr + mii_2_8139_map[location]) : 0; + } + mdio_sync (mdio_addr); + /* Shift the read command bits out. */ + for (i = 15; i >= 0; i--) { + int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; + + writeb (MDIO_DIR | dataval, mdio_addr); + mdio_delay (); + writeb (MDIO_DIR | dataval | MDIO_CLK, mdio_addr); + mdio_delay (); + } + + /* Read the two transition, 16 data, and wire-idle bits. */ + for (i = 19; i > 0; i--) { + writeb (0, mdio_addr); + mdio_delay (); + retval = + (retval << 1) | ((readb (mdio_addr) & MDIO_DATA_IN) ? 1 + : 0); + writeb (MDIO_CLK, mdio_addr); + mdio_delay (); + } + + DPRINTK ("EXIT, returning %d\n", (retval >> 1) & 0xffff); + return (retval >> 1) & 0xffff; +} + + +static void mdio_write (struct net_device *dev, int phy_id, int location, + int value) +{ + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + void *mdio_addr = tp->mmio_addr + Config4; + int mii_cmd = + (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; + int i; + + DPRINTK ("ENTER\n"); + + if (phy_id > 31) { /* Really a 8139. Use internal registers. */ + if (location < 8 && mii_2_8139_map[location]) { + writew (value, + tp->mmio_addr + mii_2_8139_map[location]); + readw (tp->mmio_addr + mii_2_8139_map[location]); + } + DPRINTK ("EXIT after directly using 8139 internal regs\n"); + return; + } + mdio_sync (mdio_addr); + + /* Shift the command bits out. */ + for (i = 31; i >= 0; i--) { + int dataval = + (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; + writeb (dataval, mdio_addr); + mdio_delay (); + writeb (dataval | MDIO_CLK, mdio_addr); + mdio_delay (); + } + + /* Clear out extra bits. */ + for (i = 2; i > 0; i--) { + writeb (0, mdio_addr); + mdio_delay (); + writeb (MDIO_CLK, mdio_addr); + mdio_delay (); + } + + DPRINTK ("EXIT\n"); +} + + +static int rtl8139_open (struct net_device *dev) +{ + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + void *ioaddr = tp->mmio_addr; + int i; + + DPRINTK ("ENTER\n"); + + MOD_INC_USE_COUNT; + + /* Soft reset the chip. */ + RTL_W8 (ChipCmd, CmdReset); + + if (request_irq (dev->irq, &rtl8139_interrupt, SA_SHIRQ, dev->name, dev)) { + DPRINTK ("EXIT, returning -EBUSY\n"); + MOD_DEC_USE_COUNT; + return -EBUSY; + } + + tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_SIZE * NUM_TX_DESC, + &tp->tx_bufs_dma); + tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_LEN + 16, + &tp->rx_ring_dma); + if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { + free_irq(dev->irq, dev); + + if (tp->tx_bufs) + pci_free_consistent(tp->pci_dev, TX_BUF_SIZE * NUM_TX_DESC, + tp->tx_bufs, tp->tx_bufs_dma); + if (tp->rx_ring) + pci_free_consistent(tp->pci_dev, RX_BUF_LEN + 16, + tp->rx_ring, tp->rx_ring_dma); + + DPRINTK ("EXIT, returning -ENOMEM\n"); + MOD_DEC_USE_COUNT; + return -ENOMEM; + + } + + rtl8139_init_ring (dev); + tp->full_duplex = tp->duplex_lock; + tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; + tp->rx_config = + (RX_FIFO_THRESH << 13) | + (RX_BUF_LEN_IDX << 11) | + (RX_DMA_BURST << 8); + + /* Check that the chip has finished the reset. */ + for (i = 1000; i > 0; i--) + if ((RTL_R8 (ChipCmd) & CmdReset) == 0) + break; + + RTL_W32 (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); + RTL_W32 (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); + + /* Must enable Tx/Rx before setting transfer thresholds! */ + RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); + RTL_W32 (RxConfig, tp->rx_config); + RTL_W32 (TxConfig, (TX_DMA_BURST << 8) | 0x00000000); + + /* Reset N-Way to chipset defaults */ + RTL_W16 (BasicModeCtrl, (1<<15)|(1<<12)|(1<<9)); + for (i = 1000; i > 0; i--) + if ((RTL_R8 (BasicModeCtrl) & (1<<15)) == 0) + break; + + /* Set N-Way to sane defaults */ + RTL_W16 (FIFOTMS, 0x0000); + RTL_W16 (NWayAdvert, (1<<13)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|0x1); + RTL_W16 (BasicModeCtrl, (1<<13)|(1<<12)|(1<<9)|(1<<8)); + + RTL_W8 (Cfg9346, 0xC0); + RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20); + RTL_W8 (Cfg9346, 0x00); + + RTL_W32 (RxBuf, tp->rx_ring_dma); + + /* Start the chip's Tx and Rx process. */ + RTL_W32 (RxMissed, 0); + rtl8139_set_rx_mode (dev); + + RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); + + /* Enable all known interrupts by setting the interrupt mask. */ + RTL_W16 (IntrMask, + PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver + | TxErr | TxOK | RxErr | RxOK); + + DPRINTK ("%s: rtl8139_open() ioaddr %#lx IRQ %d" + " GP Pins %2.2x %s-duplex.\n", + dev->name, pci_resource_start (tp->pci_dev, 1), + dev->irq, RTL_R8 (GPPinData), + tp->full_duplex ? "full" : "half"); + + /* Set the timer to switch to check for link beat and perhaps switch + to an alternate media type. */ + init_timer (&tp->timer); + tp->timer.expires = jiffies + 3 * HZ; + tp->timer.data = (unsigned long) dev; + tp->timer.function = &rtl8139_timer; + add_timer (&tp->timer); + + netif_start_queue (dev); + + DPRINTK ("EXIT, returning 0\n"); + return 0; +} + +/* Start the hardware at open or resume. */ +static void rtl8139_hw_start (struct net_device *dev) +{ + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + void *ioaddr = tp->mmio_addr; + int i; + + DPRINTK ("ENTER\n"); + + /* Soft reset the chip. */ + RTL_W8 (ChipCmd, CmdReset); + /* Check that the chip has finished the reset. */ + for (i = 1000; i > 0; i--) + if ((RTL_R8 (ChipCmd) & CmdReset) == 0) + break; + + /* Restore our idea of the MAC address. */ + RTL_W32 (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); + RTL_W32 (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); + + /* Hmmm, do these belong here? */ + RTL_W8 (Cfg9346, 0x00); + tp->cur_rx = 0; + + /* Must enable Tx/Rx before setting transfer thresholds! */ + RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); + RTL_W32 (RxConfig, tp->rx_config); + /* Check this value: the documentation contradicts ifself. Is the + IFG correct with bit 28:27 zero, or with |0x03000000 ? */ + RTL_W32 (TxConfig, (TX_DMA_BURST << 8) | 0x00000000); + + /* Reset N-Way to chipset defaults */ + RTL_W16 (BasicModeCtrl, (1<<15)|(1<<12)|(1<<9)); + for (i = 1000; i > 0; i--) + if ((RTL_R8 (BasicModeCtrl) & (1<<15)) == 0) + break; + + /* Set N-Way to sane defaults */ + RTL_W16 (FIFOTMS, 0x0000); + RTL_W16 (NWayAdvert, (1<<13)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|0x1); + RTL_W16 (BasicModeCtrl, (1<<13)|(1<<12)|(1<<9)|(1<<8)); + + /* check_duplex() here. */ + RTL_W8 (Cfg9346, 0xC0); + RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20); + RTL_W8 (Cfg9346, 0x00); + + RTL_W32 (RxBuf, tp->rx_ring_dma); + /* Start the chip's Tx and Rx process. */ + RTL_W32 (RxMissed, 0); + rtl8139_set_rx_mode (dev); + RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); + /* Enable all known interrupts by setting the interrupt mask. */ + RTL_W16 (IntrMask, + PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver + | TxErr | TxOK | RxErr | RxOK); + + netif_start_queue (dev); + + DPRINTK ("EXIT\n"); +} + + +#ifndef RTL_TUNE_TWISTER +static inline void rtl8139_tune_twister (struct net_device *dev, + struct rtl8139_private *tp) {} +#else +static void rtl8139_tune_twister (struct net_device *dev, + struct rtl8139_private *tp) +{ + int linkcase; + + DPRINTK ("ENTER\n"); + + /* This is a complicated state machine to configure the "twister" for + impedance/echos based on the cable length. + All of this is magic and undocumented. + */ + switch (tp->twistie) { + case 1: + if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { + /* We have link beat, let us tune the twister. */ + RTL_W16 (CSCR, CSCR_LinkDownOffCmd); + tp->twistie = 2; /* Change to state 2. */ + next_tick = HZ / 10; + } else { + /* Just put in some reasonable defaults for when beat returns. */ + RTL_W16 (CSCR, CSCR_LinkDownCmd); + RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */ + RTL_W32 (PARA78, PARA78_default); + RTL_W32 (PARA7c, PARA7c_default); + tp->twistie = 0; /* Bail from future actions. */ + } + break; + case 2: + /* Read how long it took to hear the echo. */ + linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; + if (linkcase == 0x7000) + tp->twist_row = 3; + else if (linkcase == 0x3000) + tp->twist_row = 2; + else if (linkcase == 0x1000) + tp->twist_row = 1; + else + tp->twist_row = 0; + tp->twist_col = 0; + tp->twistie = 3; /* Change to state 2. */ + next_tick = HZ / 10; + break; + case 3: + /* Put out four tuning parameters, one per 100msec. */ + if (tp->twist_col == 0) + RTL_W16 (FIFOTMS, 0); + RTL_W32 (PARA7c, param[(int) tp->twist_row] + [(int) tp->twist_col]); + next_tick = HZ / 10; + if (++tp->twist_col >= 4) { + /* For short cables we are done. + For long cables (row == 3) check for mistune. */ + tp->twistie = + (tp->twist_row == 3) ? 4 : 0; + } + break; + case 4: + /* Special case for long cables: check for mistune. */ + if ((RTL_R16 (CSCR) & + CSCR_LinkStatusBits) == 0x7000) { + tp->twistie = 0; + break; + } else { + RTL_W32 (PARA7c, 0xfb38de03); + tp->twistie = 5; + next_tick = HZ / 10; + } + break; + case 5: + /* Retune for shorter cable (column 2). */ + RTL_W32 (FIFOTMS, 0x20); + RTL_W32 (PARA78, PARA78_default); + RTL_W32 (PARA7c, PARA7c_default); + RTL_W32 (FIFOTMS, 0x00); + tp->twist_row = 2; + tp->twist_col = 0; + tp->twistie = 3; + next_tick = HZ / 10; + break; + + default: + /* do nothing */ + break; + } + + DPRINTK ("EXIT\n"); +} +#endif /* RTL_TUNE_TWISTER */ + + +static void rtl8139_timer (unsigned long data) +{ + struct net_device *dev = (struct net_device *) data; + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + void *ioaddr = tp->mmio_addr; + int next_tick = 60 * HZ; + int mii_reg5 = mdio_read (dev, tp->phys[0], 5); + + DPRINTK ("ENTER\n"); + + if (!tp->duplex_lock && mii_reg5 != 0xffff) { + int duplex = (mii_reg5 & 0x0100) + || (mii_reg5 & 0x01C0) == 0x0040; + if (tp->full_duplex != duplex) { + tp->full_duplex = duplex; + printk (KERN_INFO + "%s: Setting %s-duplex based on MII #%d link" + " partner ability of %4.4x.\n", dev->name, + tp->full_duplex ? "full" : "half", + tp->phys[0], mii_reg5); + RTL_W8 (Cfg9346, 0xC0); + RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20); + RTL_W8 (Cfg9346, 0x00); + } + } + + rtl8139_tune_twister (dev, tp); + + DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", + dev->name, RTL_R16 (NWayLPAR)); + DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x" + " RxStatus %4.4x.\n", dev->name, + RTL_R16 (IntrMask), + RTL_R16 (IntrStatus), + RTL_R32 (RxEarlyStatus)); + DPRINTK ("%s: Chip config %2.2x %2.2x.\n", + dev->name, RTL_R8 (Config0), + RTL_R8 (Config1)); + + tp->timer.expires = jiffies + next_tick; + add_timer (&tp->timer); + + DPRINTK ("EXIT\n"); +} + + +static void rtl8139_tx_timeout (struct net_device *dev) +{ + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + void *ioaddr = tp->mmio_addr; + int mii_reg, i; + + DPRINTK ("ENTER\n"); + + netif_stop_queue (dev); + + DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x " + "media %2.2x.\n", dev->name, + readb (ioaddr + ChipCmd), + readw (ioaddr + IntrStatus), + readb (ioaddr + GPPinData)); + + /* Disable interrupts by clearing the interrupt mask. */ + RTL_W16 (IntrMask, 0x0000); + /* Emit info to figure out what went wrong. */ + printk (KERN_DEBUG + "%s: Tx queue start entry %d dirty entry %d.\n", + dev->name, tp->cur_tx, tp->dirty_tx); + for (i = 0; i < NUM_TX_DESC; i++) + printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8x.%s\n", + dev->name, i, readl (ioaddr + TxStatus0 + i * 4), + i == + tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : ""); + printk (KERN_DEBUG "%s: MII #%d registers are:", dev->name, + tp->phys[0]); + for (mii_reg = 0; mii_reg < 8; mii_reg++) + printk (" %4.4x", mdio_read (dev, tp->phys[0], mii_reg)); + printk (".\n"); + + /* Stop a shared interrupt from scavenging while we are. */ + tp->dirty_tx = tp->cur_tx = 0; + + /* Dump the unsent Tx packets. */ + for (i = 0; i < NUM_TX_DESC; i++) { + struct ring_info *rp = &tp->tx_info[i]; + if (rp->skb) { + dev_kfree_skb (rp->skb); + rp->skb = NULL; + tp->stats.tx_dropped++; + } + if (rp->mapping != 0) { + pci_unmap_single (tp->pci_dev, rp->mapping, rp->skb->len); + rp->mapping = 0; + } + } + + rtl8139_hw_start (dev); + + DPRINTK ("EXIT\n"); +} + + +/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ +static void rtl8139_init_ring (struct net_device *dev) +{ + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + int i; + + DPRINTK ("ENTER\n"); + + tp->cur_rx = 0; + tp->dirty_tx = tp->cur_tx = 0; + + for (i = 0; i < NUM_TX_DESC; i++) { + tp->tx_info[i].skb = NULL; + tp->tx_info[i].mapping = 0; + tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; + } + + DPRINTK ("EXIT\n"); +} + +static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) +{ + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + void *ioaddr = tp->mmio_addr; + int entry; + unsigned long flags; + + DPRINTK ("ENTER\n"); + + netif_stop_queue (dev); + + /* Calculate the next Tx descriptor entry. */ + entry = tp->cur_tx % NUM_TX_DESC; + + spin_lock_irqsave (&tp->lock, flags); + + tp->tx_info[entry].skb = skb; + if ((long) skb->data & 3) { /* Must use alignment buffer. */ + tp->tx_info[entry].mapping = 0; + memcpy (tp->tx_buf[entry], skb->data, skb->len); + + assert (tp->tx_bufs_dma > 0); + RTL_W32 (TxAddr0 + entry * 4, tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs)); + } else { + tp->tx_info[entry].mapping = + pci_map_single(tp->pci_dev, skb->data, skb->len); + + assert (tp->tx_info[entry].mapping > 0); + RTL_W32 (TxAddr0 + entry * 4, tp->tx_info[entry].mapping); + } + + /* Note: the chip doesn't have auto-pad! */ + RTL_W32 (TxStatus0 + entry * 4, + tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); + + dev->trans_start = jiffies; + if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) /* Typical path */ + netif_start_queue (dev); + + spin_unlock_irqrestore (&tp->lock, flags); + + DPRINTK ("%s: Queued Tx packet at %p size %lu to slot %d.\n", + dev->name, skb->data, skb->len, entry); + + DPRINTK ("EXIT\n"); + return 0; +} + + +static inline void rtl8139_tx_interrupt (struct net_device *dev, + struct rtl8139_private *tp) +{ + void *ioaddr; + unsigned int dirty_tx; + + assert (dev != NULL); + assert (tp != NULL); + + dirty_tx = tp->dirty_tx; + ioaddr = tp->mmio_addr; + + while (tp->cur_tx - dirty_tx > 0) { + int entry = dirty_tx % NUM_TX_DESC; + int txstatus = readl (ioaddr + TxStatus0 + entry * 4); + + if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) + break; /* It still hasn't been Txed */ + + /* Note: TxCarrierLost is always asserted at 100mbps. */ + if (txstatus & (TxOutOfWindow | TxAborted)) { + /* There was an major error, log it. */ + DPRINTK ("%s: Transmit error, Tx status %8.8x.\n", + dev->name, txstatus); + tp->stats.tx_errors++; + if (txstatus & TxAborted) { + tp->stats.tx_aborted_errors++; + RTL_W32 (TxConfig, (TX_DMA_BURST << 8) | 0x03000001); + } + if (txstatus & TxCarrierLost) + tp->stats.tx_carrier_errors++; + if (txstatus & TxOutOfWindow) + tp->stats.tx_window_errors++; +#ifdef ETHER_STATS + if ((txstatus & 0x0f000000) == 0x0f000000) + tp->stats.collisions16++; +#endif + } else { + if (txstatus & TxUnderrun) { + /* Add 64 to the Tx FIFO threshold. */ + if (tp->tx_flag < 0x00300000) + tp->tx_flag += 0x00020000; + tp->stats.tx_fifo_errors++; + } + tp->stats.collisions += (txstatus >> 24) & 15; + tp->stats.tx_bytes += txstatus & 0x7ff; + tp->stats.tx_packets++; + } + + if (tp->tx_info[entry].mapping != 0) { + pci_unmap_single (tp->pci_dev, + tp->tx_info[entry].mapping, + tp->tx_info[entry].skb->len); + tp->tx_info[entry].mapping = 0; + } + /* Free the original skb. */ + dev_kfree_skb_irq (tp->tx_info[entry].skb); + tp->tx_info[entry].skb = NULL; + dirty_tx++; + if (tp->cur_tx - dirty_tx < NUM_TX_DESC) + netif_wake_queue (dev); + else + netif_stop_queue (dev); + } + +#ifndef RTL8139_NDEBUG + if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { + printk (KERN_ERR + "%s: Out-of-sync dirty pointer, %d vs. %d.\n", + dev->name, dirty_tx, tp->cur_tx); + dirty_tx += NUM_TX_DESC; + } +#endif + + tp->dirty_tx = dirty_tx; +} + + +/* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the + field alignments and semantics. */ +static inline void rtl8139_rx_interrupt (struct net_device *dev, + struct rtl8139_private *tp) +{ + void *ioaddr = tp->mmio_addr; + unsigned char *rx_ring = tp->rx_ring; + u16 cur_rx = tp->cur_rx; + + DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," + " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, + readw (ioaddr + RxBufAddr), + readw (ioaddr + RxBufPtr), + readb (ioaddr + ChipCmd)); + + while ((readb (ioaddr + ChipCmd) & RxBufEmpty) == 0) { + int ring_offset = cur_rx % RX_BUF_LEN; + u32 rx_status = + le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); + int rx_size = rx_status >> 16; + +#ifdef RTL8139_DEBUG + int i; + DPRINTK ("%s: rtl8139_rx() status %4.4x, size %4.4x," + " cur %4.4x.\n", dev->name, rx_status, + rx_size, cur_rx); + DPRINTK ("%s: Frame contents ", dev->name); + for (i = 0; i < 70; i++) + printk (" %2.2x", rx_ring[ring_offset + i]); + printk (".\n"); +#endif + + if (rx_status & + (RxBadSymbol | RxRunt | RxTooLong | RxCRCErr | + RxBadAlign)) { + DPRINTK ("%s: Ethernet frame had errors," + " status %8.8x.\n", dev->name, + rx_status); + if (rx_status & RxTooLong) { + DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", + dev->name, rx_status); + /* A.C.: The chip hangs here. */ + } + tp->stats.rx_errors++; + if (rx_status & (RxBadSymbol | RxBadAlign)) + tp->stats.rx_frame_errors++; + if (rx_status & (RxRunt | RxTooLong)) + tp->stats.rx_length_errors++; + if (rx_status & RxCRCErr) + tp->stats.rx_crc_errors++; + /* Reset the receiver, based on RealTek recommendation. (Bug?) */ + tp->cur_rx = 0; + RTL_W8 (ChipCmd, CmdTxEnb); + /* A.C.: Reset the multicast list. */ + rtl8139_set_rx_mode (dev); + RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); + } else { + /* Malloc up new buffer, compatible with net-2e. */ + /* Omit the four octet CRC from the length. */ + struct sk_buff *skb; + + skb = dev_alloc_skb (rx_size + 2); + if (skb == NULL) { + printk (KERN_WARNING + "%s: Memory squeeze, deferring packet.\n", + dev->name); + /* We should check that some rx space is free. + If not, free one and mark stats->rx_dropped++. */ + tp->stats.rx_dropped++; + break; + } + skb->dev = dev; + skb_reserve (skb, 2); /* 16 byte align the IP fields. */ + if (ring_offset + rx_size + 4 > RX_BUF_LEN) { + int semi_count = + RX_BUF_LEN - ring_offset - 4; + /* This could presumably use two calls to copy_and_sum()? */ + memcpy (skb_put (skb, semi_count), + &rx_ring[ring_offset + 4], + semi_count); + memcpy (skb_put + (skb, rx_size - semi_count), + rx_ring, rx_size - semi_count); +#ifdef RTL8139_DEBUG + { + int i; + printk (KERN_DEBUG + "%s: Frame wrap @%d", + dev->name, semi_count); + for (i = 0; i < 16; i++) + printk (" %2.2x", + rx_ring[i]); + printk (".\n"); + memset (rx_ring, 0xcc, 16); + } +#endif /* RTL8139_DEBUG */ + + } else { + eth_copy_and_sum (skb, + &rx_ring[ring_offset + + 4], rx_size, 0); + skb_put (skb, rx_size); + } + skb->protocol = eth_type_trans (skb, dev); + netif_rx (skb); + tp->stats.rx_bytes += rx_size; + tp->stats.rx_packets++; + } + + cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; + RTL_W16 (RxBufPtr, cur_rx - 16); + } + DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," + " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, + readw (ioaddr + RxBufAddr), + readw (ioaddr + RxBufPtr), + readb (ioaddr + ChipCmd)); + tp->cur_rx = cur_rx; +} + + +static inline int rtl8139_weird_interrupt (struct net_device *dev, + struct rtl8139_private *tp, + int status, int link_changed) +{ + void *ioaddr; + + DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", + dev->name, status); + + assert (dev != NULL); + assert (tp != NULL); + + ioaddr = tp->mmio_addr; + + if (status == 0xffffffff) { + printk (KERN_WARNING PFX "abnormal interrupt, card ejected? (ok to ignore)\n"); + return -1; + } + + /* Update the error count. */ + tp->stats.rx_missed_errors += + readl (ioaddr + RxMissed); + RTL_W32 (RxMissed, 0); + + if ((status & RxUnderrun) && link_changed && + (tp->drv_flags & HAS_LNK_CHNG)) { + /* Really link-change on new chips. */ + int lpar = readw (ioaddr + NWayLPAR); + int duplex = (lpar & 0x0100) || (lpar & 0x01C0) == 0x0040 + || tp->duplex_lock; + if (tp->full_duplex != duplex) { + tp->full_duplex = duplex; + RTL_W8 (Cfg9346, 0xC0); + RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20); + RTL_W8 (Cfg9346, 0x00); + } + status &= ~RxUnderrun; + } + if (status & + (RxUnderrun | RxOverflow | RxErr | RxFIFOOver)) + tp->stats.rx_errors++; + + if (status & (PCSTimeout)) + tp->stats.rx_length_errors++; + if (status & (RxUnderrun | RxFIFOOver)) + tp->stats.rx_fifo_errors++; + if (status & RxOverflow) { + tp->stats.rx_over_errors++; + tp->cur_rx = readw (ioaddr + RxBufAddr) % RX_BUF_LEN; + RTL_W16 (RxBufPtr, tp->cur_rx - 16); + } + if (status & PCIErr) { + u16 pci_cmd_status; + pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); + + printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", + dev->name, pci_cmd_status); + } + + return 0; +} + + +/* The interrupt handler does all of the Rx thread work and cleans up + after the Tx thread. */ +static void rtl8139_interrupt (int irq, void *dev_instance, + struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) dev_instance; + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + int boguscnt = max_interrupt_work; + void *ioaddr = tp->mmio_addr; + int link_changed = 0; /* Grrr, avoid bogus "uninitialized" warning */ + + spin_lock_irq (&tp->lock); + + do { + int status = readw (ioaddr + IntrStatus); + /* Acknowledge all of the current interrupt sources ASAP, but + an first get an additional status bit from CSCR. */ + if (status & RxUnderrun) + link_changed = readw (ioaddr + CSCR) & CSCR_LinkChangeBit; + RTL_W16 (IntrStatus, status); + + DPRINTK ("%s: interrupt status=%#4.4x new intstat=%#4.4x.\n", + dev->name, status, + readw (ioaddr + IntrStatus)); + + if ((status & + (PCIErr | PCSTimeout | RxUnderrun | RxOverflow | + RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0) + break; + + /* Check uncommon events with one test. */ + if (status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow | + RxFIFOOver | TxErr | RxErr)) + if (rtl8139_weird_interrupt (dev, tp, status, + link_changed) == -1) + break; + + if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) /* Rx interrupt */ + rtl8139_rx_interrupt (dev, tp); + + if (status & (TxOK | TxErr)) + rtl8139_tx_interrupt (dev, tp); + + if (--boguscnt < 0) { + printk (KERN_WARNING + "%s: Too much work at interrupt, " + "IntrStatus=0x%4.4x.\n", dev->name, + status); + /* Clear all interrupt sources. */ + RTL_W16 (IntrStatus, 0xffff); + break; + } + } while (1); + + DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", + dev->name, readw (ioaddr + IntrStatus)); + + spin_unlock_irq (&tp->lock); + return; +} + +static int rtl8139_close (struct net_device *dev) +{ + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + void *ioaddr = tp->mmio_addr; + int i; + + DPRINTK ("ENTER\n"); + + netif_stop_queue (dev); + + DPRINTK ("%s: Shutting down ethercard, status was 0x%4.4x.\n", + dev->name, readw (ioaddr + IntrStatus)); + + /* Disable interrupts by clearing the interrupt mask. */ + RTL_W16 (IntrMask, 0x0000); + + /* Stop the chip's Tx and Rx DMA processes. */ + RTL_W8 (ChipCmd, 0x00); + + /* Update the error counts. */ + tp->stats.rx_missed_errors += RTL_R32 (RxMissed); + RTL_W32 (RxMissed, 0); + + del_timer (&tp->timer); + + free_irq (dev->irq, dev); + + for (i = 0; i < NUM_TX_DESC; i++) { + struct sk_buff *skb = tp->tx_info[i].skb; + dma_addr_t mapping = tp->tx_info[i].mapping; + + if (skb) { + if (mapping) + pci_unmap_single (tp->pci_dev, mapping, skb->len); + dev_kfree_skb (skb); + } + tp->tx_info[i].skb = NULL; + tp->tx_info[i].mapping = 0; + } + + pci_free_consistent(tp->pci_dev, RX_BUF_LEN + 16, + tp->rx_ring, tp->rx_ring_dma); + pci_free_consistent(tp->pci_dev, TX_BUF_SIZE * NUM_TX_DESC, + tp->tx_bufs, tp->tx_bufs_dma); + tp->rx_ring = NULL; + tp->tx_bufs = NULL; + + /* Green! Put the chip in low-power mode. */ + RTL_W8 (Cfg9346, 0xC0); + RTL_W8 (Config1, 0x03); + RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ + + MOD_DEC_USE_COUNT; + + DPRINTK ("EXIT\n"); + return 0; +} + +static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + u16 *data = (u16 *) & rq->ifr_data; + + DPRINTK ("ENTER\n"); + + switch (cmd) { + case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ + data[0] = tp->phys[0] & 0x3f; + /* Fall Through */ + case SIOCDEVPRIVATE + 1: /* Read the specified MII register. */ + data[3] = mdio_read (dev, data[0], data[1] & 0x1f); + DPRINTK ("EXIT\n"); + return 0; + case SIOCDEVPRIVATE + 2: /* Write the specified MII register */ + if (!capable (CAP_NET_ADMIN)) + return -EPERM; + mdio_write (dev, data[0], data[1] & 0x1f, data[2]); + DPRINTK ("EXIT\n"); + return 0; + default: + DPRINTK ("EXIT\n"); + return -EOPNOTSUPP; + } + + DPRINTK ("EXIT\n"); +} + +static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) +{ + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + void *ioaddr = tp->mmio_addr; + + DPRINTK ("ENTER\n"); + + assert (tp != NULL); + + if (test_bit(LINK_STATE_START, &dev->state)) { + tp->stats.rx_missed_errors += RTL_R32 (RxMissed); + RTL_W32 (RxMissed, 0); + } + + DPRINTK ("EXIT\n"); + return &tp->stats; +} + +/* Set or clear the multicast filter for this adaptor. + This routine is not state sensitive and need not be SMP locked. */ + +static unsigned const ethernet_polynomial = 0x04c11db7U; +static inline u32 ether_crc (int length, unsigned char *data) +{ + int crc = -1; + + DPRINTK ("ENTER\n"); + + while (--length >= 0) { + unsigned char current_octet = *data++; + int bit; + for (bit = 0; bit < 8; bit++, current_octet >>= 1) + crc = (crc << 1) ^ + ((crc < 0) ^ (current_octet & 1) ? + ethernet_polynomial : 0); + } + + DPRINTK ("EXIT\n"); + return crc; +} + +static void rtl8139_set_rx_mode (struct net_device *dev) +{ + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + void *ioaddr = tp->mmio_addr; + u32 mc_filter[2]; /* Multicast hash filter */ + int i, rx_mode; + + DPRINTK ("ENTER\n"); + + DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8x.\n", + dev->name, dev->flags, readl (ioaddr + RxConfig)); + + /* Note: do not reorder, GCC is clever about common statements. */ + if (dev->flags & IFF_PROMISC) { + /* Unconditionally log net taps. */ + printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n", + dev->name); + rx_mode = + AcceptBroadcast | AcceptMulticast | AcceptMyPhys | + AcceptAllPhys; + mc_filter[1] = mc_filter[0] = 0xffffffff; + } else if ((dev->mc_count > multicast_filter_limit) + || (dev->flags & IFF_ALLMULTI)) { + /* Too many to filter perfectly -- accept all multicasts. */ + rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; + mc_filter[1] = mc_filter[0] = 0xffffffff; + } else { + struct dev_mc_list *mclist; + rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; + mc_filter[1] = mc_filter[0] = 0; + for (i = 0, mclist = dev->mc_list; + mclist && i < dev->mc_count; + i++, mclist = + mclist->next) set_bit (ether_crc (ETH_ALEN, + mclist-> + dmi_addr) >> 26, + mc_filter); + } + /* We can safely update without stopping the chip. */ + RTL_W32 (RxConfig, tp->rx_config | rx_mode); + RTL_W32 (MAR0 + 0, mc_filter[0]); + RTL_W32 (MAR0 + 4, mc_filter[1]); + + DPRINTK ("EXIT\n"); +} + + +static void rtl8139_suspend (struct pci_dev *pdev) +{ + struct net_device *dev = PCI_GET_DRIVER_DATA (pdev); + struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + void *ioaddr = tp->mmio_addr; + + netif_stop_queue (dev); + + /* Disable interrupts, stop Tx and Rx. */ + RTL_W16 (IntrMask, 0x0000); + RTL_W8 (ChipCmd, 0x00); + + /* Update the error counts. */ + tp->stats.rx_missed_errors += RTL_R32 (RxMissed); + RTL_W32 (RxMissed, 0); +} + + +static void rtl8139_resume (struct pci_dev *pdev) +{ + struct net_device *dev = PCI_GET_DRIVER_DATA (pdev); + + rtl8139_hw_start(dev); +} + + +static struct pci_driver rtl8139_pci_driver = { + name: RTL8139_MODULE_NAME, + id_table: rtl8139_pci_tbl, + probe: rtl8139_init_one, + remove: rtl8139_remove_one, + suspend: rtl8139_suspend, + resume: rtl8139_resume, +}; + + +static int __init rtl8139_init_module (void) +{ + int rc; + + DPRINTK ("ENTER\n"); + + rc = pci_register_driver (&rtl8139_pci_driver); + + if (rc > 0) { + printk (KERN_INFO RTL8139_DRIVER_NAME + " loaded (%d device%s registered)\n", + rc, rc > 1 ? "s" : ""); + } + + DPRINTK ("EXIT\n"); + return rc > 0 ? 0 : -ENODEV; +} + + +static void __exit rtl8139_cleanup_module (void) +{ + pci_unregister_driver (&rtl8139_pci_driver); +} + + +module_init(rtl8139_init_module); +module_exit(rtl8139_cleanup_module); diff --git a/drivers/net/Config.in b/drivers/net/Config.in index f3eba639f261..54ecdad60d19 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -83,10 +83,6 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then tristate ' NI5210 support' CONFIG_NI52 tristate ' NI6510 support' CONFIG_NI65 fi - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate ' RealTek 8129/8139 (not 8019/8029!) support (EXPERIMENTAL)' CONFIG_RTL8139 - tristate ' DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102 - fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate ' AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700 fi @@ -114,8 +110,8 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then tristate ' SKnet MCA support' CONFIG_SKMC tristate ' NE/2 (ne2000 MCA version) support' CONFIG_NE2_MCA fi - bool ' EISA, VLB, PCI and on board controllers' CONFIG_NET_EISA - if [ "$CONFIG_NET_EISA" = "y" ]; then + bool ' EISA, VLB, PCI and on board controllers' CONFIG_NET_PCI + if [ "$CONFIG_NET_PCI" = "y" ]; then tristate ' AMD PCnet32 (VLB and PCI) support' CONFIG_PCNET32 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate ' Adaptec Starfire support (EXPERIMENTAL)' CONFIG_ADAPTEC_STARFIRE @@ -129,6 +125,9 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then tristate ' Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5 tristate ' DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP tristate ' Digi Intl. RightSwitch SE-X support' CONFIG_DGRS + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate ' DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102 + fi tristate ' EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate ' Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390 @@ -136,6 +135,10 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then fi tristate ' PCI NE2000 support' CONFIG_NE2K_PCI # tristate ' Sundance Alta support' CONFIG_ALTA + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate ' RealTek 8129 (not 8019/8029!) support (EXPERIMENTAL)' CONFIG_RTL8129 + fi + tristate ' RealTek RTL-8139 PCI Fast Ethernet Adapter support' CONFIG_8139TOO tristate ' SiS 900/7016 PCI Fast Ethernet Adapter support' CONFIG_SIS900 tristate ' TI ThunderLAN support' CONFIG_TLAN tristate ' VIA Rhine support' CONFIG_VIA_RHINE diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 01adff342087..55e6d0e46a41 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -228,7 +228,8 @@ obj-$(CONFIG_EL3) += 3c509.o obj-$(CONFIG_3C515) += 3c515.o obj-$(CONFIG_EEXPRESS) += eexpress.o obj-$(CONFIG_EEXPRESS_PRO) += eepro.o -obj-$(CONFIG_RTL8139) += rtl8139.o +obj-$(CONFIG_RTL8129) += rtl8129.o +obj-$(CONFIG_8139TOO) += 8139too.o obj-$(CONFIG_WAVELAN) += wavelan.o obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o obj-$(CONFIG_ZNET) += znet.o diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index f15e31ae4426..f62bfebe239d 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -164,7 +164,6 @@ static void load_csrs (struct lance_private *lp) #define ZERO 0 /* Setup the Lance Rx and Tx rings */ -/* Sets dev->tbusy */ static void lance_init_ring (struct net_device *dev) { struct lance_private *lp = (struct lance_private *) dev->priv; @@ -176,7 +175,7 @@ static void lance_init_ring (struct net_device *dev) aib = lp->lance_init_block; /* Lock out other processes while setting up hardware */ - dev->tbusy = 1; + netif_stop_queue(dev); lp->rx_new = lp->tx_new = 0; lp->rx_old = lp->tx_old = 0; @@ -442,11 +441,6 @@ static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs) if (!(csr0 & LE_C0_INTR)) /* Check if any interrupt has */ return; /* been generated by the Lance. */ - if (dev->interrupt) - printk ("%s: again", dev->name); - - dev->interrupt = 1; - /* Acknowledge all the interrupt sources ASAP */ ll->rdp = csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT| LE_C0_INIT); @@ -473,15 +467,14 @@ static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs) ll->rdp = LE_C0_STRT; } - if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { - dev->tbusy = 0; - mark_bh (NET_BH); - } + if (test_bit(LINK_STATE_XOFF, &dev->state) && + TX_BUFFS_AVAIL > 0) + netif_wake_queue(dev); + ll->rap = LE_CSR0; ll->rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR| LE_C0_IDON|LE_C0_INEA; - dev->interrupt = 0; } struct net_device *last_dev = 0; @@ -506,9 +499,7 @@ static int lance_open (struct net_device *dev) load_csrs (lp); lance_init_ring (dev); - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + netif_start_queue(dev); status = init_restart_lance (lp); @@ -522,9 +513,8 @@ static int lance_close (struct net_device *dev) struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_regs *ll = lp->ll; - dev->start = 0; - dev->tbusy = 1; - del_timer(&lp->multicast_timer); + netif_stop_queue(dev); + del_timer_sync(&lp->multicast_timer); /* Stop the card */ ll->rap = LE_CSR0; @@ -548,11 +538,11 @@ static inline int lance_reset (struct net_device *dev) ll->rdp = LE_C0_STOP; load_csrs (lp); + lance_init_ring (dev); dev->trans_start = jiffies; - dev->interrupt = 0; - dev->start = 1; - dev->tbusy = 0; + netif_start_queue(dev); + status = init_restart_lance (lp); #ifdef DEBUG_DRIVER printk ("Lance restart=%d\n", status); @@ -560,6 +550,17 @@ static inline int lance_reset (struct net_device *dev) return status; } +static void lance_tx_timeout(struct net_device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_regs *ll = lp->ll; + + printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n", + dev->name, ll->rdp); + lance_reset(dev); + netif_wake_queue(dev); +} + static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) { struct lance_private *lp = (struct lance_private *)dev->priv; @@ -570,26 +571,6 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) static int outs; unsigned long flags; - /* Transmitter timeout, serious problems */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - - if (tickssofar < 100) { - status = -1; - } else { - printk ("%s: transmit timed out, status %04x, resetting\n", - dev->name, ll->rdp); - lance_reset (dev); - } - return status; - } - - /* Block a timer-based transmit from overlapping. */ - if (test_and_set_bit (0, (void *) &dev->tbusy) != 0) { - printk ("Transmitter access conflict.\n"); - return -1; - } - skblen = skb->len; save_flags(flags); @@ -628,13 +609,15 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask; outs++; + + if (TX_BUFFS_AVAIL <= 0) + netif_stop_queue(dev); + /* Kick the lance: transmit now */ ll->rdp = LE_C0_INEA | LE_C0_TDMD; dev->trans_start = jiffies; dev_kfree_skb (skb); - if (TX_BUFFS_AVAIL) - dev->tbusy = 0; restore_flags(flags); return status; @@ -704,21 +687,17 @@ static void lance_set_multicast (struct net_device *dev) volatile struct lance_init_block *ib = lp->init_block; volatile struct lance_regs *ll = lp->ll; - if (!dev->start) + if (!test_bit(LINK_STATE_START, &dev->state)) return; - if (dev->tbusy) { - mod_timer(&lp->multicast_timer, jiffies + 2); - return; - } - set_bit (0, (void *) &dev->tbusy); - if (lp->tx_old != lp->tx_new) { mod_timer(&lp->multicast_timer, jiffies + 4); - dev->tbusy = 0; + netif_wake_queue(dev); return; } + netif_stop_queue(dev); + ll->rap = LE_CSR0; ll->rdp = LE_C0_STOP; lance_init_ring (dev); @@ -731,14 +710,19 @@ static void lance_set_multicast (struct net_device *dev) } load_csrs (lp); init_restart_lance (lp); - dev->tbusy = 0; - mark_bh(NET_BH); + netif_wake_queue(dev); } -int __init a2065_probe(struct net_device *dev) +static int __init a2065_probe(void) { + struct net_device *dev = NULL; + static int called = 0; struct zorro_dev *z = NULL; + if (called) + return -ENODEV; + called++; + while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { unsigned long board, base_addr, ram_start; int is_cbm; @@ -765,6 +749,18 @@ int __init a2065_probe(struct net_device *dev) continue; } strcpy(z->name, "A2065 Ethernet Card"); + + dev = init_etherdev(NULL, sizeof(struct lance_private)); + + if (dev == NULL) { + release_mem_region(base_addr, + sizeof(struct lance_regs)); + release_mem_region(ram_start, A2065_RAM_SIZE); + return -ENOMEM; + } + priv = (struct lance_private *)dev->priv; + memset(priv, 0, sizeof(struct lance_private)); + if (is_cbm) { /* Commodore */ dev->dev_addr[0] = 0x00; dev->dev_addr[1] = 0x80; @@ -782,18 +778,6 @@ int __init a2065_probe(struct net_device *dev) dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); - init_etherdev(dev, 0); - - dev->priv = kmalloc(sizeof(struct lance_private), GFP_KERNEL); - if (dev->priv == NULL) { - release_mem_region(base_addr, - sizeof(struct lance_regs)); - release_mem_region(ram_start, A2065_RAM_SIZE); - return -ENOMEM; - } - priv = (struct lance_private *)dev->priv; - memset(priv, 0, sizeof(struct lance_private)); - dev->base_addr = ZTWO_VADDR(base_addr); dev->mem_start = ZTWO_VADDR(ram_start); dev->mem_end = dev->mem_start+A2065_RAM_SIZE; @@ -812,6 +796,8 @@ int __init a2065_probe(struct net_device *dev) dev->open = &lance_open; dev->stop = &lance_close; dev->hard_start_xmit = &lance_start_xmit; + dev->tx_timeout = &lance_tx_timeout; + dev->watchdog_timeo = 5*HZ; dev->get_stats = &lance_get_stats; dev->set_multicast_list = &lance_set_multicast; dev->dma = 0; @@ -828,31 +814,9 @@ int __init a2065_probe(struct net_device *dev) } -#ifdef MODULE -static char devicename[9] = { 0, }; - -static struct net_device a2065_dev = -{ - devicename, /* filled in by register_netdev() */ - 0, 0, 0, 0, /* memory */ - 0, 0, /* base, irq */ - 0, 0, 0, NULL, a2065_probe, -}; - -int init_module(void) -{ - int err; - - if ((err = register_netdev(&a2065_dev))) { - if (err == -EIO) - printk("No A2065 board found. Module not loaded.\n"); - return(err); - } - return(0); -} - -void cleanup_module(void) +static void __exit a2065_cleanup(void) { +#ifdef MODULE struct lance_private *priv = (struct lance_private *)a2065_dev.priv; unregister_netdev(&a2065_dev); @@ -860,6 +824,8 @@ void cleanup_module(void) sizeof(struct lance_regs)); release_mem_region(ZTWO_PADDR(a2065_dev.mem_start), A2065_RAM_SIZE); kfree(priv); +#endif } -#endif /* MODULE */ +module_init(a2065_probe); +module_exit(a2065_cleanup); diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 1fc708ee1dd3..0829bd82ef56 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -2,7 +2,7 @@ * Linux ARCnet driver - "RIM I" (entirely mem-mapped) cards * * Written 1994-1999 by Avery Pennarun. - * Written 1999 by Martin Mares . + * Written 1999-2000 by Martin Mares . * Derived from skeleton.c by Donald Becker. * * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) @@ -325,20 +325,11 @@ void cleanup_module(void) { struct net_device *dev = my_dev; struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - void *ioaddr = lp->mem_start + 0x800; - - if (dev->start) - dev->stop(dev); - - /* Flush TX and disable RX */ - AINTMASK(0); /* disable IRQ's */ - ACOMMAND(NOTXcmd); /* stop transmit */ - ACOMMAND(NORXcmd); /* disable receive */ + unregister_netdev(dev); free_irq(dev->irq, dev); iounmap(lp->mem_start); release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); - unregister_netdev(dev); kfree(dev->priv); kfree(dev); } diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 98b2ac4dac64..9b54d0b0273e 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -3,7 +3,7 @@ * * Written 1997 by David Woodhouse. * Written 1994-1999 by Avery Pennarun. - * Written 1999 by Martin Mares . + * Written 1999-2000 by Martin Mares . * Derived from skeleton.c by Donald Becker. * * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) @@ -41,7 +41,7 @@ * */ -#define VERSION "arcnet: v3.91 BETA 99/12/18 - by Avery Pennarun et al.\n" +#define VERSION "arcnet: v3.92 BETA 2000/02/13 - by Avery Pennarun et al.\n" #include #include @@ -97,6 +97,7 @@ EXPORT_SYMBOL(arcnet_interrupt); static int arcnet_open(struct net_device *dev); static int arcnet_close(struct net_device *dev); static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev); +static void arcnet_timeout(struct net_device *dev); static int arcnet_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len); @@ -347,6 +348,7 @@ void arcdev_setup(struct net_device *dev) dev->addr_len = 1; dev->tx_queue_len = 30; dev->broadcast[0] = 0x00; /* for us, broadcasts are address 0 */ + dev->watchdog_timeo = TX_TIMEOUT; /* New-style flags. */ dev->flags = IFF_BROADCAST; @@ -358,6 +360,7 @@ void arcdev_setup(struct net_device *dev) dev->open = arcnet_open; dev->stop = arcnet_close; dev->hard_start_xmit = arcnet_send_packet; + dev->tx_timeout = arcnet_timeout; dev->get_stats = arcnet_get_stats; dev->hard_header = arcnet_header; dev->rebuild_header = arcnet_rebuild_header; @@ -397,10 +400,6 @@ static int arcnet_open(struct net_device *dev) if (ARCRESET(0) && ARCRESET(1)) return -ENODEV; - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 0; - newmtu = choose_mtu(); if (newmtu < dev->mtu) dev->mtu = newmtu; @@ -441,9 +440,6 @@ static int arcnet_open(struct net_device *dev) if (ASTATUS() & RESETflag) ACOMMAND(CFLAGScmd | RESETclear); - /* we're started */ - dev->start = 1; - /* make sure we're ready to receive IRQ's. */ AINTMASK(0); udelay(1); /* give it time to set the mask before @@ -453,6 +449,8 @@ static int arcnet_open(struct net_device *dev) lp->intmask = NORXflag | RECONflag; AINTMASK(lp->intmask); + netif_start_queue(dev); + return 0; } @@ -462,16 +460,14 @@ static int arcnet_close(struct net_device *dev) { struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + netif_stop_queue(dev); + /* flush TX and disable RX */ AINTMASK(0); ACOMMAND(NOTXcmd); /* stop transmit */ ACOMMAND(NORXcmd); /* disable receive */ mdelay(1); - dev->tbusy = 1; - dev->start = 0; - dev->interrupt = 0; - /* shut down the card */ ARCOPEN(0); @@ -584,48 +580,6 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev) "transmit requested (status=%Xh, txbufs=%d/%d, len=%d)\n", ASTATUS(), lp->cur_tx, lp->next_tx, skb->len); - if (dev->tbusy) { - /* - * If we get here, some higher level has decided we are broken. - * There should really be a "kick me" function call instead. - */ - unsigned long flags; - int tickssofar = jiffies - dev->trans_start, status = ASTATUS(); - - if (tickssofar < TX_TIMEOUT) { - BUGMSG(D_DURING, "premature kickme! (status=%Xh ticks=%d)\n", - status, tickssofar); - return 1; /* means "try again" */ - } - save_flags(flags); - cli(); - - if (status & TXFREEflag) { /* transmit _DID_ finish */ - BUGMSG(D_NORMAL, "tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n", - status, tickssofar, lp->intmask, lp->lasttrans_dest); - lp->stats.tx_errors++; - } else { - BUGMSG(D_EXTRA, "tx timed out (status=%Xh, tickssofar=%d, intmask=%Xh, dest=%02Xh)\n", - status, tickssofar, lp->intmask, lp->lasttrans_dest); - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; - - ACOMMAND(NOTXcmd | (lp->cur_tx << 3)); - } - - /* - * interrupt handler will set dev->tbusy = 0 when it notices the - * transmit has been canceled. - */ - - /* make sure we didn't miss a TX IRQ */ - AINTMASK(0); - lp->intmask |= TXFREEflag; - AINTMASK(lp->intmask); - - restore_flags(flags); - return 1; - } pkt = (struct archdr *) skb->data; soft = &pkt->soft.rfc1201; proto = arc_proto_map[soft->proto]; @@ -638,18 +592,10 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev) dev_kfree_skb(skb); return 0; /* don't try again */ } - /* - * Block a timer-based transmit from overlapping. This could better be - * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. - */ - if (test_and_set_bit(0, (int *) &dev->tbusy)) { - BUGMSG(D_NORMAL, "transmitter called with busy bit set! " - "(status=%Xh, tickssofar=%ld)\n", - ASTATUS(), jiffies - dev->trans_start); - lp->stats.tx_errors++; - lp->stats.tx_fifo_errors++; - return 0; /* don't try again */ - } + + /* We're busy transmitting a packet... */ + netif_stop_queue(dev); + AINTMASK(0); txbuf = get_arcbuf(dev); @@ -718,6 +664,37 @@ static int go_tx(struct net_device *dev) } +/* Called by the kernel when transmit times out */ +static void arcnet_timeout(struct net_device *dev) +{ + unsigned long flags; + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + int status = ASTATUS(); + + save_flags(flags); + cli(); + + if (status & TXFREEflag) { /* transmit _DID_ finish */ + BUGMSG(D_NORMAL, "tx timeout - missed IRQ? (status=%Xh, mask=%Xh, dest=%02Xh)\n", + status, lp->intmask, lp->lasttrans_dest); + lp->stats.tx_errors++; + } else { + BUGMSG(D_EXTRA, "tx timed out (status=%Xh, intmask=%Xh, dest=%02Xh)\n", + status, lp->intmask, lp->lasttrans_dest); + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + ACOMMAND(NOTXcmd | (lp->cur_tx << 3)); + } + + /* make sure we didn't miss a TX IRQ */ + AINTMASK(0); + lp->intmask |= TXFREEflag; + AINTMASK(lp->intmask); + + restore_flags(flags); +} + + /* * The typical workload of the driver: Handle the network interface * interrupts. Establish which device needs attention, and call the correct @@ -743,25 +720,20 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) return; } /* - * RESET flag was enabled - if !dev->start, we must clear it right + * RESET flag was enabled - if device is not running, we must clear it right * away (but nothing else). */ - if (!dev->start) { + if (!test_bit(LINK_STATE_START, &dev->state)) { if (ASTATUS() & RESETflag) ACOMMAND(CFLAGScmd | RESETclear); AINTMASK(0); return; } - if (dev->interrupt) { - BUGMSG(D_NORMAL, "DRIVER PROBLEM! Nested arcnet interrupts!\n"); - return; /* don't even try. */ - } - dev->interrupt = 1; BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", ASTATUS(), lp->intmask); - boguscount = 3; + boguscount = 5; do { status = ASTATUS(); didsomething = 0; @@ -839,17 +811,15 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (lp->outgoing.proto->continue_tx(dev, txbuf)) { /* that was the last segment */ lp->stats.tx_bytes += lp->outgoing.skb->len; - dev_kfree_skb(lp->outgoing.skb); + dev_kfree_skb_irq(lp->outgoing.skb); lp->outgoing.proto = NULL; } lp->next_tx = txbuf; } } /* inform upper layers of idleness, if necessary */ - if (lp->cur_tx == -1) { - dev->tbusy = 0; - mark_bh(NET_BH); - } + if (lp->cur_tx == -1) + netif_wake_queue(dev); } /* now process the received packet, if any */ if (recbuf != -1) { @@ -922,8 +892,6 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) AINTMASK(0); udelay(1); AINTMASK(lp->intmask); - - dev->interrupt = 0; } @@ -987,11 +955,6 @@ void arcnet_rx(struct net_device *dev, int bufnum) } /* call the protocol-specific receiver. */ arc_proto_map[soft->proto]->rx(dev, bufnum, &pkt, length); - - /* - * If any worthwhile packets have been received, a mark_bh(NET_BH) has - * been done by netif_rx and Linux will handle them after we return. - */ } diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index 94c68901b747..7bd06e2e48c7 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -3,7 +3,7 @@ * * Written 1997 by David Woodhouse. * Written 1994-1999 by Avery Pennarun. - * Written 1999 by Martin Mares . + * Written 1999-2000 by Martin Mares . * Derived from skeleton.c by Donald Becker. * * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) @@ -176,12 +176,9 @@ void cleanup_module(void) { struct net_device *dev = my_dev; - if (dev->start) - dev->stop(dev); - + unregister_netdev(dev); free_irq(dev->irq, dev); release_region(dev->base_addr, ARCNET_TOTAL_SIZE); - unregister_netdev(dev); kfree(dev->priv); kfree(dev); } diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 585308c27d8b..b88203f543b1 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -3,7 +3,7 @@ * * Written 1994-1999 by Avery Pennarun, * based on an ISA version by David Woodhouse. - * Written 1999 by Martin Mares . + * Written 1999-2000 by Martin Mares . * Derived from skeleton.c by Donald Becker. * * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) @@ -148,13 +148,9 @@ void cleanup_module(void) for (count = 0; count < numcards; count++) { dev = cards[count]; - - if (dev->start) - dev->stop(dev); - + unregister_netdev(dev); free_irq(dev->irq, dev); release_region(dev->base_addr, ARCNET_TOTAL_SIZE); - unregister_netdev(dev); kfree(dev->priv); kfree(dev); } diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index edd92ff25426..79800883ff72 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -3,7 +3,7 @@ * * Written 1997 by David Woodhouse. * Written 1994-1999 by Avery Pennarun. - * Written 1999 by Martin Mares . + * Written 1999-2000 by Martin Mares . * Derived from skeleton.c by Donald Becker. * * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) @@ -406,20 +406,13 @@ void cleanup_module(void) struct net_device *dev = my_dev; int ioaddr = dev->base_addr; - if (dev->start) - dev->stop(dev); - - /* Flush TX and disable RX */ - AINTMASK(0); /* disable IRQ's */ - ACOMMAND(NOTXcmd); /* stop transmit */ - ACOMMAND(NORXcmd); /* disable receive */ + unregister_netdev(dev); /* Set the thing back to MMAP mode, in case the old driver is loaded later */ outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG); free_irq(dev->irq, dev); release_region(dev->base_addr, ARCNET_TOTAL_SIZE); - unregister_netdev(dev); kfree(dev->priv); kfree(dev); } diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 8431156090b8..ac8790ef0139 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -143,7 +143,7 @@ int __init com90xx_probe(struct net_device *dev) numprint %= 8; if (!numprint) { BUGMSG2(D_INIT, "\n"); - BUGMSG(D_INIT, "S1: "); + BUGMSG2(D_INIT, "S1: "); } BUGMSG2(D_INIT, "%Xh ", *port); @@ -151,7 +151,7 @@ int __init com90xx_probe(struct net_device *dev) if (check_region(*port, ARCNET_TOTAL_SIZE)) { BUGMSG2(D_INIT_REASONS, "(check_region)\n"); - BUGMSG(D_INIT_REASONS, "S1: "); + BUGMSG2(D_INIT_REASONS, "S1: "); BUGLVL(D_INIT_REASONS) numprint = 0; *port = ports[numports - 1]; numports--; @@ -160,7 +160,7 @@ int __init com90xx_probe(struct net_device *dev) } if (ASTATUS() == 0xFF) { BUGMSG2(D_INIT_REASONS, "(empty)\n"); - BUGMSG(D_INIT_REASONS, "S1: "); + BUGMSG2(D_INIT_REASONS, "S1: "); BUGLVL(D_INIT_REASONS) numprint = 0; *port = ports[numports - 1]; numports--; @@ -170,13 +170,13 @@ int __init com90xx_probe(struct net_device *dev) inb(_RESET); /* begin resetting card */ BUGMSG2(D_INIT_REASONS, "\n"); - BUGMSG(D_INIT_REASONS, "S1: "); + BUGMSG2(D_INIT_REASONS, "S1: "); BUGLVL(D_INIT_REASONS) numprint = 0; } BUGMSG2(D_INIT, "\n"); if (!numports) { - BUGMSG(D_NORMAL, "S1: No ARCnet cards found.\n"); + BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n"); return -ENODEV; } /* Stage 2: we have now reset any possible ARCnet cards, so we can't @@ -189,7 +189,7 @@ int __init com90xx_probe(struct net_device *dev) numprint %= 8; if (!numprint) { BUGMSG2(D_INIT, "\n"); - BUGMSG(D_INIT, "S2: "); + BUGMSG2(D_INIT, "S2: "); } BUGMSG2(D_INIT, "%Xh ", *port); } @@ -207,13 +207,13 @@ int __init com90xx_probe(struct net_device *dev) numprint %= 8; if (!numprint) { BUGMSG2(D_INIT, "\n"); - BUGMSG(D_INIT, "S3: "); + BUGMSG2(D_INIT, "S3: "); } BUGMSG2(D_INIT, "%lXh ", *shmem); if (check_mem_region(*shmem, BUFFER_SIZE)) { BUGMSG2(D_INIT_REASONS, "(check_mem_region)\n"); - BUGMSG(D_INIT_REASONS, "Stage 3: "); + BUGMSG2(D_INIT_REASONS, "Stage 3: "); BUGLVL(D_INIT_REASONS) numprint = 0; *shmem = shmems[numshmems - 1]; numshmems--; @@ -223,7 +223,7 @@ int __init com90xx_probe(struct net_device *dev) if (isa_readb(ptr) != TESTvalue) { BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n", isa_readb(ptr), TESTvalue); - BUGMSG(D_INIT_REASONS, "S3: "); + BUGMSG2(D_INIT_REASONS, "S3: "); BUGLVL(D_INIT_REASONS) numprint = 0; *shmem = shmems[numshmems - 1]; numshmems--; @@ -238,20 +238,20 @@ int __init com90xx_probe(struct net_device *dev) isa_writeb(0x42, ptr); if (isa_readb(ptr) != 0x42) { BUGMSG2(D_INIT_REASONS, "(read only)\n"); - BUGMSG(D_INIT_REASONS, "S3: "); + BUGMSG2(D_INIT_REASONS, "S3: "); *shmem = shmems[numshmems - 1]; numshmems--; shmem--; continue; } BUGMSG2(D_INIT_REASONS, "\n"); - BUGMSG(D_INIT_REASONS, "S3: "); + BUGMSG2(D_INIT_REASONS, "S3: "); BUGLVL(D_INIT_REASONS) numprint = 0; } BUGMSG2(D_INIT, "\n"); if (!numshmems) { - BUGMSG(D_NORMAL, "S3: No ARCnet cards found.\n"); + BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n"); return -ENODEV; } /* Stage 4: something of a dummy, to report the shmems that are @@ -263,7 +263,7 @@ int __init com90xx_probe(struct net_device *dev) numprint %= 8; if (!numprint) { BUGMSG2(D_INIT, "\n"); - BUGMSG(D_INIT, "S4: "); + BUGMSG2(D_INIT, "S4: "); } BUGMSG2(D_INIT, "%lXh ", *shmem); } @@ -282,7 +282,7 @@ int __init com90xx_probe(struct net_device *dev) numprint %= 8; if (!numprint) { BUGMSG2(D_INIT, "\n"); - BUGMSG(D_INIT, "S5: "); + BUGMSG2(D_INIT, "S5: "); } BUGMSG2(D_INIT, "%Xh ", *port); @@ -292,7 +292,7 @@ int __init com90xx_probe(struct net_device *dev) if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status); - BUGMSG(D_INIT_REASONS, "S5: "); + BUGMSG2(D_INIT_REASONS, "S5: "); BUGLVL(D_INIT_REASONS) numprint = 0; *port = ports[numports - 1]; numports--; @@ -304,7 +304,7 @@ int __init com90xx_probe(struct net_device *dev) if (status & RESETflag) { BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n", status); - BUGMSG(D_INIT_REASONS, "S5: "); + BUGMSG2(D_INIT_REASONS, "S5: "); BUGLVL(D_INIT_REASONS) numprint = 0; *port = ports[numports - 1]; numports--; @@ -327,7 +327,7 @@ int __init com90xx_probe(struct net_device *dev) if (airq <= 0) { BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq); - BUGMSG(D_INIT_REASONS, "S5: "); + BUGMSG2(D_INIT_REASONS, "S5: "); BUGLVL(D_INIT_REASONS) numprint = 0; *port = ports[numports - 1]; numports--; @@ -398,7 +398,7 @@ int __init com90xx_probe(struct net_device *dev) isa_writeb(TESTvalue, *shmem); if (retval && dev && !numcards) - BUGMSG(D_NORMAL, "S5: No ARCnet cards found.\n"); + BUGMSG2(D_NORMAL, "S5: No ARCnet cards found.\n"); return retval; } @@ -416,7 +416,7 @@ static int __init com90xx_found(struct net_device *dev0, int ioaddr, int airq, /* allocate struct net_device if we don't have one yet */ if (!dev && !(dev = dev_alloc("arc%d", &err))) { - BUGMSG(D_NORMAL, "Can't allocate device!\n"); + BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n"); return err; } lp = dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); @@ -546,8 +546,7 @@ int com90xx_reset(struct net_device *dev, int really_reset) struct arcnet_local *lp = (struct arcnet_local *) dev->priv; short ioaddr = dev->base_addr; - BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", - dev->name, ASTATUS()); + BUGMSG(D_INIT, "Resetting (status=%02Xh)\n", ASTATUS()); if (really_reset) { /* reset the card */ @@ -653,13 +652,11 @@ void cleanup_module(void) dev = cards[count]; lp = (struct arcnet_local *) dev->priv; - if (dev->start) - dev->stop(dev); + unregister_netdev(dev); free_irq(dev->irq, dev); iounmap(lp->mem_start); release_region(dev->base_addr, ARCNET_TOTAL_SIZE); release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); - unregister_netdev(dev); kfree(dev->priv); kfree(dev); } diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index 759263ca04be..92d026ec8073 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -171,7 +171,7 @@ static void rx(struct net_device *dev, int bufnum, BUGMSG(D_EXTRA, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n", in->sequence, soft->split_flag, soft->sequence); lp->rfc1201.aborted_seq = soft->sequence; - kfree_skb(in->skb); + dev_kfree_skb_irq(in->skb); lp->stats.rx_errors++; lp->stats.rx_missed_errors++; in->skb = NULL; @@ -255,7 +255,7 @@ static void rx(struct net_device *dev, int bufnum, BUGMSG(D_EXTRA, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n", saddr, in->sequence, soft->sequence, soft->split_flag); - kfree_skb(in->skb); + dev_kfree_skb_irq(in->skb); in->skb = NULL; lp->stats.rx_errors++; lp->stats.rx_missed_errors++; @@ -271,7 +271,7 @@ static void rx(struct net_device *dev, int bufnum, soft->sequence); lp->stats.rx_errors++; lp->stats.rx_missed_errors++; - kfree_skb(in->skb); + dev_kfree_skb_irq(in->skb); } in->sequence = soft->sequence; in->numpackets = ((unsigned) soft->split_flag >> 1) + 2; @@ -332,7 +332,7 @@ static void rx(struct net_device *dev, int bufnum, "(seq=%d) aborted (splitflag=%d, seq=%d)\n", in->sequence, soft->split_flag, soft->sequence); lp->rfc1201.aborted_seq = soft->sequence; - kfree_skb(in->skb); + dev_kfree_skb_irq(in->skb); in->skb = NULL; lp->stats.rx_errors++; lp->stats.rx_missed_errors++; diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 30aa851b86c4..1c297dbec58e 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -65,6 +65,7 @@ struct bmac_data { volatile struct dbdma_cmd *tx_cmds; /* xmit dma command list */ volatile struct dbdma_cmd *rx_cmds; /* recv dma command list */ struct device_node *node; + int is_bmac_plus; struct sk_buff *rx_bufs[N_RX_RING]; int rx_fill; int rx_empty; @@ -80,6 +81,7 @@ struct bmac_data { int tx_allocated; unsigned short hash_use_count[64]; unsigned short hash_table_mask[4]; + struct net_device *next_bmac; }; typedef struct bmac_reg_entry { @@ -124,7 +126,6 @@ bmac_reg_entry_t reg_entries[N_REG_ENTRIES] = { }; struct net_device *bmac_devs = NULL; -static int is_bmac_plus; #ifdef CONFIG_PMAC_PBOOK int bmac_sleep_notify(struct pmu_sleep_notifier *self, int when); @@ -133,13 +134,6 @@ static struct pmu_sleep_notifier bmac_sleep_notifier = { }; #endif -#if 0 -/* - * If we can't get a skbuff when we need it, we use this area for DMA. - */ -static unsigned char dummy_buf[RX_BUFLEN]; -#endif - /* * Number of bytes of private data per BMAC: allow enough for * the rx and tx dma commands plus a branch dma command each, @@ -151,6 +145,7 @@ static unsigned char dummy_buf[RX_BUFLEN]; + sizeof(struct sk_buff_head)) static unsigned char bitrev(unsigned char b); +static void bmac_probe1(struct device_node *bmac, int is_bmac_plus); static int bmac_open(struct net_device *dev); static int bmac_close(struct net_device *dev); static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev); @@ -192,9 +187,10 @@ dbdma_ld32(volatile unsigned long *a) void dbdma_stop(volatile struct dbdma_regs *dmap) { - dbdma_st32((volatile unsigned long *)&dmap->control, DBDMA_CLEAR(RUN) | DBDMA_SET(FLUSH)); + dbdma_st32((volatile unsigned long *)&dmap->control, + DBDMA_CLEAR(RUN) | DBDMA_SET(FLUSH)); eieio(); - + while (dbdma_ld32((volatile unsigned long *)&dmap->status) & (ACTIVE|FLUSH)) eieio(); } @@ -210,10 +206,11 @@ dbdma_continue(volatile struct dbdma_regs *dmap) static void dbdma_reset(volatile struct dbdma_regs *dmap) { - dbdma_st32((volatile unsigned long *)&dmap->control, - DBDMA_CLEAR(ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)); + dbdma_st32((volatile unsigned long *)&dmap->control, + DBDMA_CLEAR(ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)); eieio(); - while (dbdma_ld32((volatile unsigned long *)&dmap->status) & RUN) eieio(); + while (dbdma_ld32((volatile unsigned long *)&dmap->status) & RUN) + eieio(); } static void @@ -239,7 +236,7 @@ void bmwrite(struct net_device *dev, unsigned long reg_offset, unsigned data ) static __inline__ volatile unsigned short bmread(struct net_device *dev, unsigned long reg_offset ) { - return in_le16((void *)dev->base_addr + reg_offset); + return in_le16((void *)dev->base_addr + reg_offset); } static void @@ -248,7 +245,7 @@ bmac_reset_chip(struct net_device *dev) struct bmac_data *bp = (struct bmac_data *) dev->priv; volatile struct dbdma_regs *rd = bp->rx_dma; volatile struct dbdma_regs *td = bp->tx_dma; - + dbdma_reset(rd); dbdma_reset(td); @@ -349,7 +346,7 @@ bmac_init_registers(struct net_device *dev) regValue = bmread(dev, TXRST); /* wait for reset to clear..acknowledge */ } while ((regValue & TxResetBit) && i > 0); - if (!is_bmac_plus) { + if (!bp->is_bmac_plus) { regValue = bmread(dev, XCVRIF); regValue |= ClkBit | SerialMode | COLActiveLow; bmwrite(dev, XCVRIF, regValue); @@ -385,7 +382,7 @@ bmac_init_registers(struct net_device *dev) /* set rx fifo information */ bmwrite(dev, RXFIFOCSR, 0); /* first disable rxFIFO */ - bmwrite(dev, RXFIFOCSR, RxFIFOEnable ); + bmwrite(dev, RXFIFOCSR, RxFIFOEnable ); //bmwrite(dev, TXCFG, TxMACEnable); /* TxNeverGiveUp maybe later */ bmread(dev, STATUS); /* read it just to clear it */ @@ -433,13 +430,13 @@ bmac_start_chip(struct net_device *dev) /* enable rx dma channel */ dbdma_continue(rd); - + oldConfig = bmread(dev, TXCFG); - bmwrite(dev, TXCFG, oldConfig | TxMACEnable ); - + bmwrite(dev, TXCFG, oldConfig | TxMACEnable ); + /* turn on rx plus any other bits already on (promiscuous possibly) */ oldConfig = bmread(dev, RXCFG); - bmwrite(dev, RXCFG, oldConfig | RxMACEnable ); + bmwrite(dev, RXCFG, oldConfig | RxMACEnable ); udelay(20000); } @@ -447,6 +444,7 @@ static void bmac_init_phy(struct net_device *dev) { unsigned int addr; + struct bmac_data *bp = (struct bmac_data *) dev->priv; printk(KERN_DEBUG "phy registers:"); for (addr = 0; addr < 32; ++addr) { @@ -455,7 +453,7 @@ bmac_init_phy(struct net_device *dev) printk(" %.4x", bmac_mif_read(dev, addr)); } printk("\n"); - if (is_bmac_plus) { + if (bp->is_bmac_plus) { unsigned int capable, ctrl; ctrl = bmac_mif_read(dev, 0); @@ -622,7 +620,8 @@ bmac_init_rx_ring(struct bmac_data *bp) if (!bp->rx_allocated) { for (i = 0; i < N_RX_RING; i++) { bp->rx_bufs[i] = dev_alloc_skb(RX_BUFLEN+2); - if (bp->rx_bufs[i] == NULL) return 0; + if (bp->rx_bufs[i] == NULL) + return 0; skb_reserve(bp->rx_bufs[i], 2); } bp->rx_allocated = 1; @@ -657,9 +656,10 @@ static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev) /* XXDEBUG(("bmac_xmit_start: empty=%d fill=%d\n", */ /* bp->tx_empty, bp->tx_fill)); */ i = bp->tx_fill + 1; - if (i >= N_TX_RING) i = 0; + if (i >= N_TX_RING) + i = 0; if (i == bp->tx_empty) { - dev->tbusy = 1; + netif_stop_queue(dev); bp->tx_fullup = 1; XXDEBUG(("bmac_transmit_packet: tx ring full\n")); return -1; /* can't take it at the moment */ @@ -776,16 +776,15 @@ static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs) if (bp->tx_bufs[bp->tx_empty]) { ++bp->stats.tx_packets; - dev_kfree_skb(bp->tx_bufs[bp->tx_empty]); + dev_kfree_skb_irq(bp->tx_bufs[bp->tx_empty]); } bp->tx_bufs[bp->tx_empty] = NULL; bp->tx_fullup = 0; - dev->tbusy = 0; - /* XXDEBUG(("bmac_intr: cleared tbusy, empty=%d fill=%d\n", */ - /* i, bp->tx_fill)); */ - mark_bh(NET_BH); - if (++bp->tx_empty >= N_TX_RING) bp->tx_empty = 0; - if (bp->tx_empty == bp->tx_fill) break; + netif_wake_queue(dev); + if (++bp->tx_empty >= N_TX_RING) + bp->tx_empty = 0; + if (bp->tx_empty == bp->tx_fill) + break; } restore_flags(flags); @@ -831,7 +830,7 @@ crc416(unsigned int curval, unsigned short nxtval) /* is high CRC bit set? */ if ((cur & 0x80000000) == 0) high_crc_set = 0; else high_crc_set = 1; - + cur = cur << 1; if ((next & 0x0001) == 0) low_data_set = 0; @@ -859,8 +858,8 @@ bmac_crc(unsigned short *address) } /* - * Add requested mcast addr to BMac's hash table filter. - * + * Add requested mcast addr to BMac's hash table filter. + * */ static void @@ -925,7 +924,7 @@ bmac_rx_on(struct net_device *dev, int hash_enable, int promisc_enable) else rx_cfg &= ~RxPromiscEnable; bmwrite(dev, RXRST, RxResetValue); bmwrite(dev, RXFIFOCSR, 0); /* first disable rxFIFO */ - bmwrite(dev, RXFIFOCSR, RxFIFOEnable ); + bmwrite(dev, RXFIFOCSR, RxFIFOEnable ); bmwrite(dev, RXCFG, rx_cfg ); return rx_cfg; } @@ -1020,13 +1019,7 @@ static void bmac_set_multicast(struct net_device *dev) int i, j, bit, byte; unsigned short rx_cfg; u32 crc, poly = CRC_POLYNOMIAL_LE; - - /* Let the transmits drain. */ - /* while(dev->tbusy) schedule(); */ - - /* Lock out others. */ - /* set_bit(0, (void *) &dev->tbusy); */ - + if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { bmwrite(dev, BHASH0, 0xffff); bmwrite(dev, BHASH1, 0xffff); @@ -1048,15 +1041,15 @@ static void bmac_set_multicast(struct net_device *dev) for(i = 0; i < dev->mc_count; i++) { addrs = dmi->dmi_addr; dmi = dmi->next; - + if(!(*addrs & 1)) continue; - + crc = 0xffffffffU; for(byte = 0; byte < 6; byte++) { for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { int test; - + test = ((bit ^ crc) & 0x01); crc >>= 1; if(test) @@ -1071,9 +1064,6 @@ static void bmac_set_multicast(struct net_device *dev) bmwrite(dev, BHASH2, hash_table[2]); bmwrite(dev, BHASH3, hash_table[3]); } - - /* Let us get going again. */ - /* dev->tbusy = 0; */ } #endif /* SUNHME_MULTICAST */ @@ -1103,7 +1093,7 @@ static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs) } /* - * Procedure for reading EEPROM + * Procedure for reading EEPROM */ #define SROMAddressLength 5 #define DataInOn 0x0008 @@ -1126,28 +1116,28 @@ bmac_clock_out_bit(struct net_device *dev) bmwrite(dev, SROMCSR, ChipSelect | Clk); udelay(DelayValue); - + data = bmread(dev, SROMCSR); udelay(DelayValue); val = (data >> SD0ShiftCount) & 1; bmwrite(dev, SROMCSR, ChipSelect); udelay(DelayValue); - + return val; } static void bmac_clock_in_bit(struct net_device *dev, unsigned int val) { - unsigned short data; + unsigned short data; if (val != 0 && val != 1) return; - + data = (val << SDIShiftCount); bmwrite(dev, SROMCSR, data | ChipSelect ); udelay(DelayValue); - + bmwrite(dev, SROMCSR, data | ChipSelect | Clk ); udelay(DelayValue); @@ -1161,7 +1151,7 @@ reset_and_select_srom(struct net_device *dev) /* first reset */ bmwrite(dev, SROMCSR, 0); udelay(DelayValue); - + /* send it the read command (110) */ bmac_clock_in_bit(dev, 1); bmac_clock_in_bit(dev, 1); @@ -1173,13 +1163,13 @@ read_srom(struct net_device *dev, unsigned int addr, unsigned int addr_len) { unsigned short data, val; int i; - + /* send out the address we want to read from */ for (i = 0; i < addr_len; i++) { val = addr >> (addr_len-i-1); bmac_clock_in_bit(dev, val & 1); } - + /* Now read in the 16-bit data */ data = 0; for (i = 0; i < 16; i++) { @@ -1188,24 +1178,24 @@ read_srom(struct net_device *dev, unsigned int addr, unsigned int addr_len) data |= val; } bmwrite(dev, SROMCSR, 0); - + return data; } /* * It looks like Cogent and SMC use different methods for calculating - * checksums. What a pain.. + * checksums. What a pain.. */ static int bmac_verify_checksum(struct net_device *dev) { unsigned short data, storedCS; - + reset_and_select_srom(dev); data = read_srom(dev, 3, SROMAddressBits); storedCS = ((data >> 8) & 0x0ff) | ((data << 8) & 0xff00); - + return 0; } @@ -1236,8 +1226,10 @@ static int bmac_reset_and_enable(struct net_device *dev, int enable) bp->reset_and_enabled = 0; bmac_reset_chip(dev); if (enable) { - if (!bmac_init_tx_ring(bp) || !bmac_init_rx_ring(bp)) return 0; - if (!bmac_init_chip(dev)) return 0; + if (!bmac_init_tx_ring(bp) || !bmac_init_rx_ring(bp)) + return 0; + if (!bmac_init_chip(dev)) + return 0; bmac_start_chip(dev); bmwrite(dev, INTDISABLE, EnableNormal); bp->reset_and_enabled = 1; @@ -1257,70 +1249,55 @@ static int bmac_reset_and_enable(struct net_device *dev, int enable) return 1; } -static int __init bmac_probe (void) +static int __init bmac_probe(void) { - int j, rev; - struct bmac_data *bp; - struct device_node *bmacs; - unsigned char *addr; - static struct device_node *all_bmacs = NULL, *next_bmac; - struct net_device *dev = NULL; + struct device_node *bmac; -#ifdef MODULE - if(bmac_devs != NULL) - return -EBUSY; -#endif - - if (all_bmacs == NULL) { - all_bmacs = find_devices("bmac"); - is_bmac_plus = 0; - if (all_bmacs == NULL) { - all_bmacs = find_compatible_devices("network", "bmac+"); - if (all_bmacs) - is_bmac_plus = 1; - } - next_bmac = all_bmacs; - } - bmacs = next_bmac; - if (bmacs == NULL) return -ENODEV; - next_bmac = bmacs->next; + for (bmac = find_devices("bmac"); bmac != 0; bmac = bmac->next) + bmac_probe1(bmac, 0); + for (bmac = find_compatible_devices("network", "bmac+"); bmac != 0; + bmac = bmac->next) + bmac_probe1(bmac, 1); - if (bmac_devs == 0) { - bmac_devs = dev; /* KLUDGE!! */ + if (bmac_devs != 0) { + proc_net_create ("bmac", 0, bmac_proc_info); #ifdef CONFIG_PMAC_PBOOK pmu_register_sleep_notifier(&bmac_sleep_notifier); #endif } + return 0; +} - if (bmacs->n_addrs != 3 || bmacs->n_intrs != 3) { - printk(KERN_ERR "can't use BMAC %s: expect 3 addrs and 3 intrs\n", - bmacs->full_name); - return -EINVAL; +static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) +{ + int j, rev; + struct bmac_data *bp; + unsigned char *addr; + struct net_device *dev; + + if (bmac->n_addrs != 3 || bmac->n_intrs != 3) { + printk(KERN_ERR "can't use BMAC %s: need 3 addrs and 3 intrs\n", + bmac->full_name); + return; + } + addr = get_property(bmac, "mac-address", NULL); + if (addr == NULL) { + addr = get_property(bmac, "local-mac-address", NULL); + if (addr == NULL) { + printk(KERN_ERR "Can't get mac-address for BMAC %s\n", + bmac->full_name); + return; + } } dev = init_etherdev(NULL, PRIV_BYTES); - bmac_devs = dev; /*KLUDGE!!*/ -#ifdef MODULE - bmac_devs = dev; -#endif - dev->base_addr = (unsigned long) - ioremap(bmacs->addrs[0].address, bmacs->addrs[0].size); - dev->irq = bmacs->intrs[0].line; + ioremap(bmac->addrs[0].address, bmac->addrs[0].size); + dev->irq = bmac->intrs[0].line; bmwrite(dev, INTDISABLE, DisableAll); - - addr = get_property(bmacs, "mac-address", NULL); - if (addr == NULL) { - addr = get_property(bmacs, "local-mac-address", NULL); - if (addr == NULL) { - printk(KERN_ERR "Can't get mac-address for BMAC at %lx\n", - dev->base_addr); - return -EAGAIN; - } - } - + printk(KERN_INFO "%s: BMAC%s at", dev->name, (is_bmac_plus? "+": "")); rev = addr[0] == 0 && addr[1] == 0xA0; for (j = 0; j < 6; ++j) { @@ -1329,7 +1306,7 @@ static int __init bmac_probe (void) } XXDEBUG((", base_addr=%#0lx", dev->base_addr)); printk("\n"); - + dev->open = bmac_open; dev->stop = bmac_close; dev->hard_start_xmit = bmac_output; @@ -1338,61 +1315,55 @@ static int __init bmac_probe (void) dev->set_mac_address = bmac_set_address; bmac_get_station_address(dev, addr); - if (bmac_verify_checksum(dev) != 0) return -EINVAL; - + if (bmac_verify_checksum(dev) != 0) + return; + ether_setup(dev); - + bp = (struct bmac_data *) dev->priv; memset(bp, 0, sizeof(struct bmac_data)); + bp->is_bmac_plus = is_bmac_plus; bp->tx_dma = (volatile struct dbdma_regs *) - ioremap(bmacs->addrs[1].address, bmacs->addrs[1].size); - bp->tx_dma_intr = bmacs->intrs[1].line; + ioremap(bmac->addrs[1].address, bmac->addrs[1].size); + bp->tx_dma_intr = bmac->intrs[1].line; bp->rx_dma = (volatile struct dbdma_regs *) - ioremap(bmacs->addrs[2].address, bmacs->addrs[2].size); - bp->rx_dma_intr = bmacs->intrs[2].line; - + ioremap(bmac->addrs[2].address, bmac->addrs[2].size); + bp->rx_dma_intr = bmac->intrs[2].line; + bp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(bp + 1); bp->rx_cmds = bp->tx_cmds + N_TX_RING + 1; bp->queue = (struct sk_buff_head *)(bp->rx_cmds + N_RX_RING + 1); skb_queue_head_init(bp->queue); - - bp->node = bmacs; + + bp->node = bmac; memset(&bp->stats, 0, sizeof(bp->stats)); memset((char *) bp->tx_cmds, 0, (N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd)); /* init_timer(&bp->tx_timeout); */ /* bp->timeout_active = 0; */ - if (request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev)) { + if (request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev)) printk(KERN_ERR "BMAC: can't get irq %d\n", dev->irq); - return -EAGAIN; - } - if (request_irq(bmacs->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma", - dev)) { - printk(KERN_ERR "BMAC: can't get irq %d\n", bmacs->intrs[1].line); - return -EAGAIN; - } - if (request_irq(bmacs->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma", - dev)) { - printk(KERN_ERR "BMAC: can't get irq %d\n", bmacs->intrs[2].line); - return -EAGAIN; - } - - if (!bmac_reset_and_enable(dev, 0)) return -ENOMEM; - - proc_net_create ("bmac", 0, bmac_proc_info); - - return 0; + if (request_irq(bmac->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma", + dev)) + printk(KERN_ERR "BMAC: can't get irq %d\n", bmac->intrs[1].line); + if (request_irq(bmac->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma", + dev)) + printk(KERN_ERR "BMAC: can't get irq %d\n", bmac->intrs[2].line); + + bp->next_bmac = bmac_devs; + bmac_devs = dev; } static int bmac_open(struct net_device *dev) { /* XXDEBUG(("bmac: enter open\n")); */ /* reset the chip */ - bmac_reset_and_enable(dev, 1); + if (!bmac_reset_and_enable(dev, 1)) + return -ENOMEM; - dev->flags |= IFF_UP | IFF_RUNNING; + dev->flags |= IFF_RUNNING; MOD_INC_USE_COUNT; return 0; @@ -1452,14 +1423,17 @@ bmac_start(struct net_device *dev) int i; struct sk_buff *skb; unsigned long flags; - + save_flags(flags); cli(); while (1) { i = bp->tx_fill + 1; - if (i >= N_TX_RING) i = 0; - if (i == bp->tx_empty) break; + if (i >= N_TX_RING) + i = 0; + if (i == bp->tx_empty) + break; skb = skb_dequeue(bp->queue); - if (skb == NULL) break; + if (skb == NULL) + break; bmac_transmit_packet(skb, dev); } restore_flags(flags); @@ -1525,9 +1499,7 @@ static void bmac_tx_timeout(unsigned long data) bp->tx_empty = i; } bp->tx_fullup = 0; - dev->tbusy = 0; - mark_bh(NET_BH); - XXDEBUG((KERN_DEBUG "bmac: clearing tbusy\n")); + netif_wake_queue(dev); if (i != bp->tx_fill) { cp = &bp->tx_cmds[i]; out_le16(&cp->xfer_status, 0); @@ -1540,9 +1512,9 @@ static void bmac_tx_timeout(unsigned long data) /* turn it back on */ oldConfig = bmread(dev, RXCFG); - bmwrite(dev, RXCFG, oldConfig | RxMACEnable ); + bmwrite(dev, RXCFG, oldConfig | RxMACEnable ); oldConfig = bmread(dev, TXCFG); - bmwrite(dev, TXCFG, oldConfig | TxMACEnable ); + bmwrite(dev, TXCFG, oldConfig | TxMACEnable ); restore_flags(flags); } @@ -1573,7 +1545,8 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length) off_t begin = 0; int i; - if (bmac_devs == NULL) return (-ENOSYS); + if (bmac_devs == NULL) + return (-ENOSYS); len += sprintf(buffer, "BMAC counters & registers\n"); @@ -1582,20 +1555,20 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length) reg_entries[i].name, bmread(bmac_devs, reg_entries[i].reg_offset)); pos = begin + len; - + if (pos < offset) { len = 0; begin = pos; } - + if (pos > offset+length) break; } - + *start = buffer + (offset - begin); len -= (offset - begin); - + if (len > length) len = length; - + return len; } @@ -1606,26 +1579,28 @@ MODULE_DESCRIPTION("PowerMac BMAC ethernet driver."); static void __exit bmac_cleanup (void) { -#ifdef MODULE - struct bmac_data *bp; + struct bmac_data *bp; + struct net_device *dev; - if (bmac_devs == 0) - return; + if (bmac_devs == 0) + return; +#ifdef CONFIG_PMAC_PBOOK + pmu_unregister_sleep_notifier(&bmac_sleep_notifier); +#endif + proc_net_remove("bmac"); - bp = (struct bmac_data *) bmac_devs->priv; - unregister_netdev(bmac_devs); - proc_net_remove("bmac"); + do { + dev = bmac_devs; + bp = (struct bmac_data *) dev->priv; + bmac_devs = bp->next_bmac; - free_irq(bmac_devs->irq, bmac_misc_intr); - free_irq(bp->tx_dma_intr, bmac_txdma_intr); - free_irq(bp->rx_dma_intr, bmac_rxdma_intr); + free_irq(dev->irq, dev); + free_irq(bp->tx_dma_intr, dev); + free_irq(bp->rx_dma_intr, dev); -#ifdef CONFIG_PMAC_PBOOK - pmu_unregister_sleep_notifier(&bmac_sleep_notifier); -#endif - kfree(bmac_devs); - bmac_devs = NULL; -#endif + unregister_netdev(dev); + kfree(dev); + } while (bmac_devs != NULL); } module_init(bmac_probe); diff --git a/drivers/net/de4x5.c b/drivers/net/de4x5.c index 8c997b3c2c66..a565d9eb8ef4 100644 --- a/drivers/net/de4x5.c +++ b/drivers/net/de4x5.c @@ -1761,7 +1761,7 @@ de4x5_free_tx_buff(struct de4x5_private *lp, int entry) pci_unmap_single(lp->pdev, le32_to_cpu(lp->tx_ring[entry].buf), le32_to_cpu(lp->tx_ring[entry].des1) & TD_TBS1); if ((u_long) lp->tx_skb[entry] > 1) - dev_kfree_skb(lp->tx_skb[entry]); + dev_kfree_skb_irq(lp->tx_skb[entry]); lp->tx_skb[entry] = NULL; } diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index e651be8a8dda..63b5405007f6 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -73,10 +73,6 @@ static int debug = -1; /* The debug level */ #include #include -#ifdef MODVERSIONS -#include -#endif - #include #include #include @@ -84,14 +80,7 @@ static int debug = -1; /* The debug level */ #include #include #include -#ifdef HAS_PCI_NETIF -#include "pci-netif.h" -#else #include -#if LINUX_VERSION_CODE < 0x20155 -#include /* Ignore the bogus warning in 2.1.100+ */ -#endif -#endif #include #include #include @@ -118,26 +107,6 @@ MODULE_PARM(multicast_filter_limit, "i"); #define RUN_AT(x) (jiffies + (x)) -#if (LINUX_VERSION_CODE < 0x20123) -#define test_and_set_bit(val, addr) set_bit(val, addr) -#define le16_to_cpu(val) (val) -#define cpu_to_le16(val) (val) -#define le32_to_cpu(val) (val) -#define cpu_to_le32(val) (val) -#define spin_lock_irqsave(&sp->lock, flags) save_flags(flags); cli(); -#define spin_unlock_irqrestore(&sp->lock, flags); restore_flags(flags); -#endif -#if LINUX_VERSION_CODE < 0x20159 -#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE); -#else -#define dev_free_skb(skb) dev_kfree_skb(skb); -#endif -#if ! defined(CAP_NET_ADMIN) -#define capable(CAP_XXX) (suser()) -#endif -#if ! defined(HAS_NETIF_QUEUE) -#define netif_wake_queue(dev) mark_bh(NET_BH); -#endif /* The total I/O port extent of the board. The registers beyond 0x18 only exist on the i82558. */ @@ -278,7 +247,8 @@ having to sign an Intel NDA when I'm helping Intel sell their own product! */ /* This table drives the PCI probe routines. */ -static struct net_device *speedo_found1(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt); +static struct net_device *speedo_found1(struct pci_dev *pdev, long ioaddr, + int irq, int chip_idx, int fnd_cnt); #ifdef USE_IO #define SPEEDO_IOTYPE PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR1 @@ -288,14 +258,6 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn, long ioaddr, #define SPEEDO_SIZE 0x1000 #endif -#if defined(HAS_PCI_NETIF) -struct pci_id_info static pci_tbl[] = { - { "Intel PCI EtherExpress Pro100", - { 0x12298086, 0xffffffff,}, SPEEDO_IOTYPE, SPEEDO_SIZE, - 0, speedo_found1 }, - {0,}, /* 0 terminated list. */ -}; -#else enum pci_flags_bit { PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, @@ -304,13 +266,12 @@ struct pci_id_info { const char *name; u16 vendor_id, device_id, device_id_mask, flags; int io_size; - struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt); + struct net_device *(*probe1)(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt); } static pci_tbl[] = { { "Intel PCI EtherExpress Pro100", 0x8086, 0x1229, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 32, speedo_found1 }, {0,}, /* 0 terminated list. */ }; -#endif #ifndef USE_IO #define inb readb @@ -456,7 +417,7 @@ struct speedo_private { struct enet_statistics stats; struct speedo_stats *lstats; int chip_id; - unsigned char pci_bus, pci_devfn, acpi_pwr; + unsigned char acpi_pwr; struct pci_dev *pdev; struct timer_list timer; /* Media selection timer. */ int mc_setup_frm_len; /* The length of an allocated.. */ @@ -529,65 +490,39 @@ static int mii_ctrl[8] = { 0x3300, 0x3100, 0x0000, 0x0100, /* A list of all installed Speedo devices, for removing the driver module. */ static struct net_device *root_speedo_dev = NULL; -#if ! defined(HAS_PCI_NETIF) -int eepro100_init(void) +static int __init eepro100_init (void) { int cards_found = 0; - static int pci_index = 0; - - if (! pcibios_present()) - return cards_found; - - for (; pci_index < 8; pci_index++) { - unsigned char pci_bus, pci_device_fn, pci_latency; - long ioaddr; - int irq; - - u16 pci_command, new_command; + struct pci_dev *pdev = NULL; + long ioaddr; + int irq; - if (pcibios_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82557, - pci_index, &pci_bus, - &pci_device_fn)) - break; -#if LINUX_VERSION_CODE >= 0x20155 || PCI_SUPPORT_1 - { - struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); + while ((pdev = pci_find_device (PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82557, pdev))) { #ifdef USE_IO - ioaddr = pdev->resource[1].start; + ioaddr = pdev->resource[1].start; #else - ioaddr = pdev->resource[0].start; -#endif - irq = pdev->irq; - } -#else - { - u32 pciaddr; - u8 pci_irq_line; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); - /* Note: BASE_ADDRESS_0 is for memory-mapping the registers. */ -#ifdef USE_IO - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pciaddr); - pciaddr &= ~3UL; -#else - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pciaddr); -#endif - ioaddr = pciaddr; - irq = pci_irq_line; - } + ioaddr = pdev->resource[0].start; #endif + irq = pdev->irq; + /* Remove I/O space marker in bit 0. */ #ifdef USE_IO - if (check_region(ioaddr, 32)) + if (check_region(ioaddr, 32)) { + printk(KERN_ERR "eepro100: %ld mem region busy\n", ioaddr); continue; + } #else { unsigned long orig_ioaddr = ioaddr; + + if (check_mem_region(ioaddr, 32)) { + printk(KERN_ERR "eepro100: %ld mem region busy\n", + ioaddr); + continue; + } - if ((ioaddr = (long)ioremap(ioaddr & ~0xfUL, 0x1000)) == 0) { + if ((ioaddr = (long)ioremap(orig_ioaddr, 0x1000)) == 0) { printk(KERN_INFO "Failed to map PCI address %#lx.\n", orig_ioaddr); continue; @@ -598,54 +533,30 @@ int eepro100_init(void) printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n", ioaddr, irq); - /* Get and check the bus-master and latency values. */ - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); - new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; - if (pci_command != new_command) { - printk(KERN_INFO " The PCI BIOS has not enabled this" - " device! Updating PCI command %4.4x->%4.4x.\n", - pci_command, new_command); - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, new_command); - } - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, &pci_latency); - if (pci_latency < 32) { - printk(" PCI latency timer (CFLT) is unreasonably low at %d." - " Setting to 32 clocks.\n", pci_latency); - pcibios_write_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, 32); - } else if (speedo_debug > 1) - printk(" PCI latency timer (CFLT) is %#x.\n", pci_latency); - - if(speedo_found1(pci_bus, pci_device_fn, ioaddr, irq, 0,cards_found)) + if(speedo_found1(pdev, ioaddr, irq, 0,cards_found)) cards_found++; } return cards_found; } -#endif -static struct net_device *speedo_found1(int pci_bus, int pci_devfn, + +static struct net_device *speedo_found1(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int card_idx) { struct net_device *dev; struct speedo_private *sp; - struct pci_dev *pdev; unsigned char *tx_ring; dma_addr_t tx_ring_dma; const char *product; int i, option; u16 eeprom[0x100]; - int acpi_idle_state = 0; + int acpi_idle_state = 0, pm; static int did_version = 0; /* Already printed version info. */ if (speedo_debug > 0 && did_version++ == 0) printk(version); - pdev = pci_find_slot(pci_bus, pci_devfn); - tx_ring = pci_alloc_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD) + sizeof(struct speedo_stats), &tx_ring_dma); if (!tx_ring) { @@ -668,9 +579,16 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn, else option = 0; -#if defined(HAS_PCI_NETIF) - acpi_idle_state = acpi_set_pwr_state(pci_bus, pci_devfn, ACPI_D0); -#endif + /* save power state b4 pci_enable_device overwrites it */ + pm = pci_find_capability(pdev, PCI_CAP_ID_PM); + if (pm) { + u16 pwr_command; + pci_read_config_word(pdev, pm + PCI_PM_CTRL, &pwr_command); + acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; + } + + pci_enable_device (pdev); + pci_set_master (pdev); /* Read the station address EEPROM before doing the reset. Nominally his should even be done before accepting the device, but @@ -724,7 +642,7 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn, printk("%2.2X:", dev->dev_addr[i]); printk("%2.2X, IRQ %d.\n", dev->dev_addr[i], irq); -#ifndef kernel_bloat +#if 1 /* OK, this is pure kernel bloat. I don't like it when other drivers waste non-pageable kernel space to emit similar messages, but I need them for bug reports. */ @@ -793,13 +711,15 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn, #endif /* kernel_bloat */ outl(PortReset, ioaddr + SCBPort); -#if defined(HAS_PCI_NETIF) + /* Return the chip to its original power state. */ - acpi_set_pwr_state(pci_bus, pci_devfn, acpi_idle_state); -#endif + pci_set_power_state (pdev, acpi_idle_state); - /* We do a request_region() only to register /proc/ioports info. */ +#ifdef USE_IO request_region(ioaddr, SPEEDO3_TOTAL_SIZE, "Intel Speedo3 Ethernet"); +#else + request_mem_region(ioaddr, 0x1000, "Intel Speedo3 Ethernet"); +#endif dev->base_addr = ioaddr; dev->irq = irq; @@ -814,8 +734,6 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn, sp->next_module = root_speedo_dev; root_speedo_dev = dev; - sp->pci_bus = pci_bus; - sp->pci_devfn = pci_devfn; sp->pdev = pdev; sp->chip_id = chip_idx; sp->acpi_pwr = acpi_idle_state; @@ -925,13 +843,11 @@ speedo_open(struct net_device *dev) struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; -#if defined(HAS_PCI_NETIF) - acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0); -#endif - if (speedo_debug > 1) printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq); + pci_set_power_state(sp->pdev, 0); + /* Set up the Tx queue early.. */ sp->cur_tx = 0; sp->dirty_tx = 0; @@ -940,9 +856,9 @@ speedo_open(struct net_device *dev) spin_lock_init(&sp->lock); /* .. we can safely take handler calls during init. */ - if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) { - return -EAGAIN; - } + if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) + return -EBUSY; + MOD_INC_USE_COUNT; dev->if_port = sp->default_port; @@ -1059,6 +975,8 @@ static void speedo_resume(struct net_device *dev) + (sp->dirty_tx % TX_RING_SIZE) * sizeof(struct TxFD), ioaddr + SCBPointer); outw(CUStart, ioaddr + SCBCmd); + + netif_start_queue (dev); } /* Media monitoring and control. */ @@ -1220,6 +1138,7 @@ static void speedo_tx_timeout(struct net_device *dev) } sp->stats.tx_errors++; dev->trans_start = jiffies; + netif_start_queue (dev); return; } @@ -1230,6 +1149,8 @@ speedo_start_xmit(struct sk_buff *skb, struct net_device *dev) long ioaddr = dev->base_addr; int entry; + netif_stop_queue (dev); + /* Caution: the write order is important here, set the base address with the "ownership" bits last. */ @@ -1270,13 +1191,15 @@ speedo_start_xmit(struct sk_buff *skb, struct net_device *dev) } if (sp->cur_tx - sp->dirty_tx >= TX_QUEUE_LIMIT) { sp->tx_full = 1; - netif_stop_queue(dev); } spin_unlock_irqrestore(&sp->lock, flags); } wait_for_cmd_done(ioaddr + SCBCmd); outw(CUResume, ioaddr + SCBCmd); dev->trans_start = jiffies; + + if (! sp->tx_full) + netif_start_queue (dev); return 0; } @@ -1300,6 +1223,8 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs) ioaddr = dev->base_addr; sp = (struct speedo_private *)dev->priv; + spin_lock (&sp->lock); + do { status = inw(ioaddr + SCBStatus); /* Acknowledge all of the current interrupt sources ASAP. */ @@ -1330,7 +1255,6 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs) /* User interrupt, Command/Tx unit interrupt or CU not active. */ if (status & 0xA400) { unsigned int dirty_tx; - spin_lock(&sp->lock); dirty_tx = sp->dirty_tx; while (sp->cur_tx - dirty_tx > 0) { @@ -1380,10 +1304,12 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs) && sp->cur_tx - dirty_tx < TX_QUEUE_LIMIT - 1) { /* The ring is no longer full, clear tbusy. */ sp->tx_full = 0; - spin_unlock(&sp->lock); - netif_wake_queue(dev); - } else - spin_unlock(&sp->lock); + } + + if (sp->tx_full) + netif_stop_queue (dev); + else + netif_wake_queue (dev); } if (--boguscnt < 0) { @@ -1399,7 +1325,7 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs) printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", dev->name, inw(ioaddr + SCBStatus)); - return; + spin_unlock (&sp->lock); } static int @@ -1546,7 +1472,7 @@ speedo_close(struct net_device *dev) #if LINUX_VERSION_CODE < 0x20100 skb->free = 1; #endif - dev_free_skb(skb); + dev_kfree_skb(skb); } } @@ -1559,7 +1485,7 @@ speedo_close(struct net_device *dev) pci_unmap_single(sp->pdev, le32_to_cpu(sp->tx_ring[i].tx_buf_addr0), skb->len); - dev_free_skb(skb); + dev_kfree_skb(skb); } } if (sp->mc_setup_frm) { @@ -1571,10 +1497,9 @@ speedo_close(struct net_device *dev) if (speedo_debug > 3) speedo_show_state(dev); -#if defined(HAS_PCI_NETIF) /* Alt: acpi_set_pwr_state(pci_bus, pci_devfn, sp->acpi_pwr); */ - acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D2); -#endif + pci_set_power_state (sp->pdev, 2); + MOD_DEC_USE_COUNT; return 0; @@ -1626,32 +1551,22 @@ static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) long ioaddr = dev->base_addr; u16 *data = (u16 *)&rq->ifr_data; int phy = sp->phy[0] & 0x1f; -#if defined(HAS_PCI_NETIF) int saved_acpi; -#endif switch(cmd) { case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ data[0] = phy; case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ -#if defined(HAS_PCI_NETIF) - saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0); - data[3] = mdio_read(ioaddr, data[0], data[1]); - acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi); -#else - data[3] = mdio_read(ioaddr, data[0], data[1]); -#endif + saved_acpi = pci_set_power_state (sp->pdev, 0); + data[3] = mdio_read (ioaddr, data[0], data[1]); + pci_set_power_state (sp->pdev, saved_acpi); return 0; case SIOCDEVPRIVATE+2: /* Write the specified MII register */ if (!capable(CAP_NET_ADMIN)) return -EPERM; -#if defined(HAS_PCI_NETIF) - saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0); + saved_acpi = pci_set_power_state(sp->pdev, 0); mdio_write(ioaddr, data[0], data[1], data[2]); - acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi); -#else - mdio_write(ioaddr, data[0], data[1], data[2]); -#endif + pci_set_power_state(sp->pdev, saved_acpi); return 0; default: return -EOPNOTSUPP; @@ -1846,18 +1761,11 @@ static int __init eepro100_init_module(void) if (speedo_debug) printk(KERN_INFO "%s", version); -#if defined(HAS_PCI_NETIF) - cards_found = netif_pci_probe(pci_tbl); - if (cards_found < 0) - printk(KERN_INFO "eepro100: No cards found, driver not installed.\n"); - return cards_found; -#else cards_found = eepro100_init(); if (cards_found <= 0) { printk(KERN_INFO "eepro100: No cards found, driver not installed.\n"); return -ENODEV; } -#endif return 0; } @@ -1872,11 +1780,10 @@ static void __exit eepro100_cleanup_module(void) #ifdef USE_IO release_region(root_speedo_dev->base_addr, SPEEDO3_TOTAL_SIZE); #else + release_mem_region(root_speedo_dev->base_addr, 0x1000); iounmap((char *)root_speedo_dev->base_addr); #endif -#if defined(HAS_PCI_NETIF) - acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, sp->acpi_pwr); -#endif + pci_set_power_state(sp->pdev, sp->acpi_pwr); next_dev = sp->next_module; if (sp->priv_addr) kfree(sp->priv_addr); diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index c7dfb7a65e20..7d9cd2363cb2 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -79,7 +79,6 @@ MODULE_PARM(options, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(max_interrupt_work, "i"); -#define DEV_FREE_SKB(skb) dev_kfree_skb(skb); /* The I/O extent. */ #define EPIC_TOTAL_SIZE 0x100 @@ -895,7 +894,7 @@ static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs) } /* Free the original skb. */ - DEV_FREE_SKB(ep->tx_skbuff[entry]); + dev_kfree_skb_irq(ep->tx_skbuff[entry]); ep->tx_skbuff[entry] = 0; } @@ -1073,12 +1072,12 @@ static int epic_close(struct net_device *dev) ep->rx_ring[i].buflength = 0; ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */ if (skb) { - DEV_FREE_SKB(skb); + dev_kfree_skb(skb); } } for (i = 0; i < TX_RING_SIZE; i++) { if (ep->tx_skbuff[i]) - DEV_FREE_SKB(ep->tx_skbuff[i]); + dev_kfree_skb(ep->tx_skbuff[i]); ep->tx_skbuff[i] = 0; } @@ -1224,13 +1223,14 @@ static dev_node_t *epic_attach(dev_locator_t *loc) struct net_device *dev; u16 dev_id; u32 io; - u8 bus, devfn, irq; + u8 irq; struct pci_dev *pdev; if (loc->bus != LOC_PCI) return NULL; pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn); if (!pdev) return NULL; - printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", bus, devfn); + printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", + pdev->bus->number, pdev->devfn); io = pdev->resource[0].start; irq = pdev->irq; dev_id = pdev->device; @@ -1241,7 +1241,7 @@ static dev_node_t *epic_attach(dev_locator_t *loc) io == 0 ? "I/O address" : "IRQ"); return NULL; } - dev = epic_probe1(bus, devfn, io, irq, 2, -1); + dev = epic_probe1(pdev, io, irq, 2, -1); if (dev) { dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL); strcpy(node->dev_name, dev->name); diff --git a/drivers/net/gmac.c b/drivers/net/gmac.c index 7ee18bfe90fc..b1a431499f94 100644 --- a/drivers/net/gmac.c +++ b/drivers/net/gmac.c @@ -51,6 +51,7 @@ struct gmac { int phy_addr; int full_duplex; struct net_device_stats stats; + struct net_device *next_gmac; }; #define GM_OUT(r, v) out_le32(gm->regs + (r)/4, (v)) @@ -80,6 +81,7 @@ static void gmac_receive(struct net_device *dev); static void gmac_interrupt(int irq, void *dev_id, struct pt_regs *regs); static struct net_device_stats *gmac_stats(struct net_device *dev); static int gmac_probe(void); +static void gmac_probe1(struct device_node *gmac); /* Stuff for talking to the physical-layer chip */ static int @@ -383,7 +385,7 @@ static int gmac_xmit_start(struct sk_buff *skb, struct net_device *dev) i = gm->next_tx; if (gm->tx_buff[i] != 0) { /* buffer is full, can't send this packet at the moment */ - dev->tbusy = 1; + netif_stop_queue(dev); gm->tx_full = 1; restore_flags(flags); return 1; @@ -421,7 +423,7 @@ static int gmac_tx_cleanup(struct gmac *gm) gm->stats.tx_bytes += skb->len; ++gm->stats.tx_packets; gm->tx_buff[i] = NULL; - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); if (++i >= NTX) i = 0; } @@ -452,7 +454,7 @@ static void gmac_receive(struct net_device *dev) ++gm->stats.rx_dropped; } else if (ld_le32(&dp->status) & 0x40000000) { ++gm->stats.rx_errors; - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); } else { skb_put(skb, len); skb->dev = dev; @@ -486,14 +488,11 @@ static void gmac_interrupt(int irq, void *dev_id, struct pt_regs *regs) status = GM_IN(INTR_STATUS); GM_OUT(INTR_ACK, status); - if (status & GMAC_IRQ_MIF) { + if (status & GMAC_IRQ_MIF) mii_interrupt(gm); - } gmac_receive(dev); - if (gmac_tx_cleanup(gm)){ - dev->tbusy = 0; - mark_bh(NET_BH); - } + if (gmac_tx_cleanup(gm)) + netif_wake_queue(dev); } static struct net_device_stats *gmac_stats(struct net_device *dev) @@ -505,33 +504,44 @@ static struct net_device_stats *gmac_stats(struct net_device *dev) static int __init gmac_probe(void) { - static int gmacs_found; - static struct device_node *next_gmac; struct device_node *gmac; - struct gmac *gm; - unsigned long descpage; - unsigned char *addr; - int i; - - if (gmacs != NULL) - return -EBUSY; /* * We could (and maybe should) do this using PCI scanning * for vendor/net_device ID 0x106b/0x21. */ - if (!gmacs_found) { - next_gmac = find_compatible_devices("network", "gmac"); - gmacs_found = 1; - } - if ((gmac = next_gmac) == 0) - return -ENODEV; - next_gmac = gmac->next; + for (gmac = find_compatible_devices("network", "gmac"); gmac != 0; + gmac = gmac->next) + gmac_probe1(gmac); + + return 0; +} + +static void gmac_probe1(struct device_node *gmac) +{ + struct gmac *gm; + unsigned long descpage; + unsigned char *addr; + struct net_device *dev; + int i; if (gmac->n_addrs < 1 || gmac->n_intrs < 1) { printk(KERN_ERR "can't use GMAC %s: %d addrs and %d intrs\n", gmac->full_name, gmac->n_addrs, gmac->n_intrs); - return -ENODEV; + return; + } + + addr = get_property(gmac, "local-mac-address", NULL); + if (addr == NULL) { + printk(KERN_ERR "Can't get mac-address for GMAC %s\n", + gmac->full_name); + return; + } + + descpage = get_free_page(GFP_KERNEL); + if (descpage == 0) { + printk(KERN_ERR "GMAC: can't get a page for descriptors\n"); + return; } dev = init_etherdev(0, sizeof(struct gmac)); @@ -544,13 +554,6 @@ static int __init gmac_probe(void) gm->sysregs = (volatile unsigned int *) ioremap(0xf8000000, 0x1000); dev->irq = gmac->intrs[0].line; - addr = get_property(gmac, "local-mac-address", NULL); - if (addr == NULL) { - printk(KERN_ERR "Can't get mac-address for GMAC %s\n", - gmac->full_name); - return -EAGAIN; - } - printk(KERN_INFO "%s: GMAC at", dev->name); for (i = 0; i < 6; ++i) { dev->dev_addr[i] = addr[i]; @@ -558,12 +561,6 @@ static int __init gmac_probe(void) } printk("\n"); - descpage = get_free_page(GFP_KERNEL); - if (descpage == 0) { - printk(KERN_ERR "GMAC: can't get a page for descriptors\n"); - return -EAGAIN; - } - gm->desc_page = descpage; gm->rxring = (volatile struct gmac_dma_desc *) descpage; gm->txring = (volatile struct gmac_dma_desc *) (descpage + 0x800); @@ -577,34 +574,29 @@ static int __init gmac_probe(void) ether_setup(dev); - if (request_irq(dev->irq, gmac_interrupt, 0, "GMAC", dev)) { + if (request_irq(dev->irq, gmac_interrupt, 0, "GMAC", dev)) printk(KERN_ERR "GMAC: can't get irq %d\n", dev->irq); - return -EAGAIN; - } + gm->next_gmac = gmacs; gmacs = dev; - - return 0; } -MODULE_AUTHOR("Paul Mackerras"); +MODULE_AUTHOR("Paul Mackerras/Ben Herrenschmidt"); MODULE_DESCRIPTION("PowerMac GMAC driver."); - static void __exit gmac_cleanup_module(void) { struct gmac *gm; - - /* XXX should handle more than one */ - if (gmacs == NULL) - return; - - gm = (struct gmac *) gmacs->priv; - free_irq(gmacs->irq, gmac_interrupt); - free_page(gm->descpage); - unregister_netdev(gmacs); - kfree(gmacs); - gmacs = NULL; + struct net_device *dev; + + while ((dev = gmacs) != NULL) { + gm = (struct gmac *) dev->priv; + gmacs = gm->next_gmac; + free_irq(dev->irq, dev); + free_page(gm->desc_page); + unregister_netdev(dev); + kfree(dev); + } } module_init(gmac_probe); diff --git a/drivers/net/mace.c b/drivers/net/mace.c index 4840e1abfafd..ac0771bd88e3 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -20,9 +20,7 @@ #include #include "mace.h" -#ifdef MODULE static struct net_device *mace_devs = NULL; -#endif #define N_RX_RING 8 #define N_TX_RING 6 @@ -55,6 +53,7 @@ struct mace_data { struct net_device_stats stats; struct timer_list tx_timeout; int timeout_active; + struct net_device *next_mace; }; /* @@ -67,6 +66,8 @@ struct mace_data { + (N_RX_RING + NCMDS_TX * N_TX_RING + 3) * sizeof(struct dbdma_cmd)) static int bitrev(int); +static int mace_probe(void); +static void mace_probe1(struct device_node *mace); static int mace_open(struct net_device *dev); static int mace_close(struct net_device *dev); static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev); @@ -99,34 +100,36 @@ bitrev(int b) return d; } -static int __init mace_probe (void) +static int __init mace_probe(void) +{ + struct device_node *mace; + + for (mace = find_devices("mace"); mace != NULL; mace = mace->next) + mace_probe1(mace); + return 0; +} + +static void __init mace_probe1(struct device_node *mace) { int j, rev; struct net_device *dev; struct mace_data *mp; - struct device_node *mace; unsigned char *addr; - static int maces_found = 0; - static struct device_node *next_mace; - -#ifdef MODULE - if(mace_devs != NULL) - return -EBUSY; -#endif - - if (!maces_found) { - next_mace = find_devices("mace"); - maces_found = 1; - } - mace = next_mace; - if (mace == 0) - return -ENODEV; - next_mace = mace->next; if (mace->n_addrs != 3 || mace->n_intrs != 3) { - printk(KERN_ERR "can't use MACE %s: expect 3 addrs and 3 intrs\n", + printk(KERN_ERR "can't use MACE %s: need 3 addrs and 3 irqs\n", mace->full_name); - return -ENODEV; + return; + } + + addr = get_property(mace, "mac-address", NULL); + if (addr == NULL) { + addr = get_property(mace, "local-mac-address", NULL); + if (addr == NULL) { + printk(KERN_ERR "Can't get mac-address for MACE %s\n", + mace->full_name); + return; + } } dev = init_etherdev(0, PRIV_BYTES); @@ -138,16 +141,6 @@ static int __init mace_probe (void) ioremap(mace->addrs[0].address, 0x1000); dev->irq = mace->intrs[0].line; - addr = get_property(mace, "mac-address", NULL); - if (addr == NULL) { - addr = get_property(mace, "local-mac-address", NULL); - if (addr == NULL) { - printk(KERN_ERR "Can't get mac-address for MACE at %lx\n", - dev->base_addr); - return -EAGAIN; - } - } - printk(KERN_INFO "%s: MACE at", dev->name); rev = addr[0] == 0 && addr[1] == 0xA0; for (j = 0; j < 6; ++j) { @@ -186,22 +179,17 @@ static int __init mace_probe (void) mace_reset(dev); - if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev)) { + if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev)) printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq); - return -EAGAIN; - } if (request_irq(mace->intrs[1].line, mace_txdma_intr, 0, "MACE-txdma", - dev)) { + dev)) printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[1].line); - return -EAGAIN; - } if (request_irq(mace->intrs[2].line, mace_rxdma_intr, 0, "MACE-rxdma", - dev)) { + dev)) printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[2].line); - return -EAGAIN; - } - return 0; + mp->next_mace = mace_devs; + mace_devs = dev; } static void dbdma_reset(volatile struct dbdma_regs *dma) @@ -365,9 +353,7 @@ static int mace_open(struct net_device *dev) /* enable all interrupts except receive interrupts */ out_8(&mb->imr, RCVINT); -#ifdef MOD_INC_USE_COUNT MOD_INC_USE_COUNT; -#endif return 0; } @@ -406,9 +392,7 @@ static int mace_close(struct net_device *dev) mace_clean_rings(mp); -#ifdef MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT; -#endif return 0; } @@ -683,7 +667,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) mp->stats.tx_bytes += mp->tx_bufs[i]->len; ++mp->stats.tx_packets; } - dev_kfree_skb(mp->tx_bufs[i]); + dev_kfree_skb_irq(mp->tx_bufs[i]); --mp->tx_active; if (++i >= N_TX_RING) i = 0; @@ -895,23 +879,25 @@ static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) } } - MODULE_AUTHOR("Paul Mackerras"); MODULE_DESCRIPTION("PowerMac MACE driver."); static void __exit mace_cleanup (void) { -#ifdef MODULE - struct mace_data *mp = (struct mace_data *) mace_devs->priv; - unregister_netdev(mace_devs); + struct net_device *dev; + struct mace_data *mp; - free_irq(mace_devs->irq, mace_interrupt); - free_irq(mp->tx_dma_intr, mace_txdma_intr); - free_irq(mp->rx_dma_intr, mace_rxdma_intr); + while ((dev = mace_devs) != 0) { + mp = (struct mace_data *) mace_devs->priv; + mace_devs = mp->next_mace; - kfree(mace_devs); - mace_devs = NULL; -#endif + free_irq(dev->irq, dev); + free_irq(mp->tx_dma_intr, dev); + free_irq(mp->rx_dma_intr, dev); + + unregister_netdev(dev); + kfree(dev); + } } module_init(mace_probe); diff --git a/drivers/net/ncr885e.c b/drivers/net/ncr885e.c index fd120de2b6a4..6a8c8b4129a6 100644 --- a/drivers/net/ncr885e.c +++ b/drivers/net/ncr885e.c @@ -11,9 +11,10 @@ */ static const char *version = -"ncr885e.c:v0.8 11/30/98 dan@synergymicro.com\n"; +"ncr885e.c:v1.0 02/10/00 dan@synergymicro.com, cort@fsmlabs.com\n"; #include + #include #include #include @@ -81,8 +82,6 @@ static const char *chipname = "ncr885e"; int ncr885e_debug = NCR885E_DEBUG; static int print_version = 0; -static int debug = NCR885E_DEBUG; /* module parm */ - struct ncr885e_private { @@ -426,7 +425,6 @@ ncr885e_tx( struct net_device *dev ) if ( xfer ) { dev_kfree_skb( sp->tx_skbufs[i] ); - mark_bh( NET_BH ); if ( txbits & TX_STATUS_TXOK ) { sp->stats.tx_packets++; @@ -443,7 +441,7 @@ ncr885e_tx( struct net_device *dev ) } - dev->tbusy = 0; + netif_start_queue(dev); return; } @@ -626,12 +624,6 @@ ncr885e_interrupt( int irq, void *dev_id, struct pt_regs *regs ) sp = (struct ncr885e_private *) dev->priv; spin_lock( &sp->lock ); - if ( dev->interrupt ) { - printk( KERN_ERR "%s: Re-entering interrupt handler...\n", - dev->name ); - } - - dev->interrupt = 1; status = inw( ioaddr + INTERRUPT_CLEAR ); if (ncr885e_debug > 2) @@ -671,7 +663,6 @@ ncr885e_interrupt( int irq, void *dev_id, struct pt_regs *regs ) ncr885e_rx( dev ); } - dev->interrupt = 0; spin_unlock( &sp->lock ); return; @@ -779,8 +770,7 @@ ncr885e_tx_timeout( unsigned long data ) /* start anew from the beginning of the ring buffer (why not?) */ sp->tx_current = 0; - dev->tbusy = 0; - mark_bh( NET_BH ); + netif_wake_queue(dev); /* restart rx dma */ outl( (RX_DBDMA_ENABLE << 16) | RX_CHANNEL_RUN, @@ -958,9 +948,7 @@ ncr885e_open( struct net_device *dev ) outl( (RX_DBDMA_ENABLE << 16)|RX_CHANNEL_RUN, ioaddr + RX_CHANNEL_CONTROL ); - dev->start = 1; - dev->tbusy = 0; - dev->interrupt = 0; + netif_start_queue(dev); MOD_INC_USE_COUNT; @@ -990,7 +978,7 @@ ncr885e_xmit_start( struct sk_buff *skb, struct net_device *dev ) next = 0; /* mark ourselves as busy, even if we have too many packets waiting */ - dev->tbusy = 1; + netif_stop_queue(dev); /* see if it's necessary to defer this packet */ if ( sp->tx_active >= MAX_TX_ACTIVE ) { @@ -1058,8 +1046,7 @@ ncr885e_close(struct net_device *dev) struct ncr885e_private *np = (struct ncr885e_private *) dev->priv; unsigned long ioaddr = dev->base_addr; - dev->start = 0; - dev->tbusy = 1; + netif_stop_queue(dev); spin_lock( &np->lock ); @@ -1148,8 +1135,7 @@ ncr885e_stats( struct net_device *dev ) * configuration. */ -static int -ncr885e_probe1(unsigned long ioaddr, unsigned char irq ) +static int __init ncr885e_probe1(unsigned long ioaddr, unsigned char irq ) { struct net_device *dev; @@ -1158,9 +1144,6 @@ ncr885e_probe1(unsigned long ioaddr, unsigned char irq ) unsigned char *p; int i; - if (!request_region( ioaddr, NCR885E_TOTAL_SIZE, dev->name)) - return -EBUSY; - dev = init_etherdev(NULL, 0 ); /* construct private data for the 885 ethernet */ @@ -1413,12 +1396,16 @@ write_mii( unsigned long ioaddr, int reg, int data ) #endif /* NCR885E_DEBUG_MII */ -MODULE_AUTHOR("dan@synergymicro.com"); -MODULE_DESCRIPTION("Symbios 53C885 Ethernet driver"); -MODULE_PARM(debug, "i"); +int +init_module(void) +{ + if ( debug >= 0) + ncr885e_debug = debug; + return ncr885e_probe(); +} -static void __exit ncr885e_cleanup (void) +static void __exit cleanup_module(void) { struct ncr885e_private *np; @@ -1435,7 +1422,6 @@ static void __exit ncr885e_cleanup (void) module_init(ncr885e_probe); module_exit(ncr885e_cleanup); - /* * Local variables: * compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O6 -c symba.c" diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 4e4fc4157a0c..1e53dc964f31 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -220,6 +220,7 @@ struct el3_private { u_short media_status; u_short fast_poll; u_long last_irq; + spinlock_t lock; }; /* Set iff a MII transceiver on any interface requires mdio preamble. @@ -261,6 +262,7 @@ static int el3_rx(struct net_device *dev, int worklimit); static int el3_close(struct net_device *dev); static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static void set_rx_mode(struct net_device *dev); +static void el3_tx_timeout(struct net_device *dev); static dev_info_t dev_info = "3c574_cs"; @@ -320,6 +322,8 @@ static dev_link_t *tc574_attach(void) lp = kmalloc(sizeof(*lp), GFP_KERNEL); if (!lp) return NULL; memset(lp, 0, sizeof(*lp)); + + lp->lock = SPIN_LOCK_UNLOCKED; link = &lp->link; dev = &lp->dev; link->priv = dev->priv = link->irq.Instance = lp; @@ -351,7 +355,10 @@ static dev_link_t *tc574_attach(void) dev->init = &tc574_init; dev->open = &el3_open; dev->stop = &el3_close; - dev->tbusy = 1; + dev->tx_timeout = el3_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; + + netif_start_queue (dev); /* Register with Card Services */ link->next = dev_list; @@ -398,13 +405,12 @@ static void tc574_detach(dev_link_t *link) if (*linkp == NULL) return; - save_flags(flags); - cli(); + spin_lock_irqsave(&lp->lock, flags); if (link->state & DEV_RELEASE_PENDING) { del_timer(&link->release); link->state &= ~DEV_RELEASE_PENDING; } - restore_flags(flags); + spin_unlock_irqrestore(&lp->lock, flags); if (link->state & DEV_CONFIG) { tc574_release((u_long)link); @@ -502,7 +508,7 @@ static void tc574_config(dev_link_t *link) dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; - dev->tbusy = 0; + netif_start_queue (dev); if (register_netdev(dev) != 0) { printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n"); goto failed; @@ -667,7 +673,7 @@ static int tc574_event(event_t event, int priority, case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { - dev->tbusy = 1; dev->start = 0; + netif_stop_queue (dev); link->release.expires = jiffies + HZ/20; add_timer(&link->release); } @@ -682,7 +688,7 @@ static int tc574_event(event_t event, int priority, case CS_EVENT_RESET_PHYSICAL: if (link->state & DEV_CONFIG) { if (link->open) { - dev->tbusy = 1; dev->start = 0; + netif_stop_queue (dev); } CardServices(ReleaseConfiguration, link->handle); } @@ -695,7 +701,7 @@ static int tc574_event(event_t event, int priority, CardServices(RequestConfiguration, link->handle, &link->conf); if (link->open) { tc574_reset(dev); - dev->tbusy = 0; dev->start = 1; + netif_start_queue (dev); } } break; @@ -913,7 +919,7 @@ static int el3_open(struct net_device *dev) link->open++; MOD_INC_USE_COUNT; - dev->interrupt = 0; dev->tbusy = 0; dev->start = 1; + netif_start_queue (dev); tc574_reset(dev); lp->media.function = &media_check; @@ -939,7 +945,7 @@ static void el3_tx_timeout(struct net_device *dev) /* Issue TX_RESET and TX_START commands. */ wait_for_completion(dev, TxReset); outw(TxEnable, ioaddr + EL3_CMD); - dev->tbusy = 0; + netif_start_queue (dev); } static void pop_tx_status(struct net_device *dev) @@ -972,22 +978,16 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev) long flags = 0; #endif - /* Transmitter timeout, serious problems. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - if (jiffies - dev->trans_start < TX_TIMEOUT) - return 1; - el3_tx_timeout(dev); - } - DEBUG(3, "%s: el3_start_xmit(length = %ld) called, " "status %4.4x.\n", dev->name, (long)skb->len, inw(ioaddr + EL3_STATUS)); + netif_stop_queue (dev); + #ifdef BROKEN_FEATURES if (use_fifo_buffer) { /* Avoid other accesses to the chip while RunnerWrCtrl is non-zero. */ - save_flags(flags); - cli(); + spin_lock_irqsave(&lp->lock, flags); outw((((skb->len + 7)>>2)<<1), ioaddr + RunnerWrCtrl); DEBUG(0, "TxFree %x, tx length %x, RunnerWrCtrl is %4.4x.\n", inw(ioaddr+TxFree), skb->len, inw(ioaddr+RunnerWrCtrl)); @@ -1009,7 +1009,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev) DEBUG(0, " RunnerWr/RdCtrl is %4.4x/%4.4x, TxFree %x.\n", inw(ioaddr + RunnerWrCtrl), inw(ioaddr + RunnerRdCtrl), inw(ioaddr + TxFree)); - restore_flags(flags); + spin_unlock_irqrestore (&lp->lock, flags); } #else outw(skb->len, ioaddr + TX_FIFO); @@ -1021,7 +1021,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev) /* TxFree appears only in Window 1, not offset 0x1c. */ if (inw(ioaddr + TxFree) > 1536) { - dev->tbusy = 0; + netif_start_queue (dev); } else /* Interrupt us when the FIFO has room for max-sized packet. The threshold is in units of dwords. */ @@ -1041,26 +1041,27 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) ioaddr_t ioaddr, status; int work_budget = max_interrupt_work; - if ((lp == NULL) || !dev->start) + if (lp == NULL) return; + + spin_lock (&lp->lock); + ioaddr = dev->base_addr; #ifdef PCMCIA_DEBUG - if (test_and_set_bit(0, (void*)&dev->interrupt)) { - printk(KERN_NOTICE "%s: re-entering the interrupt handler.\n", - dev->name); - return; - } DEBUG(3, "%s: interrupt, status %4.4x.\n", dev->name, inw(ioaddr + EL3_STATUS)); #endif while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete | RxEarly | StatsFull)) { + +#if 0 if ((dev->start == 0) || ((status & 0xe000) != 0x2000)) { DEBUG(1, "%s: Interrupt from dead card\n", dev->name); break; } +#endif if (status & RxComplete) work_budget = el3_rx(dev, work_budget); @@ -1069,8 +1070,9 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) DEBUG(3, " TX room bit was handled.\n"); /* There's room in the FIFO for a full-sized packet. */ outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); - dev->tbusy = 0; - mark_bh(NET_BH); + netif_wake_queue (dev); + } else { + netif_stop_queue (dev); } if (status & TxComplete) @@ -1120,9 +1122,9 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) #ifdef PCMCIA_DEBUG DEBUG(3, "%s: exiting interrupt, status %4.4x.\n", dev->name, inw(ioaddr + EL3_STATUS)); - dev->interrupt = 0; #endif - return; + + spin_unlock (&lp->lock); } /* @@ -1138,7 +1140,9 @@ static void media_check(u_long arg) u_long flags; u_short /* cable, */ media, partner; +#if 0 if (dev->start == 0) goto reschedule; +#endif /* Check for pending interrupt with expired latency timer: with this, we can limp along even if the interrupt is blocked */ @@ -1208,7 +1212,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev) { struct el3_private *lp = (struct el3_private *)dev->priv; - if (dev->start) + if (test_bit(LINK_STATE_START, &dev->state)) update_stats(dev); return &lp->stats; } @@ -1404,6 +1408,8 @@ static int el3_close(struct net_device *dev) DEBUG(2, "%s: shutting down ethercard.\n", dev->name); + netif_stop_queue (dev); + if (DEV_OK(link)) { /* Turn off statistics ASAP. We update lp->stats below. */ outw(StatsDisable, ioaddr + EL3_CMD); @@ -1419,7 +1425,6 @@ static int el3_close(struct net_device *dev) } link->open--; - dev->start = 0; del_timer(&lp->media); if (link->state & DEV_STALE_CONFIG) { link->release.expires = jiffies + HZ/20; diff --git a/drivers/net/pcmcia/3c575_cb.c b/drivers/net/pcmcia/3c575_cb.c index 82f534f0c68e..18cb312e4d14 100644 --- a/drivers/net/pcmcia/3c575_cb.c +++ b/drivers/net/pcmcia/3c575_cb.c @@ -53,18 +53,7 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits; #error You must compile this driver with "-O". #endif -#include -#include -#ifdef MODULE -#ifdef MODVERSIONS -#include -#endif #include -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif - #include #include #include @@ -89,13 +78,6 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits; #include -#define PCI_SUPPORT_VER2 -#define DEV_FREE_SKB(skb) dev_kfree_skb(skb); -#if ! defined(CAP_NET_ADMIN) -#define capable(CAP_XXX) (suser()) -#endif - -#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115 MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver"); MODULE_PARM(debug, "i"); @@ -106,7 +88,6 @@ MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(compaq_ioaddr, "i"); MODULE_PARM(compaq_irq, "i"); MODULE_PARM(compaq_device_id, "i"); -#endif /* Operational parameter that usually are not changed. */ @@ -209,15 +190,15 @@ struct pci_id_info { const char *name; u16 vendor_id, device_id, device_id_mask, flags; int drv_flags, io_size; - struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev, - long ioaddr, int irq, int chip_idx, int fnd_cnt); + struct net_device *(*probe1)(struct pci_dev *pdev, struct net_device *dev, + long ioaddr, int irq, int chip_idx, int fnd_cnt); }; enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, }; -static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, - struct net_device *dev, long ioaddr, - int irq, int dev_id, int card_idx); +static struct net_device *vortex_probe1(struct pci_dev *pdev, + struct net_device *dev, long ioaddr, + int irq, int dev_id, int card_idx); static struct pci_id_info pci_tbl[] = { {"3c590 Vortex 10Mbps", 0x10B7, 0x5900, 0xffff, PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1}, @@ -427,7 +408,7 @@ struct vortex_private { struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */ /* PCI configuration space information. */ - u8 pci_bus, pci_devfn; /* PCI bus location, for power management. */ + struct pci_dev *pdev; char *cb_fn_base; /* CardBus function status addr space. */ int chip_id; @@ -451,6 +432,7 @@ struct vortex_private { u16 advertising; /* NWay media advertisement */ unsigned char phys[2]; /* MII device addresses. */ u16 deferred; + spinlock_t lock; }; /* The action to take with a media selection timer tick. @@ -501,7 +483,8 @@ static void update_stats(long ioaddr, struct net_device *dev); static struct net_device_stats *vortex_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static void acpi_wake(int pci_bus, int pci_devfn); +static void vortex_tx_timeout(struct net_device *dev); +static void acpi_wake(struct pci_dev *pdev); static void acpi_set_WOL(struct net_device *dev); /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */ @@ -542,20 +525,21 @@ static dev_node_t *vortex_attach(dev_locator_t *loc) { u16 dev_id, vendor_id; u32 io; - u8 bus, devfn, irq; + u8 irq; struct net_device *dev; int chip_idx; + struct pci_dev *pdev; vortex_reap(); if (loc->bus != LOC_PCI) return NULL; - bus = loc->b.pci.bus; devfn = loc->b.pci.devfn; - pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io); - pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq); - pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id); - pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id); + pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn); + if (!pdev) return NULL; + io = pci_resource_start (pdev, 0); + irq = pdev->irq; + vendor_id = pdev->vendor; + dev_id = pdev->device; printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n", - bus, devfn, dev_id); - io &= ~3; + pdev->bus->number, pdev->devfn, dev_id); if (io == 0 || irq == 0) { printk(KERN_ERR "The 3Com CardBus Ethernet interface was not " "assigned an %s.\n" KERN_ERR " It will not be activated.\n", @@ -572,7 +556,7 @@ static dev_node_t *vortex_attach(dev_locator_t *loc) "vortex_attach().\n", vendor_id, dev_id); return NULL; } - dev = vortex_probe1(bus, devfn, NULL, io, irq, chip_idx, MAX_UNITS+1); + dev = vortex_probe1(pdev, NULL, io, irq, chip_idx, MAX_UNITS+1); if (dev) { dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL); strcpy(node->dev_name, dev->name); @@ -663,44 +647,6 @@ static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[]) int cards_found = 0; /* Allow an EISA-only driver. */ -#if defined(CONFIG_PCI) || (defined(MODULE) && !defined(NO_PCI)) - /* Ideally we would detect all cards in slot order. That would - be best done a central PCI probe dispatch, which wouldn't work - well with the current structure. So instead we detect 3Com cards - in slot order. */ - if (pcibios_present()) { - static int pci_index = 0; - unsigned char pci_bus, pci_device_fn; - - for (;pci_index < 0xff; pci_index++) { - u16 vendor, device, pci_command, new_command; - int chip_idx, irq; - long ioaddr; - - if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index, - &pci_bus, &pci_device_fn) - != PCIBIOS_SUCCESSFUL) - break; - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_DEVICE_ID, &device); - for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++) - if (vendor == pci_tbl[chip_idx].vendor_id - && (device & pci_tbl[chip_idx].device_id_mask) == - pci_tbl[chip_idx].device_id) - break; - if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */ - continue; - - /* The Cyclone requires config space re-write if powered down. */ - acpi_wake(pci_bus, pci_device_fn); - - { - struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); - ioaddr = pdev->resource[0].start; - irq = pdev->irq; -#elif LINUX_VERSION_CODE >= 0x20155 struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); ioaddr = pdev->base_address[0] & ~3; irq = pdev->irq; @@ -751,7 +697,6 @@ static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[]) } } } -#endif /* NO_PCI */ /* Now check all slots of the EISA bus. */ if (EISA_bus) { @@ -787,9 +732,9 @@ static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[]) } #endif /* ! Cardbus */ -static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, - struct net_device *dev, long ioaddr, - int irq, int chip_idx, int card_idx) +static struct net_device *vortex_probe1(struct pci_dev *pdev, + struct net_device *dev, long ioaddr, + int irq, int chip_idx, int card_idx) { struct vortex_private *vp; int option; @@ -817,9 +762,9 @@ static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, vp->next_module = root_vortex_dev; root_vortex_dev = dev; + vp->lock = SPIN_LOCK_UNLOCKED; vp->chip_id = chip_idx; - vp->pci_bus = pci_bus; - vp->pci_devfn = pci_devfn; + vp->pdev = pdev; /* The lower four bits are the media type. */ if (dev->mem_start) @@ -892,10 +837,9 @@ static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, if (pci_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) { u32 fn_st_addr; /* Cardbus function status space */ - pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2, - &fn_st_addr); + fn_st_addr = pci_resource_start (pdev, 2); if (fn_st_addr) - vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128); + vp->cb_fn_base = ioremap(fn_st_addr, 128); printk(KERN_INFO "%s: CardBus functions mapped %8.8x->%p\n", dev->name, fn_st_addr, vp->cb_fn_base); } @@ -988,6 +932,8 @@ static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, dev->get_stats = &vortex_get_stats; dev->do_ioctl = &vortex_ioctl; dev->set_multicast_list = &set_rx_mode; + dev->tx_timeout = vortex_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; return dev; } @@ -1013,7 +959,7 @@ vortex_up(struct net_device *dev) int i; /* Should be if(HAS_ACPI) */ - acpi_wake(vp->pci_bus, vp->pci_devfn); + acpi_wake(vp->pdev); /* Before initializing select the active media port. */ EL3WINDOW(3); @@ -1157,9 +1103,7 @@ vortex_up(struct net_device *dev) outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ vp->in_interrupt = 0; - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + netif_start_queue (dev); outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ @@ -1377,8 +1321,10 @@ static void vortex_tx_timeout(struct net_device *dev) ioaddr + DownListPtr); if (vp->tx_full && (vp->cur_tx - vp->dirty_tx <= TX_RING_SIZE - 1)) { vp->tx_full = 0; - clear_bit(0, (void*)&dev->tbusy); + netif_start_queue (dev); } + if (vp->tx_full) + netif_stop_queue (dev); outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); outw(DownUnstall, ioaddr + EL3_CMD); } else @@ -1478,12 +1424,8 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) struct vortex_private *vp = (struct vortex_private *)dev->priv; long ioaddr = dev->base_addr; - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - if (jiffies - dev->trans_start >= TX_TIMEOUT) - vortex_tx_timeout(dev); - return 1; - } - + netif_stop_queue (dev); + /* Put out the doubleword header... */ outl(skb->len, ioaddr + TX_FIFO); if (vp->bus_master) { @@ -1496,9 +1438,9 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) } else { /* ... and the packet rounded to a doubleword. */ outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); - DEV_FREE_SKB(skb); + dev_kfree_skb (skb); if (inw(ioaddr + TxFree) > 1536) { - clear_bit(0, (void*)&dev->tbusy); + netif_start_queue (dev); } else /* Interrupt us when the FIFO has room for max-sized packet. */ outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); @@ -1535,11 +1477,8 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) struct vortex_private *vp = (struct vortex_private *)dev->priv; long ioaddr = dev->base_addr; - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - if (jiffies - dev->trans_start >= TX_TIMEOUT) - vortex_tx_timeout(dev); - return 1; - } else { + netif_stop_queue (dev); + if (1) { /* Calculate the next Tx descriptor entry. */ int entry = vp->cur_tx % TX_RING_SIZE; struct boom_tx_desc *prev_entry = @@ -1561,8 +1500,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG); vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded); - save_flags(flags); - cli(); + spin_lock_irqsave(&vp->lock, flags); /* Wait for the stall to complete. */ wait_for_completion(dev, DownStall); prev_entry->next = cpu_to_le32(virt_to_bus(&vp->tx_ring[entry])); @@ -1571,16 +1509,17 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) queued_packet++; } outw(DownUnstall, ioaddr + EL3_CMD); - restore_flags(flags); + spin_unlock_irqrestore(&vp->lock, flags); vp->cur_tx++; - if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) + if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) { vp->tx_full = 1; - else { /* Clear previous interrupt enable. */ + netif_stop_queue (dev); + } else { /* Clear previous interrupt enable. */ #if defined(tx_interrupt_mitigation) prev_entry->status &= cpu_to_le32(~TxIntrUploaded); #endif - clear_bit(0, (void*)&dev->tbusy); + netif_start_queue (dev); } dev->trans_start = jiffies; return 0; @@ -1597,23 +1536,8 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) int latency, status; int work_done = max_interrupt_work; -#if defined(__i386__) - /* A lock to prevent simultaneous entry bug on Intel SMP machines. */ - if (test_and_set_bit(0, (void*)&dev->interrupt)) { - printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n", - dev->name); - dev->interrupt = 0; /* Avoid halting machine. */ - return; - } -#else - if (dev->interrupt) { - printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); - return; - } - dev->interrupt = 1; -#endif - - dev->interrupt = 1; + spin_lock (&vp->lock); + ioaddr = dev->base_addr; latency = inb(ioaddr + Timer); status = inw(ioaddr + EL3_STATUS); @@ -1643,8 +1567,7 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) printk(KERN_DEBUG " TX room bit was handled.\n"); /* There's room in the FIFO for a full-sized packet. */ outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); - clear_bit(0, (void*)&dev->tbusy); - mark_bh(NET_BH); + netif_wake_queue (dev); } if (status & DownComplete) { @@ -1657,7 +1580,7 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) virt_to_bus(&vp->tx_ring[entry])) break; /* It still hasn't been processed. */ if (vp->tx_skbuff[entry]) { - DEV_FREE_SKB(vp->tx_skbuff[entry]); + dev_kfree_skb_irq(vp->tx_skbuff[entry]); vp->tx_skbuff[entry] = 0; } /* vp->stats.tx_packets++; Counted below. */ @@ -1666,19 +1589,21 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) vp->dirty_tx = dirty_tx; if (vp->tx_full && (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) { vp->tx_full = 0; - clear_bit(0, (void*)&dev->tbusy); - mark_bh(NET_BH); + netif_wake_queue (dev); } } + if (vp->tx_full) + netif_stop_queue (dev); if (status & DMADone) { if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) { outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */ - DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */ + dev_kfree_skb_irq(vp->tx_skb); /* Release the transfered buffer */ if (inw(ioaddr + TxFree) > 1536) { - clear_bit(0, (void*)&dev->tbusy); - mark_bh(NET_BH); - } else /* Interrupt when FIFO has room for max-sized packet. */ + netif_wake_queue (dev); + } else { /* Interrupt when FIFO has room for max-sized packet. */ outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); + netif_stop_queue (dev); + } } } /* Check for all uncommon interrupts at once. */ @@ -1715,12 +1640,7 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", dev->name, status); handler_exit: -#if defined(__i386__) - clear_bit(0, (void*)&dev->interrupt); -#else - dev->interrupt = 0; -#endif - return; + spin_unlock (&vp->lock); } static int vortex_rx(struct net_device *dev) @@ -1891,8 +1811,7 @@ vortex_down(struct net_device *dev) struct vortex_private *vp = (struct vortex_private *)dev->priv; long ioaddr = dev->base_addr; - dev->start = 0; - dev->tbusy = 1; + netif_stop_queue (dev); del_timer(&vp->timer); @@ -1926,7 +1845,7 @@ vortex_close(struct net_device *dev) long ioaddr = dev->base_addr; int i; - if (dev->start) + if (test_bit(LINK_STATE_START, &dev->state)) vortex_down(dev); if (vortex_debug > 1) { @@ -1942,14 +1861,14 @@ vortex_close(struct net_device *dev) if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */ for (i = 0; i < RX_RING_SIZE; i++) if (vp->rx_skbuff[i]) { - DEV_FREE_SKB(vp->rx_skbuff[i]); + dev_kfree_skb(vp->rx_skbuff[i]); vp->rx_skbuff[i] = 0; } } if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */ for (i = 0; i < TX_RING_SIZE; i++) if (vp->tx_skbuff[i]) { - DEV_FREE_SKB(vp->tx_skbuff[i]); + dev_kfree_skb(vp->tx_skbuff[i]); vp->tx_skbuff[i] = 0; } } @@ -1964,11 +1883,10 @@ static struct net_device_stats *vortex_get_stats(struct net_device *dev) struct vortex_private *vp = (struct vortex_private *)dev->priv; unsigned long flags; - if (dev->start) { - save_flags(flags); - cli(); + if (test_bit(LINK_STATE_START, &dev->state)) { + spin_lock_irqsave (&vp->lock, flags); update_stats(dev->base_addr, dev); - restore_flags(flags); + spin_unlock_irqrestore (&vp->lock, flags); } return &vp->stats; } @@ -2168,35 +2086,35 @@ static void acpi_set_WOL(struct net_device *dev) outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD); outw(RxEnable, ioaddr + EL3_CMD); /* Change the power state to D3; RxEnable doesn't take effect. */ - pcibios_write_config_word(vp->pci_bus, vp->pci_devfn, 0xe0, 0x8103); + pci_write_config_word(vp->pdev, 0xe0, 0x8103); } /* Change from D3 (sleep) to D0 (active). Problem: The Cyclone forgets all PCI config info during the transition! */ -static void acpi_wake(int bus, int devfn) +static void acpi_wake(struct pci_dev *pdev) { u32 base0, base1, romaddr; u16 pci_command, pwr_command; u8 pci_latency, pci_cacheline, irq; - pcibios_read_config_word(bus, devfn, 0xe0, &pwr_command); + pci_read_config_word(pdev, 0xe0, &pwr_command); if ((pwr_command & 3) == 0) return; - pcibios_read_config_word( bus, devfn, PCI_COMMAND, &pci_command); - pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &base0); - pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_1, &base1); - pcibios_read_config_dword(bus, devfn, PCI_ROM_ADDRESS, &romaddr); - pcibios_read_config_byte( bus, devfn, PCI_LATENCY_TIMER, &pci_latency); - pcibios_read_config_byte( bus, devfn, PCI_CACHE_LINE_SIZE, &pci_cacheline); - pcibios_read_config_byte( bus, devfn, PCI_INTERRUPT_LINE, &irq); - - pcibios_write_config_word( bus, devfn, 0xe0, 0x0000); - pcibios_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, base0); - pcibios_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_1, base1); - pcibios_write_config_dword(bus, devfn, PCI_ROM_ADDRESS, romaddr); - pcibios_write_config_byte( bus, devfn, PCI_INTERRUPT_LINE, irq); - pcibios_write_config_byte( bus, devfn, PCI_LATENCY_TIMER, pci_latency); - pcibios_write_config_byte( bus, devfn, PCI_CACHE_LINE_SIZE, pci_cacheline); - pcibios_write_config_word( bus, devfn, PCI_COMMAND, pci_command | 5); + pci_read_config_word( pdev, PCI_COMMAND, &pci_command); + pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base0); + pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1, &base1); + pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &romaddr); + pci_read_config_byte( pdev, PCI_LATENCY_TIMER, &pci_latency); + pci_read_config_byte( pdev, PCI_CACHE_LINE_SIZE, &pci_cacheline); + pci_read_config_byte( pdev, PCI_INTERRUPT_LINE, &irq); + + pci_write_config_word( pdev, 0xe0, 0x0000); + pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, base0); + pci_write_config_dword(pdev, PCI_BASE_ADDRESS_1, base1); + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, romaddr); + pci_write_config_byte( pdev, PCI_INTERRUPT_LINE, irq); + pci_write_config_byte( pdev, PCI_LATENCY_TIMER, pci_latency); + pci_write_config_byte( pdev, PCI_CACHE_LINE_SIZE, pci_cacheline); + pci_write_config_word( pdev, PCI_COMMAND, pci_command | 5); } #ifdef MODULE diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index e95b87104373..b819be85616e 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -155,6 +155,7 @@ static void update_stats(struct net_device *dev); static struct net_device_stats *el3_get_stats(struct net_device *dev); static int el3_rx(struct net_device *dev); static int el3_close(struct net_device *dev); +static void el3_tx_timeout(struct net_device *dev); static void set_multicast_list(struct net_device *dev); @@ -257,7 +258,10 @@ static dev_link_t *tc589_attach(void) dev->init = &tc589_init; dev->open = &el3_open; dev->stop = &el3_close; - dev->tbusy = 1; + dev->tx_timeout = el3_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; + + netif_start_queue (dev); /* Register with Card Services */ link->next = dev_list; @@ -399,7 +403,7 @@ static void tc589_config(dev_link_t *link) dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; - dev->tbusy = 0; + netif_start_queue (dev); if (register_netdev(dev) != 0) { printk(KERN_NOTICE "3c589_cs: register_netdev() failed\n"); goto failed; @@ -508,7 +512,7 @@ static int tc589_event(event_t event, int priority, case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { - dev->tbusy = 1; dev->start = 0; + netif_stop_queue (dev); link->release.expires = jiffies + HZ/20; add_timer(&link->release); } @@ -523,7 +527,7 @@ static int tc589_event(event_t event, int priority, case CS_EVENT_RESET_PHYSICAL: if (link->state & DEV_CONFIG) { if (link->open) { - dev->tbusy = 1; dev->start = 0; + netif_stop_queue (dev); } CardServices(ReleaseConfiguration, link->handle); } @@ -536,7 +540,7 @@ static int tc589_event(event_t event, int priority, CardServices(RequestConfiguration, link->handle, &link->conf); if (link->open) { tc589_reset(dev); - dev->tbusy = 0; dev->start = 1; + netif_start_queue (dev); } } break; @@ -683,7 +687,7 @@ static int el3_open(struct net_device *dev) link->open++; MOD_INC_USE_COUNT; - dev->interrupt = 0; dev->tbusy = 0; dev->start = 1; + netif_start_queue (dev); tc589_reset(dev); lp->media.function = &media_check; @@ -709,7 +713,7 @@ static void el3_tx_timeout(struct net_device *dev) /* Issue TX_RESET and TX_START commands. */ wait_for_completion(dev, TxReset); outw(TxEnable, ioaddr + EL3_CMD); - dev->tbusy = 0; + netif_start_queue (dev); } static void pop_tx_status(struct net_device *dev) @@ -739,22 +743,12 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev) { ioaddr_t ioaddr = dev->base_addr; - /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - if (jiffies - dev->trans_start < TX_TIMEOUT) - return 1; - el3_tx_timeout(dev); - } - DEBUG(3, "%s: el3_start_xmit(length = %ld) called, " "status %4.4x.\n", dev->name, (long)skb->len, inw(ioaddr + EL3_STATUS)); - /* Avoid timer-based retransmission conflicts. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) - printk(KERN_NOTICE "%s: transmitter access conflict.\n", - dev->name); - else { + netif_stop_queue (dev); + if (1) { struct el3_private *lp = (struct el3_private *)dev->priv; lp->stats.tx_bytes += skb->len; /* Put out the doubleword header... */ @@ -765,7 +759,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; if (inw(ioaddr + TX_FREE) > 1536) { - dev->tbusy = 0; + netif_start_queue (dev); } else /* Interrupt us when the FIFO has room for max-sized packet. */ outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); @@ -785,7 +779,7 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) ioaddr_t ioaddr, status; int i = 0; - if ((lp == NULL) || !dev->start) + if (lp == NULL) return; ioaddr = dev->base_addr; @@ -802,10 +796,12 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete | StatsFull)) { +#if 0 if ((dev->start == 0) || ((status & 0xe000) != 0x2000)) { DEBUG(1, "%s: interrupt from dead card\n", dev->name); break; } +#endif if (status & RxComplete) el3_rx(dev); @@ -814,8 +810,9 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) DEBUG(3, " TX room bit was handled.\n"); /* There's room in the FIFO for a full-sized packet. */ outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); - dev->tbusy = 0; - mark_bh(NET_BH); + netif_wake_queue (dev); + } else { + netif_stop_queue (dev); } if (status & TxComplete) @@ -879,7 +876,9 @@ static void media_check(u_long arg) u_short media, errs; u_long flags; +#if 0 if (dev->start == 0) goto reschedule; +#endif EL3WINDOW(1); /* Check for pending interrupt with expired latency timer: with @@ -1093,6 +1092,8 @@ static int el3_close(struct net_device *dev) ioaddr_t ioaddr = dev->base_addr; DEBUG(1, "%s: shutting down ethercard.\n", dev->name); + + netif_stop_queue (dev); if (DEV_OK(link)) { /* Turn off statistics ASAP. We update lp->stats below. */ @@ -1122,7 +1123,6 @@ static int el3_close(struct net_device *dev) } link->open--; - dev->start = 0; del_timer(&lp->media); if (link->state & DEV_STALE_CONFIG) { link->release.expires = jiffies + HZ/20; diff --git a/drivers/net/pcmcia/aironet4500_cs.c b/drivers/net/pcmcia/aironet4500_cs.c index 3dbb9923fc3b..1e96e668c881 100644 --- a/drivers/net/pcmcia/aironet4500_cs.c +++ b/drivers/net/pcmcia/aironet4500_cs.c @@ -231,8 +231,7 @@ static dev_link_t *awc_attach(void) dev->init = &awc_pcmcia_init; dev->open = &awc_pcmcia_open; dev->stop = &awc_pcmcia_close; - dev->tbusy = 1; - dev->start = 0; + netif_start_queue (dev); link->priv = dev; #if CS_RELEASE_CODE > 0x2911 @@ -567,7 +566,7 @@ static int awc_event(event_t event, int priority, case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { - dev->tbusy = 1; dev->start = 0; + netif_stop_queue (dev); link->release.expires = RUN_AT( HZ/20 ); add_timer(&link->release); } @@ -582,7 +581,7 @@ static int awc_event(event_t event, int priority, case CS_EVENT_RESET_PHYSICAL: if (link->state & DEV_CONFIG) { if (link->open) { - dev->tbusy = 1; dev->start = 0; + netif_stop_queue (dev); } CardServices(ReleaseConfiguration, link->handle); } @@ -595,7 +594,7 @@ static int awc_event(event_t event, int priority, CardServices(RequestConfiguration, link->handle, &link->conf); if (link->open) { // awc_reset(dev); - dev->tbusy = 0; dev->start = 1; + netif_start_queue (dev); } } break; diff --git a/drivers/net/pcmcia/netwave_cs.c b/drivers/net/pcmcia/netwave_cs.c index 74928fd27576..dd99d84acef9 100644 --- a/drivers/net/pcmcia/netwave_cs.c +++ b/drivers/net/pcmcia/netwave_cs.c @@ -151,7 +151,7 @@ static const unsigned int txConfEUD = 0x10; /* Enable Uni-Data packets */ static const unsigned int txConfKey = 0x02; /* Scramble data packets */ static const unsigned int txConfLoop = 0x01; /* Loopback mode */ -/*static int netwave_debug = 0;*/ +static int netwave_debug = 0; /* All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If @@ -223,6 +223,7 @@ static void netwave_reset(struct net_device *dev); static int netwave_open(struct net_device *dev); /* Open the device */ static int netwave_close(struct net_device *dev); /* Close the device */ static int netwave_config(struct net_device *dev, struct ifmap *map); +static void netwave_tx_timeout (struct net_device *dev); /* Packet transmission and Packet reception */ static int netwave_start_xmit( struct sk_buff *skb, struct net_device *dev); @@ -308,6 +309,7 @@ typedef struct netwave_private { u_char *ramBase; int timeoutCounter; int lastExec; + spinlock_t lock; struct timer_list watchdog; /* To avoid blocking state */ struct site_survey nss; struct enet_statistics stats; @@ -454,6 +456,7 @@ static dev_link_t *netwave_attach(void) priv = kmalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return NULL; memset(priv, 0, sizeof(*priv)); + priv->lock = SPIN_LOCK_UNLOCKED; link = &priv->link; dev = &priv->dev; link->priv = dev->priv = priv; link->release.function = &netwave_release; @@ -503,7 +506,9 @@ static dev_link_t *netwave_attach(void) dev->init = &netwave_init; dev->open = &netwave_open; dev->stop = &netwave_close; - dev->tbusy = 1; + dev->tx_timeout = netwave_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; + netif_start_queue (dev); link->irq.Instance = dev; /* Register with Card Services */ @@ -835,7 +840,7 @@ static void netwave_pcmcia_config(dev_link_t *link) { struct net_device *dev = &priv->dev; tuple_t tuple; cisparse_t parse; - int i, j, last_ret, last_fn; + int i=0, j, last_ret, last_fn; u_char buf[64]; win_req_t req; memreq_t mem; @@ -910,7 +915,7 @@ static void netwave_pcmcia_config(dev_link_t *link) { dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; - dev->tbusy = 0; + netif_start_queue (dev); if (register_netdev(dev) != 0) { printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n"); goto failed; @@ -1014,7 +1019,7 @@ static int netwave_event(event_t event, int priority, case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { - dev->tbusy = 1; dev->start = 0; + netif_stop_queue (dev); link->release.expires = jiffies + 5; add_timer(&link->release); } @@ -1029,7 +1034,7 @@ static int netwave_event(event_t event, int priority, case CS_EVENT_RESET_PHYSICAL: if (link->state & DEV_CONFIG) { if (link->open) { - dev->tbusy = 1; dev->start = 0; + netif_stop_queue (dev); } CardServices(ReleaseConfiguration, link->handle); } @@ -1042,7 +1047,7 @@ static int netwave_event(event_t event, int priority, CardServices(RequestConfiguration, link->handle, &link->conf); if (link->open) { netwave_reset(dev); - dev->tbusy = 0; dev->start = 1; + netif_start_queue (dev); } } break; @@ -1229,6 +1234,18 @@ static int netwave_hw_xmit(unsigned char* data, int len, return 0; } + +static void netwave_tx_timeout (struct net_device *dev) +{ + if (netwave_debug > 0) + printk (KERN_DEBUG "%s timed out.\n", dev->name); + netwave_reset (dev); + dev->trans_start = jiffies; + netif_start_queue (dev); +} + + + static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) { /* This flag indicate that the hardware can't perform a transmission. * Theoritically, NET3 check it before sending a packet to the driver, @@ -1236,29 +1253,6 @@ static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) { * As the watchdog will abort too long transmissions, we are quite safe... */ - if (dev->tbusy) { - /* Handled by watchdog */ - return 1; - - /* If we get here, some higher level has decided we are broken. - There should really be a 'kick me' function call instead. - */ - /*int tickssofar = jiffies - dev->trans_start;*/ - /* printk("xmit called with busy. tickssofar %d\n", tickssofar); */ - /*if (tickssofar < TX_TIMEOUT) - return 1; - */ - /* Should also detect if the kernel tries to xmit - * on a stopped card. - */ - - /*if (netwave_debug > 0) - printk(KERN_DEBUG "%s timed out.\n", dev->name); - netwave_reset(dev); - dev->trans_start = jiffies; - dev->tbusy = 0;*/ - } - /* Sending a NULL skb means some higher layer thinks we've missed an * tx-done interrupt. Caution: dev_tint() handles the cli()/sti() * itself. @@ -1268,15 +1262,14 @@ static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) { * better be done with atomic_swap(1, dev->tbusy, but set_bit() * works as well */ - if ( test_and_set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else { + netif_stop_queue (dev); + if (1) { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char* buf = skb->data; if (netwave_hw_xmit( buf, length, dev) == 1) { /* Some error, let's make them call us another time? */ - dev->tbusy = 0; + netif_start_queue (dev); } dev->trans_start = jiffies; } @@ -1303,14 +1296,10 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { dev_link_t *link = &priv->link; int i; - if ((dev == NULL) | (!dev->start)) + if (dev == NULL) return; - if (dev->interrupt) { - printk("%s: re-entering the interrupt handler.\n", dev->name); - return; - } - dev->interrupt = 1; + spin_lock (&priv->lock); iobase = dev->base_addr; ramBase = priv->ramBase; @@ -1409,8 +1398,7 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { /* If watchdog was activated, kill it ! */ del_timer(&priv->watchdog); - dev->tbusy = 0; - mark_bh(NET_BH); + netif_wake_queue (dev); } /* TxBA, this would trigger on all error packets received */ /* if (status & 0x01) { @@ -1420,8 +1408,7 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { */ } /* done.. */ - dev->interrupt = 0; - return; + spin_unlock (&priv->lock); } /* netwave_interrupt */ /* @@ -1444,7 +1431,7 @@ static void netwave_watchdog(u_long a) { netwave_reset(dev); /* We are not waiting anymore... */ - dev->tbusy = 0; + netif_start_queue (dev); } /* netwave_watchdog */ @@ -1584,7 +1571,7 @@ static int netwave_open(struct net_device *dev) { link->open++; MOD_INC_USE_COUNT; - dev->interrupt = 0; dev->tbusy = 0; dev->start = 1; + netif_start_queue (dev); netwave_reset(dev); return 0; @@ -1596,11 +1583,12 @@ static int netwave_close(struct net_device *dev) { DEBUG(1, "netwave_close: finishing.\n"); + netif_stop_queue (dev); + /* If watchdog was activated, kill it ! */ del_timer(&priv->watchdog); link->open--; - dev->start = 0; if (link->state & DEV_STALE_CONFIG) { link->release.expires = jiffies + 5; link->state |= DEV_RELEASE_PENDING; diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 2fb3772a55a4..a3c22cc7a4b1 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -307,6 +307,10 @@ four transmit and 12 receive frames at a time. #undef MACE_IMR_DEFAULT #define MACE_IMR_DEFAULT 0x00 /* New statistics handling: grab everything */ +#define TX_TIMEOUT (5*HZ) + + + /* ---------------------------------------------------------------------------- Type Definitions ---------------------------------------------------------------------------- */ @@ -360,6 +364,7 @@ typedef struct _mace_private { dev_link_t link; struct net_device dev; dev_node_t node; + spinlock_t lock; struct net_device_stats linux_stats; /* Linux statistics counters */ mace_statistics mace_stats; /* MACE chip statistics counters */ @@ -432,6 +437,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); static struct net_device_stats *mace_get_stats(struct net_device *dev); static int mace_rx(struct net_device *dev, unsigned char RxCnt); static void restore_multicast_list(struct net_device *dev); +static void mace_tx_timeout (struct net_device *dev); static void set_multicast_list(struct net_device *dev); @@ -498,6 +504,8 @@ static dev_link_t *nmclan_attach(void) lp = kmalloc(sizeof(*lp), GFP_KERNEL); if (!lp) return NULL; memset(lp, 0, sizeof(*lp)); + + lp->lock = SPIN_LOCK_UNLOCKED; link = &lp->link; dev = &lp->dev; link->priv = dev->priv = link->irq.Instance = lp; @@ -531,7 +539,10 @@ static dev_link_t *nmclan_attach(void) dev->init = &nmclan_init; dev->open = &mace_open; dev->stop = &mace_close; - dev->tbusy = 0xFF; + dev->tx_timeout = mace_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; + + netif_start_queue (dev); /* Register with Card Services */ link->next = dev_list; @@ -752,7 +763,7 @@ static void nmclan_config(dev_link_t *link) CS_CHECK(RequestConfiguration, handle, &link->conf); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; - dev->tbusy = 0; + netif_start_queue (dev); i = register_netdev(dev); if (i != 0) { printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n"); @@ -859,7 +870,7 @@ static int nmclan_event(event_t event, int priority, case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { - dev->tbusy = 0xFF; dev->start = 0; + netif_stop_queue (dev); link->release.expires = jiffies + HZ/20; add_timer(&link->release); } @@ -874,7 +885,7 @@ static int nmclan_event(event_t event, int priority, case CS_EVENT_RESET_PHYSICAL: if (link->state & DEV_CONFIG) { if (link->open) { - dev->tbusy = 0xFF; dev->start = 0; + netif_stop_queue (dev); } CardServices(ReleaseConfiguration, link->handle); } @@ -886,9 +897,8 @@ static int nmclan_event(event_t event, int priority, if (link->state & DEV_CONFIG) { CardServices(RequestConfiguration, link->handle, &link->conf); if (link->open) { - dev->tbusy = 0; - dev->start = 1; nmclan_reset(dev); + netif_start_queue (dev); } } break; @@ -987,10 +997,7 @@ static int mace_open(struct net_device *dev) MACEBANK(0); - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; - + netif_start_queue (dev); nmclan_reset(dev); return 0; /* Always succeed */ @@ -1007,12 +1014,13 @@ static int mace_close(struct net_device *dev) dev_link_t *link = &lp->link; DEBUG(2, "%s: shutting down ethercard.\n", dev->name); + + netif_stop_queue (dev); /* Mask off all interrupts from the MACE chip. */ outb(0xFF, ioaddr + AM2150_MACE_BASE + MACE_IMR); link->open--; - dev->start = 0; if (link->state & DEV_STALE_CONFIG) { link->release.expires = jiffies + HZ/20; link->state |= DEV_RELEASE_PENDING; @@ -1024,6 +1032,24 @@ static int mace_close(struct net_device *dev) return 0; } /* mace_close */ + +static void mace_tx_timeout (struct net_device *dev) +{ + mace_private *lp = (mace_private *)dev->priv; + dev_link_t *link = &lp->link; + + printk (KERN_NOTICE "%s: transmit timed out -- ", dev->name); +#if RESET_ON_TIMEOUT + printk ("resetting card\n"); + CardServices (ResetCard, link->handle); +#else /* #if RESET_ON_TIMEOUT */ + printk ("NOT resetting card\n"); +#endif /* #if RESET_ON_TIMEOUT */ + dev->trans_start = jiffies; + netif_start_queue (dev); +} + + /* ---------------------------------------------------------------------------- mace_start_xmit This routine begins the packet transmit function. When completed, @@ -1038,39 +1064,11 @@ static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev) { mace_private *lp = (mace_private *)dev->priv; ioaddr_t ioaddr = dev->base_addr; - dev_link_t *link = &lp->link; - -#if TIMEOUT_TX - /* Transmitter timeout. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - - if (tickssofar < (HZ/5)) - return 1; - printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name); -#if RESET_ON_TIMEOUT - printk("resetting card\n"); - CardServices(ResetCard, link->handle); -#else /* #if RESET_ON_TIMEOUT */ - printk("NOT resetting card\n"); -#endif /* #if RESET_ON_TIMEOUT */ - dev->trans_start = jiffies; - return 1; - } -#else /* #if TIMEOUT_TX */ - if (dev->tbusy) - return 1; -#endif /* #if TIMEOUT_TX */ DEBUG(3, "%s: mace_start_xmit(length = %ld) called.\n", dev->name, (long)skb->len); - /* Avoid timer-based retransmission conflicts. */ - if (test_and_set_bit(TBUSY_UNSPECIFIED, (void*)&dev->tbusy) != 0) { - printk(KERN_NOTICE "%s: transmitter access conflict.\n", - dev->name); - return 1; - } + netif_stop_queue (dev); #if (!TX_INTERRUPTABLE) /* Disable MACE TX interrupts. */ @@ -1085,11 +1083,9 @@ static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev) the upper layers. The interrupt handler is guaranteed never to service a transmit interrupt while we are in here. */ - set_bit(TBUSY_PARTIAL_TX_FRAME, (void*)&dev->tbusy); lp->linux_stats.tx_bytes += skb->len; lp->tx_free_frames--; - set_bit(TBUSY_NO_FREE_TX_FRAMES, (void*)&dev->tbusy); /* WARNING: Write the _exact_ number of bytes written in the header! */ /* Put out the word header [must be an outw()] . . . */ @@ -1105,11 +1101,10 @@ static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev) if (lp->tx_free_frames > 0) { #if MULTI_TX - clear_bit(TBUSY_NO_FREE_TX_FRAMES, (void*)&dev->tbusy); + netif_start_queue (dev); #endif /* #if MULTI_TX */ } - clear_bit(TBUSY_PARTIAL_TX_FRAME, (void*)&dev->tbusy); } #if (!TX_INTERRUPTABLE) @@ -1140,8 +1135,10 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) irq); return; } + + spin_lock (&lp->lock); - if (dev->interrupt || lp->tx_irq_disabled) { + if (lp->tx_irq_disabled) { printk( (lp->tx_irq_disabled? KERN_NOTICE "%s: Interrupt with tx_irq_disabled " @@ -1155,12 +1152,6 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* WARNING: MACE_IR has been read! */ return; } - dev->interrupt = 1; - - if (dev->start == 0) { - DEBUG(2, "%s: interrupt from dead card\n", dev->name); - goto exception; - } do { /* WARNING: MACE_IR is a READ/CLEAR port! */ @@ -1230,8 +1221,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) lp->linux_stats.tx_packets++; lp->tx_free_frames++; - clear_bit(TBUSY_NO_FREE_TX_FRAMES, (void*)&dev->tbusy); - mark_bh(NET_BH); + netif_wake_queue (dev); } /* if (status & MACE_IR_XMTINT) */ if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) { @@ -1266,8 +1256,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) } while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt)); exception: - dev->interrupt = 0; - return; + spin_unlock (&lp->lock); } /* mace_interrupt */ /* ---------------------------------------------------------------------------- diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 4a58706f6efc..897e93d03fcb 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -125,6 +125,8 @@ struct smc_private { u_short media_status; u_short fast_poll; u_long last_rx; + + spinlock_t lock; }; /* Special definitions for Megahertz multifunction cards */ @@ -281,6 +283,7 @@ static void smc91c92_release(u_long arg); static int smc91c92_event(event_t event, int priority, event_callback_args_t *args); +static void smc91c92_tx_timeout (struct net_device *dev); static int smc91c92_open(struct net_device *dev); static int smc91c92_close(struct net_device *dev); static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev); @@ -379,9 +382,12 @@ static dev_link_t *smc91c92_attach(void) dev->init = &smc91c92_init; dev->open = &smc91c92_open; dev->stop = &smc91c92_close; - dev->tbusy = 1; + dev->tx_timeout = smc91c92_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; dev->priv = link->priv = link->irq.Instance = smc; + netif_start_queue (dev); + /* Register with Card Services */ link->next = dev_list; dev_list = link; @@ -663,7 +669,7 @@ static int mot_setup(dev_link_t *link) { struct smc_private *smc = link->priv; struct net_device *dev = &smc->dev; ioaddr_t ioaddr = dev->base_addr; - int i, wait, loop; + int i, wait=0, loop; unsigned int addr; /* Read Ethernet address from Serial EEPROM */ @@ -775,7 +781,7 @@ static int osi_config(dev_link_t *link) struct smc_private *smc = link->priv; struct net_device *dev = &smc->dev; static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; - int i, j; + int i=0, j; link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; @@ -977,7 +983,7 @@ static void smc91c92_config(dev_link_t *link) dev->if_port = if_port; else printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n"); - dev->tbusy = 0; + netif_start_queue (dev); if (register_netdev(dev) != 0) { printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n"); @@ -1106,8 +1112,7 @@ static int smc91c92_event(event_t event, int priority, case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue (dev); link->release.expires = jiffies + HZ/20; link->state |= DEV_RELEASE_PENDING; add_timer(&link->release); @@ -1123,7 +1128,7 @@ static int smc91c92_event(event_t event, int priority, case CS_EVENT_RESET_PHYSICAL: if (link->state & DEV_CONFIG) { if (link->open) { - dev->tbusy = 1; dev->start = 0; + netif_stop_queue (dev); } CardServices(ReleaseConfiguration, link->handle); } @@ -1147,7 +1152,7 @@ static int smc91c92_event(event_t event, int priority, } if (link->open) { smc_reset(dev); - dev->tbusy = 0; dev->start = 1; + netif_start_queue (dev); } } break; @@ -1201,7 +1206,7 @@ static int smc91c92_open(struct net_device *dev) link->open++; MOD_INC_USE_COUNT; - dev->interrupt = 0; dev->tbusy = 0; dev->start = 1; + netif_start_queue (dev); smc->saved_skb = 0; smc->packets_waiting = 0; @@ -1225,8 +1230,7 @@ static int smc91c92_close(struct net_device *dev) DEBUG(0, "%s: smc91c92_close(), status %4.4x.\n", dev->name, inw(ioaddr + BANK_SELECT)); - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue (dev); /* Shut off all interrupts, and turn off the Tx and Rx sections. Don't bother to check for chip present. */ @@ -1240,7 +1244,7 @@ static int smc91c92_close(struct net_device *dev) SMC_SELECT_BANK( 1 ); outw(CTL_POWERDOWN, ioaddr + CONTROL ); - link->open--; dev->start = 0; + link->open--; del_timer(&smc->media); if (link->state & DEV_STALE_CONFIG) { link->release.expires = jiffies + HZ/20; @@ -1281,7 +1285,7 @@ static void smc_hardware_send_packet( struct net_device * dev ) " failed, status %#2.2x.\n", dev->name, packet_no); dev_kfree_skb (skb); smc->saved_skb = NULL; - dev->tbusy = 0; + netif_start_queue (dev); return; } @@ -1329,10 +1333,28 @@ static void smc_hardware_send_packet( struct net_device * dev ) smc->saved_skb = NULL; dev_kfree_skb (skb); dev->trans_start = jiffies; - dev->tbusy = 0; + netif_start_queue (dev); return; } +/*====================================================================*/ + +static void smc91c92_tx_timeout (struct net_device *dev) +{ + struct smc_private *smc = dev->priv; + ioaddr_t ioaddr = dev->base_addr; + + printk (KERN_NOTICE "%s: SMC91c92 transmit timed out, " + "Tx_status %2.2x status %4.4x.\n", + dev->name, inw (ioaddr) & 0xff, inw (ioaddr + 2)); + smc->stats.tx_errors++; + smc_reset (dev); + dev->trans_start = jiffies; + smc->saved_skb = NULL; + netif_start_queue (dev); +} + + /*====================================================================*/ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) @@ -1342,29 +1364,10 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned short num_pages; short time_out, ir; - /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < TX_TIMEOUT) - return 1; - printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, " - "Tx_status %2.2x status %4.4x.\n", - dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2)); - smc->stats.tx_errors++; - smc_reset(dev); - dev->trans_start = jiffies; - dev->tbusy = 0; - smc->saved_skb = NULL; - } - DEBUG(2, "%s: smc91c92_start_xmit(length = %d) called," " status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2)); - - /* Avoid timer-based retransmission conflicts. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - printk(KERN_ERR "%s: transmitter access conflict.\n", dev->name); - return 1; - } + + netif_stop_queue (dev); if ( smc->saved_skb) { /* THIS SHOULD NEVER HAPPEN. */ @@ -1500,18 +1503,13 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) u_short saved_bank, saved_pointer, mask, status; char bogus_cnt = INTR_WORK; /* Work we are willing to do. */ - if ((smc == NULL) || !dev->start) + if (smc == NULL) return; ioaddr = dev->base_addr; -#ifdef PCMCIA_DEBUG - if (dev->interrupt) { - printk(KERN_ERR "%s: re-entering the interrupt handler.\n", - dev->name); - return; - } - dev->interrupt = 1; + spin_lock (&smc->lock); +#ifdef PCMCIA_DEBUG DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name, irq, ioaddr); #endif @@ -1569,7 +1567,7 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) mask |= ( IM_TX_EMPTY_INT | IM_TX_INT ); /* and let the card send more packets to me */ - mark_bh( NET_BH ); + netif_wake_queue (dev); } if (status & IM_RX_OVRN_INT) { smc->stats.rx_errors++; @@ -1588,8 +1586,9 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) outw(saved_pointer, ioaddr + POINTER); SMC_SELECT_BANK( saved_bank ); + spin_unlock (&smc->lock); + #ifdef PCMCIA_DEBUG - dev->interrupt = 0; DEBUG(3, "%s: Exiting interrupt IRQ%d.\n", dev->name, irq); #endif @@ -1913,8 +1912,10 @@ static void media_check(u_long arg) ioaddr_t ioaddr = dev->base_addr; u_short i, media, saved_bank; +#if 0 if (dev->start == 0) goto reschedule; - +#endif + saved_bank = inw(ioaddr + BANK_SELECT); SMC_SELECT_BANK(2); i = inw(ioaddr + INTERRUPT); diff --git a/drivers/net/pcmcia/tulip_cb.c b/drivers/net/pcmcia/tulip_cb.c index ee49f58ebecc..25ffb1c2c3ed 100644 --- a/drivers/net/pcmcia/tulip_cb.c +++ b/drivers/net/pcmcia/tulip_cb.c @@ -128,7 +128,6 @@ static int csr0 = 0x00A00000 | 0x4800; /* Kernel compatibility defines, some common to David Hinds' PCMCIA package. This is only in the support-all-kernels source code. */ -#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115 MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver"); MODULE_PARM(debug, "i"); @@ -138,13 +137,11 @@ MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(csr0, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif #define RUN_AT(x) (jiffies + (x)) #define NETSTATS_VER2 #define PCI_SUPPORT_VER3 -#define dev_free_skb(skb) dev_kfree_skb(skb); #define tulip_debug debug #ifdef TULIP_DEBUG @@ -438,7 +435,8 @@ struct tulip_private { struct mediatable *mtable; int cur_index; /* Current media index. */ int saved_if_port; - unsigned char pci_bus, pci_devfn; + struct pci_dev *pdev; + spinlock_t lock; int pad0, pad1; /* Used for 8-byte alignment */ }; @@ -515,9 +513,9 @@ static void outl_CSR6 (u32 newcsr6, long ioaddr, int chip_idx) restore_flags(flags); } -static struct net_device *tulip_probe1(int pci_bus, int pci_devfn, - struct net_device *dev, long ioaddr, int irq, - int chip_idx, int board_idx) +static struct net_device *tulip_probe1(struct pci_dev *pdev, + struct net_device *dev, long ioaddr, int irq, + int chip_idx, int board_idx) { static int did_version = 0; /* Already printed version info. */ struct tulip_private *tp; @@ -534,11 +532,11 @@ static struct net_device *tulip_probe1(int pci_bus, int pci_devfn, dev = init_etherdev(dev, 0); - pcibios_read_config_byte(pci_bus, pci_devfn, PCI_REVISION_ID, &chip_rev); + pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev); /* Bring the 21143 out of sleep mode. Caution: Snooze mode does not work with some boards! */ if (tulip_tbl[chip_idx].flags & HAS_ACPI) - pcibios_write_config_dword(pci_bus, pci_devfn, 0x40, 0x00000000); + pci_write_config_dword(pdev, 0x40, 0x00000000); printk(KERN_INFO "%s: %s rev %d at %#3lx,", dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr); @@ -691,8 +689,8 @@ static struct net_device *tulip_probe1(int pci_bus, int pci_devfn, memset(tp, 0, sizeof(*tp)); dev->priv = tp; - tp->pci_bus = pci_bus; - tp->pci_devfn = pci_devfn; + tp->lock = SPIN_LOCK_UNLOCKED; + tp->pdev = pdev; tp->chip_id = chip_idx; tp->revision = chip_rev; tp->csr0 = csr0; @@ -807,6 +805,8 @@ static struct net_device *tulip_probe1(int pci_bus, int pci_devfn, #ifdef HAVE_MULTICAST dev->set_multicast_list = &set_rx_mode; #endif + dev->tx_timeout = tulip_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; /* Reset the xcvr interface and turn on heartbeat. */ switch (chip_idx) { @@ -1302,7 +1302,7 @@ tulip_up(struct net_device *dev) udelay(2); if (tulip_tbl[tp->chip_id].flags & HAS_ACPI) - pcibios_write_config_dword(tp->pci_bus, tp->pci_devfn, 0x40, 0x00000000); + pci_write_config_dword(tp->pdev, 0x40, 0x00000000); /* Clear the tx ring */ for (i = 0; i < TX_RING_SIZE; i++) { @@ -1461,15 +1461,13 @@ media_picked: outl_CSR6(tp->csr6, ioaddr, tp->chip_id); outl_CSR6(tp->csr6 | 0x2000, ioaddr, tp->chip_id); - dev->tbusy = 0; - tp->interrupt = 0; - dev->start = 1; - /* Enable interrupts by setting the interrupt mask. */ outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5); outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); outl(0, ioaddr + CSR2); /* Rx poll demand */ + + netif_start_queue (dev); if (tulip_debug > 2) { printk(KERN_DEBUG "%s: Done tulip_open(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n", @@ -2413,15 +2411,6 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) int entry; u32 flag; - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - if (jiffies - dev->trans_start < TX_TIMEOUT) - return 1; - tulip_tx_timeout(dev); - return 1; - } - /* Caution: the write order is important here, set the base address with the "ownership" bits last. */ @@ -2454,8 +2443,10 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) tp->tx_ring[entry].length = skb->len | flag; tp->tx_ring[entry].status = DescOwned; /* Pass ownership to the chip. */ tp->cur_tx++; - if ( ! tp->tx_full) - clear_bit(0, (void*)&dev->tbusy); + if (tp->tx_full) + netif_stop_queue (dev); + else + netif_wake_queue (dev); /* Trigger an immediate transmit demand. */ outl(0, dev->base_addr + CSR1); @@ -2474,21 +2465,7 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) long ioaddr = dev->base_addr; int csr5, work_budget = max_interrupt_work; -#if defined(__i386__) && defined(SMP_CHECK) - if (test_and_set_bit(0, (void*)&dev->interrupt)) { - printk(KERN_ERR "%s: Duplicate entry of the interrupt handler by " - "processor %d.\n", - dev->name, smp_processor_id()); - dev->interrupt = 0; - return; - } -#else - if (dev->interrupt) { - printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); - return; - } - dev->interrupt = 1; -#endif + spin_lock (&tp->lock); do { csr5 = inl(ioaddr + CSR5); @@ -2549,7 +2526,7 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) } /* Free the original skb. */ - dev_free_skb(tp->tx_skbuff[entry]); + dev_kfree_skb_irq(tp->tx_skbuff[entry]); tp->tx_skbuff[entry] = 0; } @@ -2561,13 +2538,15 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) } #endif - if (tp->tx_full && dev->tbusy - && tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) { - /* The ring is no longer full, clear tbusy. */ + if (tp->tx_full && + tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) + /* The ring is no longer full */ tp->tx_full = 0; - dev->tbusy = 0; - mark_bh(NET_BH); - } + + if (tp->tx_full) + netif_stop_queue (dev); + else + netif_wake_queue (dev); tp->dirty_tx = dirty_tx; if (csr5 & TxDied) { @@ -2630,12 +2609,7 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n", dev->name, inl(ioaddr + CSR5)); -#if defined(__i386__) - clear_bit(0, (void*)&dev->interrupt); -#else - dev->interrupt = 0; -#endif - return; + spin_unlock (&tp->lock); } static int @@ -2751,8 +2725,7 @@ tulip_down(struct net_device *dev) long ioaddr = dev->base_addr; struct tulip_private *tp = (struct tulip_private *)dev->priv; - dev->start = 0; - dev->tbusy = 1; + netif_stop_queue (dev); /* Disable interrupts by clearing the interrupt mask. */ outl(0x00000000, ioaddr + CSR7); @@ -2781,7 +2754,7 @@ tulip_close(struct net_device *dev) printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", dev->name, inl(ioaddr + CSR5)); - if (dev->start) + if (test_bit(LINK_STATE_START, &dev->state)) tulip_down(dev); free_irq(dev->irq, dev); @@ -2794,12 +2767,12 @@ tulip_close(struct net_device *dev) tp->rx_ring[i].length = 0; tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */ if (skb) { - dev_free_skb(skb); + dev_kfree_skb(skb); } } for (i = 0; i < TX_RING_SIZE; i++) { if (tp->tx_skbuff[i]) - dev_free_skb(tp->tx_skbuff[i]); + dev_kfree_skb(tp->tx_skbuff[i]); tp->tx_skbuff[i] = 0; } @@ -2813,7 +2786,7 @@ static struct net_device_stats *tulip_get_stats(struct net_device *dev) struct tulip_private *tp = (struct tulip_private *)dev->priv; long ioaddr = dev->base_addr; - if (dev->start) + if (test_bit(LINK_STATE_START, &dev->state)) tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; return &tp->stats; @@ -3075,8 +3048,8 @@ static void set_rx_mode(struct net_device *dev) tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame); tp->tx_ring[entry].status = DescOwned; if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) { - set_bit(0, (void*)&dev->tbusy); tp->tx_full = 1; + netif_stop_queue (dev); } if (dummy >= 0) tp->tx_ring[dummy].status = DescOwned; @@ -3114,10 +3087,11 @@ static int __devinit tulip_pci_probe(struct pci_dev *pdev, const struct pci_devi printk(KERN_INFO "tulip_attach(%s)\n", pdev->slot_name); - pci_set_master(pdev); - dev = tulip_probe1(pdev->bus->number, pdev->devfn, NULL, - pdev->resource[0].start, pdev->irq, - id->driver_data, board_idx++); + pci_enable_device (pdev); + pci_set_master (pdev); + dev = tulip_probe1(pdev, NULL, + pci_resource_start (pdev, 0), pdev->irq, + id->driver_data, board_idx++); if (dev) { pdev->driver_data = dev; return 0; diff --git a/drivers/net/pcmcia/wavelan_cs.c b/drivers/net/pcmcia/wavelan_cs.c index c1c38aa28550..b8ec9510429b 100644 --- a/drivers/net/pcmcia/wavelan_cs.c +++ b/drivers/net/pcmcia/wavelan_cs.c @@ -64,31 +64,6 @@ * (wavelan modem or i82593) */ -/*------------------------------------------------------------------*/ -/* - * Wrapper for disabling interrupts. - */ -static inline unsigned long -wv_splhi(void) -{ - unsigned long flags; - - save_flags(flags); - cli(); - - return(flags); -} - -/*------------------------------------------------------------------*/ -/* - * Wrapper for re-enabling interrupts. - */ -static inline void -wv_splx(unsigned long flags) -{ - restore_flags(flags); -} - /*------------------------------------------------------------------*/ /* * Wrapper for reporting error to cardservices @@ -581,20 +556,20 @@ void wv_roam_cleanup(struct net_device *dev) void wv_nwid_filter(unsigned char mode, net_local *lp) { mm_t m; - unsigned long x; + unsigned long flags; #ifdef WAVELAN_ROAMING_DEBUG printk(KERN_DEBUG "WaveLAN: NWID promisc %s, device %s\n",(mode==NWID_PROMISC) ? "on" : "off", lp->dev->name); #endif /* Disable interrupts & save flags */ - x = wv_splhi(); + spin_lock_irqsave (&lp->lock, flags); m.w.mmw_loopt_sel = (mode==NWID_PROMISC) ? MMW_LOOPT_SEL_DIS_NWID : 0x00; mmc_write(lp->dev->base_addr, (char *)&m.w.mmw_loopt_sel - (char *)&m, (unsigned char *)&m.w.mmw_loopt_sel, 1); /* ReEnable interrupts & restore flags */ - wv_splx(x); + spin_unlock_irqrestore (&lp->lock, flags); if(mode==NWID_PROMISC) lp->cell_search=1; @@ -755,7 +730,7 @@ void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp) { ioaddr_t base = lp->dev->base_addr; mm_t m; - unsigned long x; + unsigned long flags; if(wavepoint==lp->curr_point) /* Sanity check... */ { @@ -768,7 +743,7 @@ void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp) #endif /* Disable interrupts & save flags */ - x = wv_splhi(); + spin_lock_irqsave(&lp->lock, flags); m.w.mmw_netw_id_l = wavepoint->nwid & 0xFF; m.w.mmw_netw_id_h = (wavepoint->nwid & 0xFF00) >> 8; @@ -776,7 +751,7 @@ void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp) mmc_write(base, (char *)&m.w.mmw_netw_id_l - (char *)&m, (unsigned char *)&m.w.mmw_netw_id_l, 2); /* ReEnable interrupts & restore flags */ - wv_splx(x); + spin_unlock_irqrestore (&lp->lock, flags); wv_nwid_filter(!NWID_PROMISC,lp); lp->curr_point=wavepoint; @@ -863,15 +838,15 @@ wv_82593_cmd(device * dev, net_local * lp = (net_local *)dev->priv; int status; long spin; - u_long opri; + u_long flags; /* Spin until the chip finishes executing its current command (if any) */ do { - opri = wv_splhi(); + spin_lock_irqsave (&lp->lock, flags); outb(OP0_NOP | CR0_STATUS_3, LCCR(base)); status = inb(LCSR(base)); - wv_splx(opri); + spin_unlock_irqrestore (&lp->lock, flags); } while((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE); @@ -1009,27 +984,25 @@ read_ringbuf(device * dev, * wavelan_interrupt is not an option...), so you may experience * some delay sometime... */ -static inline void -wv_82593_reconfig(device * dev) +static inline void wv_82593_reconfig (device * dev) { - net_local * lp = (net_local *)dev->priv; - dev_link_t * link = ((net_local *) dev->priv)->link; + net_local *lp = (net_local *) dev->priv; + dev_link_t *link = ((net_local *) dev->priv)->link; - /* Check if we can do it now ! */ - if(!(link->open) || (test_and_set_bit(0, (void *)&dev->tbusy) != 0)) - { - lp->reconfig_82593 = TRUE; + /* Check if we can do it now ! */ + if (!(link->open)) { + lp->reconfig_82593 = TRUE; #ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "%s: wv_82593_reconfig(): delayed (busy = %ld, link = %d)\n", - dev->name, dev->tbusy, link->open); + printk (KERN_DEBUG "%s: wv_82593_reconfig(): delayed (link = %d)\n", + dev->name, link->open); #endif - } - else - { - lp->reconfig_82593 = FALSE; - wv_82593_config(dev); - dev->tbusy = 0; - } + } else { + netif_stop_queue (dev); + + lp->reconfig_82593 = FALSE; + wv_82593_config (dev); + netif_start_queue (dev); + } } #ifdef OLDIES @@ -1286,9 +1259,6 @@ static void wv_dev_show(device * dev) { printk(KERN_DEBUG "dev:"); - printk(" start=%d,", dev->start); - printk(" tbusy=%ld,", dev->tbusy); - printk(" interrupt=%d,", dev->interrupt); printk(" trans_start=%ld,", dev->trans_start); printk(" flags=0x%x,", dev->flags); printk("\n"); @@ -1908,7 +1878,7 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */ struct iwreq * wrq = (struct iwreq *) rq; psa_t psa; mm_t m; - unsigned long x; + unsigned long flags; int ret = 0; #ifdef DEBUG_IOCTL_TRACE @@ -1916,7 +1886,7 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */ #endif /* Disable interrupts & save flags */ - x = wv_splhi(); + spin_lock_irqsave (&lp->lock, flags); /* Look what is the request */ switch(cmd) @@ -2528,7 +2498,7 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */ } /* ReEnable interrupts & restore flags */ - wv_splx(x); + spin_unlock_irqrestore (&lp->lock, flags); #ifdef DEBUG_IOCTL_TRACE printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name); @@ -2548,14 +2518,14 @@ wavelan_get_wireless_stats(device * dev) net_local * lp = (net_local *) dev->priv; mmr_t m; iw_stats * wstats; - unsigned long x; + unsigned long flags; #ifdef DEBUG_IOCTL_TRACE printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", dev->name); #endif /* Disable interrupts & save flags */ - x = wv_splhi(); + spin_lock_irqsave (&lp->lock, flags); if(lp == (net_local *) NULL) return (iw_stats *) NULL; @@ -2583,7 +2553,7 @@ wavelan_get_wireless_stats(device * dev) wstats->discard.misc = 0L; /* ReEnable interrupts & restore flags */ - wv_splx(x); + spin_unlock_irqrestore (&lp->lock, flags); #ifdef DEBUG_IOCTL_TRACE printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", dev->name); @@ -2917,7 +2887,7 @@ wv_packet_write(device * dev, { net_local * lp = (net_local *) dev->priv; ioaddr_t base = dev->base_addr; - unsigned long x; + unsigned long flags; int clen = length; register u_short xmtdata_base = TX_BASE; @@ -2925,7 +2895,7 @@ wv_packet_write(device * dev, printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, length); #endif - x = wv_splhi(); + spin_lock_irqsave (&lp->lock, flags); /* Check if we need some padding */ if(clen < ETH_ZLEN) @@ -2963,7 +2933,7 @@ wv_packet_write(device * dev, add_timer(&lp->watchdog); } - wv_splx(x); + spin_unlock_irqrestore (&lp->lock, flags); #ifdef DEBUG_TX_INFO wv_packet_info((u_char *) buf, length, dev->name, "wv_packet_write"); @@ -2972,6 +2942,8 @@ wv_packet_write(device * dev, #ifdef DEBUG_TX_TRACE printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name); #endif + + netif_start_queue (dev); } /*------------------------------------------------------------------*/ @@ -2981,60 +2953,45 @@ wv_packet_write(device * dev, * the packet. We also prevent reentrance. Then, we call the function * to send the packet... */ -static int -wavelan_packet_xmit(struct sk_buff * skb, - device * dev) +static int wavelan_packet_xmit (struct sk_buff *skb, + device * dev) { - net_local * lp = (net_local *)dev->priv; + net_local *lp = (net_local *) dev->priv; #ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name, - (unsigned) skb); + printk (KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name, + (unsigned) skb); #endif - /* This flag indicate that the hardware can't perform a transmission. - * Theoritically, NET3 check it before sending a packet to the driver, - * but in fact it never do that and pool continuously. - * As the watchdog will abort too long transmissions, we are quite safe... - */ - if(dev->tbusy) - return(1); + /* + * For ethernet, fill in the header. + */ - /* - * For ethernet, fill in the header. - */ - - /* - * Block a timer-based transmit from overlapping a previous transmit. - * In other words, prevent reentering this routine. - */ - if(test_and_set_bit(0, (void *)&dev->tbusy) != 0) -#ifdef DEBUG_TX_ERROR - printk(KERN_INFO "%s: Transmitter access conflict.\n", dev->name); -#endif - else - { - /* If somebody has asked to reconfigure the controler, we can do it now */ - if(lp->reconfig_82593) - { - lp->reconfig_82593 = FALSE; - wv_82593_config(dev); - } + netif_stop_queue (dev); + /* + * Block a timer-based transmit from overlapping a previous transmit. + * In other words, prevent reentering this routine. + */ + if (1) { + /* If somebody has asked to reconfigure the controler, we can do it now */ + if (lp->reconfig_82593) { + lp->reconfig_82593 = FALSE; + wv_82593_config (dev); + } #ifdef DEBUG_TX_ERROR - if(skb->next) - printk(KERN_INFO "skb has next\n"); + if (skb->next) + printk (KERN_INFO "skb has next\n"); #endif - - wv_packet_write(dev, skb->data, skb->len); - } - dev_kfree_skb(skb); + wv_packet_write (dev, skb->data, skb->len); + } + dev_kfree_skb (skb); #ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name); + printk (KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name); #endif - return(0); + return (0); } /********************** HARDWARE CONFIGURATION **********************/ @@ -3245,7 +3202,8 @@ static int wv_ru_stop(device * dev) { ioaddr_t base = dev->base_addr; - unsigned long opri; + net_local *lp = (net_local *) dev->priv; + unsigned long flags; int status; int spin; @@ -3262,10 +3220,10 @@ wv_ru_stop(device * dev) do { udelay(10); - opri = wv_splhi(); + spin_lock_irqsave (&lp->lock, flags); outb(OP0_NOP | CR0_STATUS_3, LCCR(base)); status = inb(LCSR(base)); - wv_splx(opri); + spin_unlock_irqrestore (&lp->lock, flags); } while(((status & SR3_RCV_STATE_MASK) != SR3_RCV_IDLE) && (spin++ < 300)); @@ -3273,10 +3231,10 @@ wv_ru_stop(device * dev) do { udelay(10); - opri = wv_splhi(); + spin_lock_irqsave (&lp->lock, flags); outb(OP0_NOP | CR0_STATUS_3, LCCR(base)); status = inb(LCSR(base)); - wv_splx(opri); + spin_unlock_irqrestore (&lp->lock, flags); } while(((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE) && (spin++ < 300)); @@ -3347,16 +3305,16 @@ wv_ru_start(device * dev) #ifdef DEBUG_I82593_SHOW { int status; - int opri; + unsigned long flags; int i = 0; /* spin until the chip starts receiving */ do { - opri = wv_splhi(); + spin_lock_irqsave (&lp->lock, flags); outb(OP0_NOP | CR0_STATUS_3, LCCR(base)); status = inb(LCSR(base)); - wv_splx(opri); + spin_unlock_irqrestore (&lp->lock, flags); if(i++ > 10000) break; } @@ -3838,7 +3796,7 @@ wv_pcmcia_config(dev_link_t * link) /* Feed device with this info... */ dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; - dev->tbusy = 0; + netif_start_queue (dev); #ifdef DEBUG_CONFIG_INFO printk(KERN_DEBUG "wv_pcmcia_config: MEMSTART 0x%x IRQ %d IOPORT 0x%x\n", @@ -3991,13 +3949,7 @@ wavelan_interrupt(int irq, lp = (net_local *) dev->priv; base = dev->base_addr; - /* Prevent reentrance. What should we do here ? */ -#ifdef DEBUG_INTERRUPT_ERROR - if(dev->interrupt) - printk(KERN_INFO "%s: wavelan_interrupt(): Re-entering the interrupt handler.\n", - dev->name); -#endif - dev->interrupt = 1; + spin_lock (&lp->lock); /* Treat all pending interrupts */ while(1) @@ -4201,8 +4153,7 @@ wavelan_interrupt(int irq, lp->stats.collisions += (tx_status & TX_NCOL_MASK); lp->stats.tx_packets++; - dev->tbusy = FALSE; - mark_bh(NET_BH); + netif_wake_queue (dev); outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); /* Acknowledge the interrupt */ } else /* if interrupt = transmit done or retransmit done */ @@ -4214,7 +4165,8 @@ wavelan_interrupt(int irq, outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); /* Acknowledge the interrupt */ } } - dev->interrupt = FALSE; + + spin_unlock_irq (&lp->lock); #ifdef DEBUG_INTERRUPT_TRACE printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name); @@ -4296,7 +4248,7 @@ wavelan_watchdog(u_long a) #endif /* We are no more waiting for something... */ - dev->tbusy = 0; + netif_start_queue (dev); #ifdef DEBUG_INTERRUPT_TRACE printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name); @@ -4349,9 +4301,7 @@ wavelan_open(device * dev) return FALSE; if(!wv_ru_start(dev)) wv_hw_reset(dev); /* If problem : reset */ - dev->interrupt = 0; - dev->start = 1; - dev->tbusy = 0; + netif_start_queue (dev); /* Mark the device as used */ link->open++; @@ -4385,6 +4335,8 @@ wavelan_close(device * dev) (unsigned int) dev); #endif + netif_stop_queue (dev); + /* If the device isn't open, then nothing to do */ if(!link->open) { @@ -4408,10 +4360,9 @@ wavelan_close(device * dev) MOD_DEC_USE_COUNT; /* If the card is still present */ - if(dev->start) + if (test_bit(LINK_STATE_START, &dev->state)) { - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue (dev); /* Stop receiving new messages and wait end of transmission */ wv_ru_stop(dev); @@ -4549,7 +4500,7 @@ wavelan_attach(void) /* Other specific data */ /* Provide storage area for device name */ dev->name = ((net_local *)dev->priv)->node.dev_name; - dev->tbusy = 1; + netif_start_queue (dev); dev->mtu = WAVELAN_MTU; /* Register with Card Services */ @@ -4711,7 +4662,7 @@ wavelan_event(event_t event, /* The event received */ if(link->state & DEV_CONFIG) { /* Accept no more transmissions */ - dev->tbusy = 1; dev->start = 0; + netif_stop_queue (dev); /* Release the card */ wv_pcmcia_release((u_long) link); @@ -4749,8 +4700,7 @@ wavelan_event(event_t event, /* The event received */ { if(link->open) { - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue (dev); } CardServices(ReleaseConfiguration, link->handle); } @@ -4766,8 +4716,7 @@ wavelan_event(event_t event, /* The event received */ if(link->open) /* If RESET -> True, If RESUME -> False ??? */ { wv_hw_reset(dev); - dev->tbusy = 0; - dev->start = 1; + netif_start_queue (dev); } } break; diff --git a/drivers/net/pcmcia/wavelan_cs.h b/drivers/net/pcmcia/wavelan_cs.h index 0f5be4f37423..f35a81ac972c 100644 --- a/drivers/net/pcmcia/wavelan_cs.h +++ b/drivers/net/pcmcia/wavelan_cs.h @@ -550,6 +550,7 @@ typedef u_char mac_addr[WAVELAN_ADDR_SIZE]; /* Hardware address */ */ struct net_local { + spinlock_t lock; dev_node_t node; /* ???? What is this stuff ???? */ device * dev; /* Reverse link... */ dev_link_t * link; /* pcmcia structure */ @@ -609,10 +610,6 @@ void wv_roam_cleanup(struct net_device *dev); #endif /* WAVELAN_ROAMING */ /* ----------------------- MISC SUBROUTINES ------------------------ */ -static inline unsigned long /* flags */ - wv_splhi(void); /* Disable interrupts */ -static inline void - wv_splx(unsigned long); /* ReEnable interrupts : flags */ static void cs_error(client_handle_t, /* Report error to cardmgr */ int, diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 0c4f72ae7af0..b424f9e9914f 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -410,6 +410,7 @@ typedef struct local_info_t { int suspended; unsigned last_ptr_value; /* last packets transmitted value */ const char *manf_str; + spinlock_t lock; } local_info_t; /**************** @@ -429,6 +430,7 @@ static void do_reset(struct net_device *dev, int full); static int init_mii(struct net_device *dev); static void do_powerdown(struct net_device *dev); static int do_stop(struct net_device *dev); +static void xirc_tx_timeout (struct net_device *dev); /*=============== Helper functions =========================*/ static void @@ -691,6 +693,8 @@ xirc2ps_attach(void) local = kmalloc(sizeof(*local), GFP_KERNEL); if (!local) return NULL; memset(local, 0, sizeof(*local)); + + local->lock = SPIN_LOCK_UNLOCKED; link = &local->link; dev = &local->dev; link->priv = dev->priv = local; @@ -717,7 +721,9 @@ xirc2ps_attach(void) dev->init = &do_init; dev->open = &do_open; dev->stop = &do_stop; - dev->tbusy = 1; + dev->tx_timeout = xirc_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; + netif_start_queue (dev); /* Register with Card Services */ link->next = dev_list; @@ -1233,7 +1239,7 @@ xirc2ps_config(dev_link_t * link) /* we can now register the device with the net subsystem */ dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; - dev->tbusy = 0; + netif_start_queue (dev); if ((err=register_netdev(dev))) { printk(KNOT_XIRC "register_netdev() failed\n"); goto config_error; @@ -1334,7 +1340,7 @@ xirc2ps_event(event_t event, int priority, case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { - dev->tbusy = 1; dev->start = 0; + netif_stop_queue (dev); link->release.expires = jiffies + HZ / 20; add_timer(&link->release); } @@ -1349,7 +1355,7 @@ xirc2ps_event(event_t event, int priority, case CS_EVENT_RESET_PHYSICAL: if (link->state & DEV_CONFIG) { if (link->open) { - dev->tbusy = 1; dev->start = 0; + netif_stop_queue (dev); lp->suspended=1; do_powerdown(dev); } @@ -1365,7 +1371,7 @@ xirc2ps_event(event_t event, int priority, if (link->open) { do_reset(dev,1); lp->suspended=0; - dev->tbusy = 0; dev->start = 1; + netif_start_queue (dev); } } break; @@ -1393,14 +1399,8 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) * -- on a laptop? */ - if (!dev->start) - return; + spin_lock (&lp->lock); - if (dev->interrupt) { - printk(KERR_XIRC "re-entering isr on irq %d (dev=%p)\n", irq, dev); - return; - } - dev->interrupt = 1; ioaddr = dev->base_addr; if (lp->mohawk) { /* must disable the interrupt */ PutByte(XIRCREG_CR, 0); @@ -1555,8 +1555,7 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) DEBUG(0, "PTR not changed?\n"); } else lp->stats.tx_packets += lp->last_ptr_value - n; - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ + netif_wake_queue (dev); } if (tx_status & 0x0002) { /* Execessive collissions */ DEBUG(0, "tx restarted due to execssive collissions\n"); @@ -1595,7 +1594,9 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) goto loop_entry; } SelectPage(saved_page); - dev->interrupt = 0; + + spin_unlock (&lp->lock); + PutByte(XIRCREG_CR, EnableIntr); /* re-enable interrupts */ /* Instead of dropping packets during a receive, we could * force an interrupt with this command: @@ -1605,44 +1606,39 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) /*====================================================================*/ -static int -do_start_xmit(struct sk_buff *skb, struct net_device *dev) +static void xirc_tx_timeout (struct net_device *dev) { - local_info_t *lp = dev->priv; - ioaddr_t ioaddr = dev->base_addr; - int okay; - unsigned freespace; - unsigned pktlen = skb? skb->len : 0; - - DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n", - skb, dev, pktlen); - - /* Transmitter timeout, serious problems */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; + local_info_t *lp = dev->priv; if (lp->suspended) { - dev_kfree_skb (skb); dev->trans_start = jiffies; lp->stats.tx_dropped++; - return 0; + netif_start_queue (dev); + return; } - if (tickssofar < TX_TIMEOUT) - return 1; printk(KERN_NOTICE "%s: transmit timed out\n", dev->name); lp->stats.tx_errors++; /* reset the card */ do_reset(dev,1); dev->trans_start = jiffies; - dev->tbusy = 0; - } + netif_start_queue (dev); +} - if (test_and_set_bit(0, (void*)&dev->tbusy)) { - printk(KWRN_XIRC "transmitter access conflict\n"); - dev_kfree_skb (skb); - return 0; - } + +static int +do_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + local_info_t *lp = dev->priv; + ioaddr_t ioaddr = dev->base_addr; + int okay; + unsigned freespace; + unsigned pktlen = skb? skb->len : 0; + + DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n", + skb, dev, pktlen); + + netif_stop_queue (dev); /* adjust the packet length to min. required * and hope that the buffer is large enough @@ -1664,7 +1660,6 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev) DEBUG(2 + (okay ? 2 : 0), "%s: avail. tx space=%u%s\n", dev->name, freespace, okay ? " (okay)":" (not enough)"); if (!okay) { /* not enough space */ - dev->tbusy = 1; return 1; /* upper layer may decide to requeue this packet */ } /* send the packet */ @@ -1678,7 +1673,7 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev) dev_kfree_skb (skb); dev->trans_start = jiffies; - dev->tbusy = 0; + netif_start_queue (dev); lp->stats.tx_bytes += pktlen; return 0; } @@ -1823,7 +1818,7 @@ do_open(struct net_device *dev) link->open++; MOD_INC_USE_COUNT; - dev->interrupt = 0; dev->tbusy = 0; dev->start = 1; + netif_start_queue (dev); lp->suspended = 0; do_reset(dev,1); @@ -2141,8 +2136,7 @@ do_stop(struct net_device *dev) if (!link) return -ENODEV; - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue (dev); SelectPage(0); PutByte(XIRCREG_CR, 0); /* disable interrupts */ @@ -2152,7 +2146,7 @@ do_stop(struct net_device *dev) PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */ SelectPage(0); - link->open--; dev->start = 0; + link->open--; if (link->state & DEV_STALE_CONFIG) { link->release.expires = jiffies + HZ/20; link->state |= DEV_RELEASE_PENDING; diff --git a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c index 396e783c59d9..27b0c6474bcd 100644 --- a/drivers/net/rcpci45.c +++ b/drivers/net/rcpci45.c @@ -309,7 +309,6 @@ RCfound_device(int memaddr, int irq, #endif dev->base_addr = (unsigned long)vaddr; dev->irq = irq; - dev->interrupt = 0; /* * Request a shared interrupt line. @@ -430,6 +429,7 @@ RCopen(struct net_device *dev) printk("rc: RCopen: posted %d buffers\n", (uint)pDpa->numOutRcvBuffers); #endif MOD_INC_USE_COUNT; + netif_start_queue(dev); return 0; } @@ -441,29 +441,26 @@ RC_xmit_packet(struct sk_buff *skb, struct net_device *dev) singleTCB tcb; psingleTCB ptcb = &tcb; RC_RETURN status = 0; - - if (dev->tbusy || pDpa->shutdown || pDpa->reboot) - { + + netif_stop_queue(dev); + + if (pDpa->shutdown || pDpa->reboot) + { #ifdef RCDEBUG printk("rc: RC_xmit_packet: tbusy!\n"); #endif - dev->tbusy = 1; return 1; - } - - if ( skb->len <= 0 ) - { - printk("RC_xmit_packet: skb->len less than 0!\n"); - return 0; } - + /* * The user is free to reuse the TCB after RCI2OSendPacket() returns, since * the function copies the necessary info into its own private space. Thus, * our TCB can be a local structure. The skb, on the other hand, will be * freed up in our interrupt handler. */ + ptcb->bcount = 1; + /* * we'll get the context when the adapter interrupts us to tell us that * the transmision is done. At that time, we can free skb. @@ -483,13 +480,12 @@ RC_xmit_packet(struct sk_buff *skb, struct net_device *dev) #ifdef RCDEBUG printk("rc: RC send error 0x%x\n", (uint)status); #endif - dev->tbusy = 1; return 1; } else { dev->trans_start = jiffies; - // dev->tbusy = 0; + netif_wake_queue(dev); } /* * That's it! @@ -546,10 +542,9 @@ RCxmit_callback(U32 Status, printk("rc: skb = 0x%x\n", (uint)skb); #endif BufferContext++; - dev_kfree_skb (skb); + dev_kfree_skb_irq(skb); } - dev->tbusy = 0; - + netif_wake_queue(dev); } static void @@ -811,14 +806,8 @@ RCinterrupt(int irq, void *dev_id, struct pt_regs *regs) (uint)pDpa, (uint)dev, (uint)pDpa->id); printk("dev = 0x%x\n", (uint)dev); #endif - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - dev->interrupt = 1; RCProcI2OMsgQ(pDpa->id); - dev->interrupt = 0; - - return; } @@ -870,7 +859,7 @@ static void rc_timer(unsigned long data) (uint)pDpa->numOutRcvBuffers); } printk("rc: Initialization done.\n"); - dev->tbusy=0; + netif_wake_queue(dev); retry=0; return; case RC_RTN_FREE_Q_EMPTY: @@ -913,6 +902,8 @@ RCclose(struct net_device *dev) PDPA pDpa = (PDPA) dev->priv; + netif_stop_queue(dev); + #ifdef RCDEBUG printk("rc: RCclose\r\n"); #endif diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8129.c similarity index 99% rename from drivers/net/rtl8139.c rename to drivers/net/rtl8129.c index 25efb4ae435c..fad5b90ff2d9 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8129.c @@ -170,12 +170,14 @@ static struct net_device * rtl8129_probe1(struct pci_dev *pdev, int pci_bus, static struct pci_id_info pci_tbl[] = {{ "RealTek RTL8129 Fast Ethernet", 0x10ec, 0x8129, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, +#ifdef USE_8139_SUPPORT_ALSO { "RealTek RTL8139 Fast Ethernet", 0x10ec, 0x8139, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, { "SMC1211TX EZCard 10/100 (RealTek RTL8139)", 0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, { "Accton MPX5030 (RealTek RTL8139)", 0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, +#endif {0,}, /* 0 terminated list. */ }; @@ -942,6 +944,7 @@ static void rtl8129_tx_timeout(struct net_device *dev) tp->tx_full = 0; } else { tp->tx_full = 1; + netif_stop_queue(dev); } } diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c index d2756c92fda5..f7d86c10336e 100644 --- a/drivers/net/seeq8005.c +++ b/drivers/net/seeq8005.c @@ -83,6 +83,7 @@ extern int seeq8005_probe(struct net_device *dev); static int seeq8005_probe1(struct net_device *dev, int ioaddr); static int seeq8005_open(struct net_device *dev); +static void seeq8005_timeout(struct net_device *dev); static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev); static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void seeq8005_rx(struct net_device *dev); @@ -324,9 +325,11 @@ static int __init seeq8005_probe1(struct net_device *dev, int ioaddr) dev->open = seeq8005_open; dev->stop = seeq8005_close; - dev->hard_start_xmit = seeq8005_send_packet; - dev->get_stats = seeq8005_get_stats; - dev->set_multicast_list = &set_multicast_list; + dev->hard_start_xmit = seeq8005_send_packet; + dev->tx_timeout = seeq8005_timeout; + dev->watchdog_timeo = HZ/20; + dev->get_stats = seeq8005_get_stats; + dev->set_multicast_list = set_multicast_list; /* Fill in the fields of the device structure with ethernet values. */ ether_setup(dev); @@ -344,8 +347,7 @@ static int __init seeq8005_probe1(struct net_device *dev, int ioaddr) registers that "should" only need to be set once at boot, so that there is non-reboot way to recover if something goes wrong. */ -static int -seeq8005_open(struct net_device *dev) +static int seeq8005_open(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; @@ -363,46 +365,34 @@ seeq8005_open(struct net_device *dev) lp->open_time = jiffies; - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + netif_start_queue(dev); return 0; } -static int -seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev) +static void seeq8005_timeout(struct net_device *dev) { int ioaddr = dev->base_addr; - struct net_local *lp = (struct net_local *)dev->priv; + printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, + tx_done(dev) ? "IRQ conflict" : "network cable problem"); + /* Try to restart the adaptor. */ + seeq8005_init(dev, 1); + dev->trans_start = jiffies; + netif_wake_queue(dev); +} - if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) - return 1; - printk("%s: transmit timed out, %s?\n", dev->name, - tx_done(dev) ? "IRQ conflict" : "network cable problem"); - /* Try to restart the adaptor. */ - seeq8005_init(dev, 1); - dev->tbusy=0; - dev->trans_start = jiffies; - } +static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev) +{ + struct net_local *lp = (struct net_local *)dev->priv; + short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + unsigned char *buf = skb->data; - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = skb->data; - - hardware_send_packet(dev, buf, length); - dev->trans_start = jiffies; - lp->stats.tx_bytes += length; - } + /* Block a timer-based transmit from overlapping */ + netif_stop_queue(dev); + + hardware_send_packet(dev, buf, length); + dev->trans_start = jiffies; + lp->stats.tx_bytes += length; dev_kfree_skb (skb); - /* You might need to clean up and record Tx statistics here. */ return 0; @@ -410,22 +400,12 @@ seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev) /* The typical workload of the driver: Handle the network interface interrupts. */ -static void -seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs) +static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct net_device *dev = dev_id; struct net_local *lp; int ioaddr, status, boguscount = 0; - if (dev == NULL) { - printk ("net_interrupt(): irq %d for unknown device.\n", irq); - return; - } - - if (dev->interrupt) - printk ("%s: Re-entering the interrupt handler.\n", dev->name); - dev->interrupt = 1; - ioaddr = dev->base_addr; lp = (struct net_local *)dev->priv; @@ -444,8 +424,7 @@ seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs) if (status & SEEQSTAT_TX_INT) { outw( SEEQCMD_TX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); lp->stats.tx_packets++; - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ + netif_wake_queue(dev); /* Inform upper layers. */ } if (status & SEEQSTAT_RX_INT) { /* Got a packet(s). */ @@ -457,13 +436,10 @@ seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs) if(net_debug>2) { printk("%s: eoi\n",dev->name); } - dev->interrupt = 0; - return; } /* We have a good packet(s), get it/them out of the buffers. */ -static void -seeq8005_rx(struct net_device *dev) +static void seeq8005_rx(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int boguscount = 10; @@ -561,17 +537,15 @@ seeq8005_rx(struct net_device *dev) } /* The inverse routine to net_open(). */ -static int -seeq8005_close(struct net_device *dev) +static int seeq8005_close(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; lp->open_time = 0; - dev->tbusy = 1; - dev->start = 0; - + netif_stop_queue(dev); + /* Flush the Tx and disable Rx here. */ outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD); @@ -598,8 +572,7 @@ static struct net_device_stats *seeq8005_get_stats(struct net_device *dev) num_addrs > 0 Multicast mode, receive normal and MC packets, and do best-effort filtering. */ -static void -set_multicast_list(struct net_device *dev) +static void set_multicast_list(struct net_device *dev) { /* * I _could_ do up to 6 addresses here, but won't (yet?) diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c index 23644ef1d3b2..ab1664fecd0f 100644 --- a/drivers/net/smc-mca.c +++ b/drivers/net/smc-mca.c @@ -414,9 +414,8 @@ static int ultramca_close_card(struct net_device *dev) { int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */ - dev->start = 0; - dev->tbusy = 1; - + netif_stop_queue(dev); + if (ei_debug > 1) printk("%s: Shutting down ethercard.\n", dev->name); diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index 944ad87c3aa9..661c1b36355f 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -50,11 +50,8 @@ static const char *version = "smc9194.c:v0.12 03/06/96 by Erik Stahlman (erik@vt.edu)\n"; -#ifdef MODULE #include #include -#endif - #include #include #include @@ -81,22 +78,6 @@ static const char *version = . -------------------------------------------------------------------------*/ -/* - . this is for kernels > 1.2.70 -*/ -#define REALLY_NEW_KERNEL -#ifndef REALLY_NEW_KERNEL -#define free_irq( x, y ) free_irq( x ) -#define request_irq( x, y, z, u, v ) request_irq( x, y, z, u ) -#endif - -/* - . Do you want to use this with old kernels. - . WARNING: this is not well tested. -#define SUPPORT_OLD_KERNEL -*/ - - /* . Do you want to use 32 bit xfers? This should work on all chips, as . the chipset is designed to accommodate them. @@ -108,9 +89,10 @@ static const char *version = .for a slightly different card, you can add it to the array. Keep in .mind that the array must end in zero. */ -static unsigned int smc_portlist[] __initdata = - { 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, - 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0}; +static unsigned int smc_portlist[] __initdata = { + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, + 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0 +}; /* . Wait time for memory to be free. This probably shouldn't be @@ -149,12 +131,6 @@ static unsigned int smc_portlist[] __initdata = #endif -/* the older versions of the kernel cannot support autoprobing */ -#ifdef SUPPORT_OLD_KERNEL -#define NO_AUTOPROBE -#endif - - /*------------------------------------------------------------------------ . . The internal workings of the driver. If you are changing anything @@ -164,9 +140,6 @@ static unsigned int smc_portlist[] __initdata = -------------------------------------------------------------------------*/ #define CARDNAME "SMC9194" -#ifdef SUPPORT_OLD_KERNEL -char kernel_version[] = UTS_RELEASE; -#endif /* store this information for the driver.. */ struct smc_local { @@ -216,6 +189,11 @@ int smc_init(struct net_device *dev); */ static int smc_open(struct net_device *dev); +/* + . Our watchdog timed out. Called by the networking layer +*/ +static void smc_timeout(struct net_device *dev); + /* . This is called by the kernel to send a packet out into the net. it's . responsible for doing a best-effort send, but if it's simply not possible @@ -240,12 +218,12 @@ static struct net_device_stats * smc_query_statistics( struct net_device *dev); . Finally, a call to set promiscuous mode ( for TCPDUMP and related . programs ) and multicast modes. */ -#ifdef SUPPORT_OLD_KERNEL -static void smc_set_multicast_list(struct net_device *dev, int num_addrs, - void *addrs); -#else static void smc_set_multicast_list(struct net_device *dev); -#endif + +/* + . CRC compute + */ +static int crc32( char * s, int length ); /*--------------------------------------------------------------- . @@ -256,11 +234,7 @@ static void smc_set_multicast_list(struct net_device *dev); /* . Handles the actual interrupt */ -#ifdef REALLY_NEW_KERNEL static void smc_interrupt(int irq, void *, struct pt_regs *regs); -#else -static void smc_interrupt(int irq, struct pt_regs *regs); -#endif /* . This is a separate procedure to handle the receipt of a packet, to . leave the interrupt code looking slightly cleaner @@ -321,25 +295,9 @@ static void smc_enable( int ioaddr ); /* this puts the device in an inactive state */ static void smc_shutdown( int ioaddr ); -#ifndef NO_AUTOPROBE /* This routine will find the IRQ of the driver if one is not . specified in the input to the device. */ static int smc_findirq( int ioaddr ); -#endif - -/* - this routine will set the hardware multicast table to the specified - values given it by the higher level routines -*/ -#ifndef SUPPORT_OLD_KERNEL -static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * ); -static int crc32( char *, int ); -#endif - -#ifdef SUPPORT_OLD_KERNEL -extern struct net_device *init_etherdev(struct net_device *dev, int sizeof_private, - unsigned long *mem_startp ); -#endif /* . Function: smc_reset( int ioaddr ) @@ -442,7 +400,6 @@ static void smc_shutdown( int ioaddr ) } -#ifndef SUPPORT_OLD_KERNEL /* . Function: smc_setmulticast( int ioaddr, int count, dev_mc_list * adds ) . Purpose: @@ -525,8 +482,6 @@ static int crc32( char * s, int length ) { return crc_value; } -#endif - /* . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * ) @@ -575,6 +530,7 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * de dev_kfree_skb (skb); lp->saved_skb = NULL; /* this IS an error, but, i don't want the skb saved */ + netif_wake_queue(dev); return 0; } /* either way, a packet is waiting now */ @@ -616,7 +572,7 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * de } /* or YES! I can send the packet now.. */ smc_hardware_send_packet(dev); - + netif_wake_queue(dev); return 0; } @@ -663,7 +619,7 @@ static void smc_hardware_send_packet( struct net_device * dev ) printk(KERN_DEBUG CARDNAME": Memory allocation failed. \n"); kfree(skb); lp->saved_skb = NULL; - dev->tbusy = 0; + netif_wake_queue(dev); return; } @@ -729,8 +685,7 @@ static void smc_hardware_send_packet( struct net_device * dev ) dev->trans_start = jiffies; /* we can send another packet */ - dev->tbusy = 0; - + netif_wake_queue(dev); return; } @@ -787,7 +742,6 @@ int __init smc_init(struct net_device *dev) return -ENODEV; } -#ifndef NO_AUTOPROBE /*---------------------------------------------------------------------- . smc_findirq . @@ -860,7 +814,6 @@ int __init smc_findirq( int ioaddr ) /* and return what I found */ return autoirq_report( 0 ); } -#endif /*---------------------------------------------------------------------- . Function: smc_probe( int ioaddr ) @@ -962,14 +915,7 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr) /* see if I need to initialize the ethernet card structure */ if (dev == NULL) { -#ifdef SUPPORT_OLD_KERNEL -#ifndef MODULE -/* note: the old module interface does not support this call */ - dev = init_etherdev( 0, sizeof( struct smc_local ), 0 ); -#endif -#else dev = init_etherdev(0, 0); -#endif if (dev == NULL) return -ENOMEM; } @@ -1043,7 +989,6 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr) . what (s)he is doing. No checking is done!!!! . */ -#ifndef NO_AUTOPROBE if ( dev->irq < 2 ) { int trials; @@ -1060,13 +1005,6 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr) printk(CARDNAME": Couldn't autodetect your IRQ. Use irq=xx.\n"); return -ENODEV; } -#else - if (dev->irq == 0 ) { - printk(CARDNAME - ": Autoprobing IRQs is not supported for old kernels.\n"); - return -ENODEV; - } -#endif if (dev->irq == 2) { /* Fixup for users that don't know that IRQ 2 is really IRQ 9, * or don't know which one to set. @@ -1114,10 +1052,10 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr) dev->open = smc_open; dev->stop = smc_close; dev->hard_start_xmit = smc_send_packet; + dev->tx_timeout = smc_timeout; + dev->watchdog_timeo = HZ/20; dev->get_stats = smc_query_statistics; -#ifdef HAVE_MULTICAST - dev->set_multicast_list = &smc_set_multicast_list; -#endif + dev->set_multicast_list = smc_set_multicast_list; return 0; } @@ -1174,12 +1112,7 @@ static int smc_open(struct net_device *dev) /* clear out all the junk that was put here before... */ memset(dev->priv, 0, sizeof(struct smc_local)); - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; -#ifdef MODULE MOD_INC_USE_COUNT; -#endif /* reset the hardware */ @@ -1211,6 +1144,8 @@ static int smc_open(struct net_device *dev) address |= dev->dev_addr[ i ]; outw( address, ioaddr + ADDR0 + i ); } + + netif_start_queue(dev); return 0; } @@ -1220,38 +1155,29 @@ static int smc_open(struct net_device *dev) . skeleton.c, from Becker. .-------------------------------------------------------- */ -static int smc_send_packet(struct sk_buff *skb, struct net_device *dev) + +static void smc_timeout(struct net_device *dev) { - if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) - return 1; - printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n", - tx_done(dev) ? "IRQ conflict" : - "network cable problem"); - /* "kick" the adaptor */ - smc_reset( dev->base_addr ); - smc_enable( dev->base_addr ); - - dev->tbusy = 0; - dev->trans_start = jiffies; - /* clear anything saved */ - ((struct smc_local *)dev->priv)->saved_skb = NULL; - } + /* If we get here, some higher level has decided we are broken. + There should really be a "kick me" function call instead. */ + printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n", + tx_done(dev) ? "IRQ conflict" : + "network cable problem"); + /* "kick" the adaptor */ + smc_reset( dev->base_addr ); + smc_enable( dev->base_addr ); + dev->trans_start = jiffies; + /* clear anything saved */ + ((struct smc_local *)dev->priv)->saved_skb = NULL; + netif_wake_queue(dev); +} - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - printk(KERN_WARNING CARDNAME": Transmitter access conflict.\n"); - dev_kfree_skb (skb); - } else { - /* Well, I want to send the packet.. but I don't know - if I can send it right now... */ - return smc_wait_to_send_packet( skb, dev ); - } - return 0; +static int smc_send_packet(struct sk_buff *skb, struct net_device *dev) +{ + netif_stop_queue(dev); + /* Well, I want to send the packet.. but I don't know + if I can send it right now... */ + return smc_wait_to_send_packet( skb, dev ); } /*-------------------------------------------------------------------- @@ -1266,11 +1192,8 @@ static int smc_send_packet(struct sk_buff *skb, struct net_device *dev) . and finally restore state. . ---------------------------------------------------------------------*/ -#ifdef REALLY_NEW_KERNEL + static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs) -#else -static void smc_interrupt(int irq, struct pt_regs * regs) -#endif { struct net_device *dev = dev_id; int ioaddr = dev->base_addr; @@ -1288,20 +1211,6 @@ static void smc_interrupt(int irq, struct pt_regs * regs) PRINTK3((CARDNAME": SMC interrupt started \n")); - if (dev == NULL) { - printk(KERN_WARNING CARDNAME": irq %d for unknown device.\n", - irq); - return; - } - -/* will Linux let this happen ?? If not, this costs some speed */ - if ( dev->interrupt ) { - printk(KERN_WARNING CARDNAME": interrupt inside interrupt.\n"); - return; - } - - dev->interrupt = 1; - saved_bank = inw( ioaddr + BANK_SELECT ); SMC_SELECT_BANK(2); @@ -1346,12 +1255,7 @@ static void smc_interrupt(int irq, struct pt_regs * regs) lp->stats.collisions += card_stats & 0xF; /* these are for when linux supports these statistics */ -#if 0 - card_stats >>= 4; - /* deferred */ - card_stats >>= 4; - /* excess deferred */ -#endif + SMC_SELECT_BANK( 2 ); PRINTK2((KERN_WARNING CARDNAME ": TX_BUFFER_EMPTY handled\n")); @@ -1372,8 +1276,8 @@ static void smc_interrupt(int irq, struct pt_regs * regs) mask |= ( IM_TX_EMPTY_INT | IM_TX_INT ); /* and let the card send more packets to me */ - mark_bh( NET_BH ); - + netif_wake_queue(dev); + PRINTK2((CARDNAME": Handoff done successfully.\n")); } else if (status & IM_RX_OVRN_INT ) { lp->stats.rx_errors++; @@ -1397,7 +1301,6 @@ static void smc_interrupt(int irq, struct pt_regs * regs) SMC_SELECT_BANK( saved_bank ); - dev->interrupt = 0; PRINTK3((CARDNAME ": Interrupt done\n")); return; } @@ -1462,11 +1365,7 @@ static void smc_rcv(struct net_device *dev) if ( status & RS_MULTICAST ) lp->stats.multicast++; -#ifdef SUPPORT_OLD_KERNEL - skb = alloc_skb( packet_length + 5, GFP_ATOMIC ); -#else skb = dev_alloc_skb( packet_length + 5); -#endif if ( skb == NULL ) { printk(KERN_NOTICE CARDNAME @@ -1478,18 +1377,12 @@ static void smc_rcv(struct net_device *dev) ! This should work without alignment, but it could be ! in the worse case */ -#ifndef SUPPORT_OLD_KERNEL - /* TODO: Should I use 32bit alignment here ? */ + skb_reserve( skb, 2 ); /* 16 bit alignment */ -#endif skb->dev = dev; -#ifdef SUPPORT_OLD_KERNEL - skb->len = packet_length; - data = skb->data; -#else data = skb_put( skb, packet_length); -#endif + #ifdef USE_32_BIT /* QUESTION: Like in the TX routine, do I want to send the DWORDs or the bytes first, or some @@ -1516,9 +1409,7 @@ static void smc_rcv(struct net_device *dev) print_packet( data, packet_length ); #endif -#ifndef SUPPORT_OLD_KERNEL skb->protocol = eth_type_trans(skb, dev ); -#endif netif_rx(skb); lp->stats.rx_packets++; } else { @@ -1616,17 +1507,12 @@ static void smc_tx( struct net_device * dev ) -----------------------------------------------------*/ static int smc_close(struct net_device *dev) { - dev->tbusy = 1; - dev->start = 0; - + netif_stop_queue(dev); /* clear everything */ smc_shutdown( dev->base_addr ); /* Update the statistics here. */ -#ifdef MODULE MOD_DEC_USE_COUNT; -#endif - return 0; } @@ -1648,21 +1534,12 @@ static struct net_device_stats* smc_query_statistics(struct net_device *dev) { . promiscuous mode ( for TCPDUMP and cousins ) or accept . a select set of multicast packets */ -#ifdef SUPPORT_OLD_KERNEL -static void smc_set_multicast_list( struct net_device * dev, - int num_addrs, void * addrs ) -#else static void smc_set_multicast_list(struct net_device *dev) -#endif { short ioaddr = dev->base_addr; SMC_SELECT_BANK(0); -#ifdef SUPPORT_OLD_KERNEL - if ( num_addrs < 0 ) -#else if ( dev->flags & IFF_PROMISC ) -#endif outw( inw(ioaddr + RCR ) | RCR_PROMISC, ioaddr + RCR ); /* BUG? I never disable promiscuous mode if multicasting was turned on. @@ -1674,27 +1551,12 @@ static void smc_set_multicast_list(struct net_device *dev) I don't need to zero the multicast table, because the flag is checked before the table is */ -#ifdef SUPPORT_OLD_KERNEL - else if ( num_addrs > 20 ) /* arbitrary constant */ -#else else if (dev->flags & IFF_ALLMULTI) -#endif outw( inw(ioaddr + RCR ) | RCR_ALMUL, ioaddr + RCR ); /* We just get all multicast packets even if we only want them . from one source. This will be changed at some future . point. */ -#ifdef SUPPORT_OLD_KERNEL - else if (num_addrs > 0 ) { -/* the old kernel support will not have hardware multicast support. It would - involve more kludges, and make the multicast setting code even worse. - Instead, just use the ALMUL method. This is reasonable, considering that - it is seldom used -*/ - outw( inw( ioaddr + RCR ) & ~RCR_PROMISC, ioaddr + RCR ); - outw( inw( ioadddr + RCR ) | RCR_ALMUL, ioadddr + RCR ); - } -#else else if (dev->mc_count ) { /* support hardware multicasting */ @@ -1705,7 +1567,6 @@ static void smc_set_multicast_list(struct net_device *dev) last thing called. The bank is set to zero at the top */ smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list ); } -#endif else { outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL), ioaddr + RCR ); diff --git a/drivers/net/strip.c b/drivers/net/strip.c index 2f3eb9076782..ee31cb4ca314 100644 --- a/drivers/net/strip.c +++ b/drivers/net/strip.c @@ -1036,9 +1036,7 @@ static void strip_unlock(struct strip *strip_info) */ strip_info->idle_timer.expires = jiffies + 1*HZ; add_timer(&strip_info->idle_timer); - if (!test_and_clear_bit(0, (void *)&strip_info->dev.tbusy)) - printk(KERN_ERR "%s: trying to unlock already unlocked device!\n", - strip_info->dev.name); + netif_wake_queue(&strip_info->dev); } @@ -1355,7 +1353,8 @@ static void strip_write_some_more(struct tty_struct *tty) struct strip *strip_info = (struct strip *) tty->disc_data; /* First make sure we're connected. */ - if (!strip_info || strip_info->magic != STRIP_MAGIC || !strip_info->dev.start) + if (!strip_info || strip_info->magic != STRIP_MAGIC || + !test_bit(LINK_STATE_START, &strip_info->dev.state)) return; if (strip_info->tx_left > 0) @@ -1387,7 +1386,6 @@ static void strip_write_some_more(struct tty_struct *tty) { tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); strip_unlock(strip_info); - mark_bh(NET_BH); } } @@ -1646,12 +1644,14 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev) { struct strip *strip_info = (struct strip *)(dev->priv); - if (!dev->start) + if (!test_bit(LINK_STATE_START, &dev->state)) { printk(KERN_ERR "%s: xmit call when iface is down\n", dev->name); return(1); } - if (test_and_set_bit(0, (void *) &strip_info->dev.tbusy)) return(1); + + netif_stop_queue(dev); + del_timer(&strip_info->idle_timer); /* See if someone has been ifconfigging */ @@ -1687,7 +1687,8 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev) strip_send(strip_info, skb); - if (skb) dev_kfree_skb(skb); + if (skb) + dev_kfree_skb(skb); return(0); } @@ -2336,7 +2337,8 @@ strip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int struct strip *strip_info = (struct strip *) tty->disc_data; const unsigned char *end = cp + count; - if (!strip_info || strip_info->magic != STRIP_MAGIC || !strip_info->dev.start) + if (!strip_info || strip_info->magic != STRIP_MAGIC + || !test_bit(LINK_STATE_START, &strip_info->dev.state)) return; /* Argh! mtu change time! - costs us the packet part received at the change */ @@ -2507,13 +2509,11 @@ static int strip_open_low(struct net_device *dev) if (in_dev->ifa_list->ifa_address == 0) in_dev->ifa_list->ifa_address = ntohl(0xC0A80001); #endif - dev->tbusy = 0; - dev->start = 1; - printk(KERN_INFO "%s: Initializing Radio.\n", strip_info->dev.name); ResetRadio(strip_info); strip_info->idle_timer.expires = jiffies + 1*HZ; add_timer(&strip_info->idle_timer); + netif_wake_queue(dev); return(0); } @@ -2529,9 +2529,9 @@ static int strip_close_low(struct net_device *dev) if (strip_info->tty == NULL) return -EBUSY; strip_info->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue(dev); + /* * Free all STRIP frame buffers. */ diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c index e11c9bcfe5f6..47196db9c7fb 100644 --- a/drivers/net/wan/cycx_x25.c +++ b/drivers/net/wan/cycx_x25.c @@ -502,12 +502,10 @@ static int if_open (struct net_device *dev) x25_channel_t *chan = dev->priv; cycx_t *card = chan->card; - if (dev->start) + if (test_bit(LINK_STATE_START, &dev->state)) return -EBUSY; /* only one open is allowed */ - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; + netif_start_queue(dev); cyclomx_mod_inc_use_count(card); return 0; @@ -521,8 +519,8 @@ static int if_close (struct net_device *dev) x25_channel_t *chan = dev->priv; cycx_t *card = chan->card; - dev->start = 0; - + netif_stop_queue(dev); + if (chan->state == WAN_CONNECTED || chan->state == WAN_CONNECTING) chan_disconnect(dev); @@ -556,7 +554,7 @@ static int if_rebuild_hdr (struct sk_buff *skb) } /* Send a packet on a network interface. - * o set tbusy flag (marks start of the transmission). + * o set busy flag (marks start of the transmission). * o check link state. If link is not up, then drop the packet. * o check channel status. If it's down then initiate a call. * o pass a packet to corresponding WAN device. @@ -575,11 +573,6 @@ static int if_send (struct sk_buff *skb, struct net_device *dev) x25_channel_t *chan = dev->priv; cycx_t *card = chan->card; - if (dev->tbusy) { - ++chan->ifstats.rx_dropped; - return -EBUSY; - } - if (!chan->svc) chan->protocol = skb->protocol; @@ -595,14 +588,14 @@ static int if_send (struct sk_buff *skb, struct net_device *dev) switch (chan->state) { case WAN_DISCONNECTED: if (chan_connect(dev)) { - dev->tbusy = 1; + netif_stop_queue(dev); return -EBUSY; } /* fall thru */ case WAN_CONNECTED: reset_timer(dev); dev->trans_start = jiffies; - dev->tbusy = 1; + netif_stop_queue(dev); if (chan_send(dev, skb)) return -EBUSY; @@ -632,8 +625,8 @@ static int if_send (struct sk_buff *skb, struct net_device *dev) skb_pull(skb, 1); /* Remove control byte */ reset_timer(dev); dev->trans_start = jiffies; - dev->tbusy = 1; - + netif_stop_queue(dev); + if (chan_send(dev, skb)) { /* prepare for future retransmissions */ skb_push(skb, 1); @@ -705,9 +698,6 @@ static void cyx_isr (cycx_t *card) cycx_poke(&card->hw, 0, &z, sizeof(z)); cycx_poke(&card->hw, X25_RXMBOX_OFFS, &z, sizeof(z)); card->in_isr = 0; - - if (card->buff_int_mode_unbusy) - mark_bh(NET_BH); } /* Transmit interrupt handler. @@ -724,7 +714,7 @@ static void tx_intr (cycx_t *card, TX25Cmd *cmd) /* unbusy device and then dev_tint(); */ if ((dev = get_dev_by_lcn(wandev, lcn)) != NULL) { card->buff_int_mode_unbusy = 1; - dev->tbusy = 0; + netif_wake_queue(dev); } else printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n", card->devname, lcn); @@ -1357,7 +1347,7 @@ static void set_chan_state (struct net_device *dev, u8 state) case WAN_CONNECTED: string_state = "connected!"; *(u16*)dev->dev_addr = htons(chan->lcn); - dev->tbusy = 0; + netif_wake_queue(dev); reset_timer(dev); if (chan->protocol == ETH_P_X25) @@ -1384,7 +1374,7 @@ static void set_chan_state (struct net_device *dev, u8 state) if (chan->protocol == ETH_P_X25) chan_x25_send_event(dev, 2); - dev->tbusy = 0; + netif_wake_queue(dev); break; } @@ -1560,14 +1550,14 @@ static void x25_dump_devs(wan_device_t *wandev) struct net_device *dev = wandev->dev; printk(KERN_INFO "X.25 dev states\n"); - printk(KERN_INFO "name: addr: tbusy: protocol:\n"); + printk(KERN_INFO "name: addr: txoff: protocol:\n"); printk(KERN_INFO "---------------------------------------\n"); for (; dev; dev = dev->slave) { x25_channel_t *chan = dev->priv; - printk(KERN_INFO "%-5.5s %-15.15s %ld ETH_P_%s\n", - chan->name, chan->addr, dev->tbusy, + printk(KERN_INFO "%-5.5s %-15.15s %d ETH_P_%s\n", + chan->name, chan->addr, test_bit(LINK_STATE_XOFF, &dev->state), chan->protocol == ETH_P_IP ? "IP" : "X25"); } } diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index a4564afcb064..56e4f372242f 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -163,7 +163,7 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe dev = lapbeth_get_x25_dev(dev); - if (dev == NULL || dev->start == 0) { + if (dev == NULL || test_bit(LINK_STATE_START, &dev->state) == 0) { kfree_skb(skb); return 0; } @@ -215,7 +215,7 @@ static int lapbeth_xmit(struct sk_buff *skb, struct net_device *dev) * Just to be *really* sure not to send anything if the interface * is down, the ethernet device may have gone. */ - if (!dev->start) { + if (!test_bit(LINK_STATE_START, &dev->state)) { lapbeth_check_devices(dev); kfree_skb(skb); return -ENODEV; @@ -360,9 +360,6 @@ static int lapbeth_open(struct net_device *dev) if (lapbeth_check_devices(dev)) return -ENODEV; /* oops, it's gone */ - dev->tbusy = 0; - dev->start = 1; - lapbeth = (struct lapbethdev *)dev->priv; lapbeth_callbacks.connect_confirmation = lapbeth_connected; @@ -374,12 +371,11 @@ static int lapbeth_open(struct net_device *dev) if ((err = lapb_register(lapbeth, &lapbeth_callbacks)) != LAPB_OK) { printk(KERN_ERR "lapbeth: lapb_register error - %d\n", err); - dev->tbusy = 1; - dev->start = 0; return -ENODEV; } MOD_INC_USE_COUNT; + netif_start_queue(dev); return 0; } @@ -389,9 +385,8 @@ static int lapbeth_close(struct net_device *dev) struct lapbethdev *lapbeth; int err; - dev->tbusy = 1; - dev->start = 0; - + netif_stop_queue(dev); + lapbeth = (struct lapbethdev *)dev->priv; if ((err = lapb_unregister(lapbeth)) != LAPB_OK) diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 4cf0c05a1c34..1aa7afc2087a 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -59,11 +59,6 @@ #include -#if LINUX_VERSION_CODE >=0x020200 -#define v22 -#endif - - #include #include #include @@ -74,6 +69,7 @@ #include #include #include +#include #include #include @@ -88,12 +84,8 @@ #include - - -#ifdef v22 #include #include -#endif #include "sbni.h" @@ -523,6 +515,7 @@ static int __init sbni_probe1(struct net_device *dev, int ioaddr) dev->hard_header_cache = sbni_header_cache; dev->header_cache_update = sbni_header_cache_update; + spin_lock_init(&lp->lock); lp->m=dev; lp->me=dev; lp->next_lp=NULL; @@ -538,15 +531,15 @@ static int sbni_open(struct net_device *dev) { struct net_local* lp = (struct net_local*)dev->priv; struct timer_list* watchdog = &lp->watchdog; - + unsigned long flags; DP( printk("%s: sbni_open\n", dev->name); ) + save_flags(flags); cli(); lp->currframe = NULL; card_start(dev); - dev->start = 1; /* set timer watchdog */ init_timer(watchdog); watchdog->expires = jiffies + SBNI_TIMEOUT; @@ -555,8 +548,9 @@ static int sbni_open(struct net_device *dev) add_timer(watchdog); DP( printk("%s: sbni timer watchdog initialized\n", dev->name); ); - sti(); - + restore_flags(flags); + + netif_start_queue(dev); MOD_INC_USE_COUNT; return 0; } @@ -566,21 +560,18 @@ static int sbni_close(struct net_device *dev) int ioaddr = dev->base_addr; struct net_local* lp = (struct net_local*) dev->priv; struct timer_list* watchdog = &lp->watchdog; - - + unsigned long flags; + DP( printk("%s: sbni_close\n", dev->name); ) + netif_stop_queue(dev); + + save_flags(flags); cli(); - sbni_drop_tx_queue(dev); - - dev->tbusy = 1; - dev->start = 0; - del_timer(watchdog); - outb(0, ioaddr + CSR0); - sti(); + restore_flags(flags); MOD_DEC_USE_COUNT; return 0; @@ -590,6 +581,7 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_local *lp = (struct net_local*)dev->priv; struct sbni_hard_header *hh=(struct sbni_hard_header *)skb->data; + unsigned long flags; #ifdef KATYUSHA struct net_local *nl; @@ -602,13 +594,6 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev) if(lp->me != dev) panic("sbni: lp->me != dev !!!\nMail to developer (xenon@granch.ru) if you noticed this error\n"); - if(dev->interrupt) - { - DP( printk("sbni_xmit_start: interrupt\n"); ) - /* May be unloading, don't stamp on */ - return 1; /* the packet buffer this time */ - } - hh->number = 1; hh->reserv = 0; @@ -623,6 +608,7 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->len - sizeof(struct sbni_hard_header), hh->crc); + spin_lock_irqsave(&lp->lock, flags); #ifdef KATYUSHA /* looking for first idle device */ for (stop=0,nl=lp; nl && !stop; nl=nl->next_lp) @@ -657,6 +643,7 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev) /* set request for transmit */ outb(inb(dev->base_addr + CSR0) | TR_REQ, dev->base_addr + CSR0); #endif + spin_unlock_irqrestore(&lp->lock, flags); return 0; } @@ -677,9 +664,6 @@ void card_start(struct net_device *dev) lp->waitack=0; skb_queue_head_init(&lp->queue); sbni_drop_tx_queue(dev); - dev->tbusy = 0; - - dev->interrupt = 0; /* Reset the card and set start parameters */ outb(PR_RES | *(char*)&lp->csr1, dev->base_addr + CSR1); outb(EN_INT, dev->base_addr + CSR0); @@ -776,8 +760,7 @@ static inline unsigned short sbni_recv(struct net_device *dev) /* * reset output active flags */ - dev->tbusy = 0; - mark_bh(NET_BH); + netif_wake_queue(dev); /*} if */ } case PACKET_RESEND: @@ -920,17 +903,12 @@ static void sbni_interrupt(int irq, void *dev_id, struct pt_regs *regs) return; } - if(dev->interrupt) - { - printk("%s: Reentering the interrupt driver!\n", dev->name); - return; - } - dev->interrupt = 1; - csr0 = inb(dev->base_addr + CSR0); DP( printk("%s: entering interrupt handler, CSR0 = %02x\n", dev->name, csr0); ) lp=dev->priv; + + spin_lock(&lp->lock); if(!lp->carrier) lp->carrier=1; @@ -971,7 +949,7 @@ static void sbni_interrupt(int irq, void *dev_id, struct pt_regs *regs) */ outb(csr0 | EN_INT, dev->base_addr + CSR0); - dev->interrupt = 0; + spin_unlock(&lp->lock); } static struct enet_statistics *sbni_get_stats(struct net_device *dev) @@ -1103,7 +1081,7 @@ static void sbni_watchdog(unsigned long arg) } sti(); outb(csr0 | RC_CHK, dev->base_addr + CSR0); - if(dev->start) + if(test_bit(LINK_STATE_START, &dev->state)) { struct timer_list* watchdog = &lp->watchdog; init_timer(watchdog); @@ -1167,9 +1145,8 @@ static void sbni_drop_tx_queue(struct net_device *dev) } } lp->waitack=0; - dev->tbusy = 0; - - mark_bh(NET_BH); + netif_wake_queue(dev); + DP( printk("%s: queue dropping stoped\n",dev->name); ); } @@ -1194,7 +1171,7 @@ static int sbni_set_mac_address(struct net_device *dev, void *addr) /* struct net_local *lp = (struct net_local *)dev->priv; */ struct sockaddr *saddr = addr; - if(dev->start) + if(test_bit(LINK_STATE_START, &dev->state)) { /* Only possible while card isn't started */ return -EBUSY; @@ -1400,13 +1377,11 @@ static int rxl[SBNI_MAX_NUM_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; static int baud[SBNI_MAX_NUM_CARDS] = { 0 }; static long mac[SBNI_MAX_NUM_CARDS] = { 0 }; -#ifdef v22 MODULE_PARM(io, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i"); MODULE_PARM(rxl, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i"); MODULE_PARM(baud, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i"); MODULE_PARM(mac, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i"); -#endif static int sbniautodetect = -1; diff --git a/drivers/net/wan/sbni.h b/drivers/net/wan/sbni.h index 2e34d8d3451d..56550d8f2812 100644 --- a/drivers/net/wan/sbni.h +++ b/drivers/net/wan/sbni.h @@ -146,7 +146,7 @@ struct net_local { int carrier; - + spinlock_t lock; }; diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index e50865d97907..be92deae42fa 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -205,8 +205,7 @@ static void x25_asy_changed_mtu(struct x25_asy *sl) static inline void x25_asy_lock(struct x25_asy *sl) { - if (test_and_set_bit(0, (void *) &sl->dev->tbusy)) - printk("%s: trying to lock already locked device!\n", sl->dev->name); + netif_stop_queue(sl->dev); } @@ -214,8 +213,7 @@ static inline void x25_asy_lock(struct x25_asy *sl) static inline void x25_asy_unlock(struct x25_asy *sl) { - if (!test_and_clear_bit(0, (void *)&sl->dev->tbusy)) - printk("%s: trying to unlock already unlocked device!\n", sl->dev->name); + netif_wake_queue(sl->dev); } /* Send one completely decapsulated IP datagram to the IP layer. */ @@ -303,7 +301,7 @@ static void x25_asy_write_wakeup(struct tty_struct *tty) struct x25_asy *sl = (struct x25_asy *) tty->disc_data; /* First make sure we're connected. */ - if (!sl || sl->magic != X25_ASY_MAGIC || !sl->dev->start) + if (!sl || sl->magic != X25_ASY_MAGIC || !test_bit(LINK_STATE_START, &sl->dev->state)) return; if (sl->xleft <= 0) @@ -313,7 +311,6 @@ static void x25_asy_write_wakeup(struct tty_struct *tty) sl->tx_packets++; tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); x25_asy_unlock(sl); - mark_bh(NET_BH); return; } @@ -322,6 +319,20 @@ static void x25_asy_write_wakeup(struct tty_struct *tty) sl->xhead += actual; } +static void x25_asy_timeout(struct net_device *dev) +{ + struct x25_asy *sl = (struct x25_asy*)(dev->priv); + /* May be we must check transmitter timeout here ? + * 14 Oct 1994 Dmitry Gorodchanin. + */ + printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, + (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ? + "bad line quality" : "driver error"); + sl->xleft = 0; + sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + x25_asy_unlock(sl); +} + /* Encapsulate an IP datagram and kick it into a TTY queue. */ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev) @@ -329,7 +340,7 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev) struct x25_asy *sl = (struct x25_asy*)(dev->priv); int err; - if (!dev->start) + if (!test_bit(LINK_STATE_START, &sl->dev->state)) { printk("%s: xmit call when iface is down\n", dev->name); return 1; @@ -361,25 +372,6 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev) * So, no queues ! * 14 Oct 1994 Dmitry Gorodchanin. */ - if (dev->tbusy) { - /* May be we must check transmitter timeout here ? - * 14 Oct 1994 Dmitry Gorodchanin. - */ -#ifdef SL_CHECK_TRANSMIT - if (jiffies - dev->trans_start < 20 * HZ) { - /* 20 sec timeout not reached */ - return 1; - } - printk("%s: transmit timed out, %s?\n", dev->name, - (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ? - "bad line quality" : "driver error"); - sl->xleft = 0; - sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); - x25_asy_unlock(sl); -#else - return 1; -#endif - } if((err=lapb_data_request(sl,skb))!=LAPB_OK) { @@ -414,7 +406,7 @@ static void x25_asy_data_indication(void *token, struct sk_buff *skb) static void x25_asy_data_transmit(void *token, struct sk_buff *skb) { struct x25_asy *sl=token; - if(sl->dev->tbusy) + if(test_bit(LINK_STATE_XOFF, &sl->dev->state)) { printk(KERN_ERR "x25_asy: tbusy drop\n"); kfree_skb(skb); @@ -514,10 +506,8 @@ static int x25_asy_open(struct net_device *dev) sl->xleft = 0; sl->flags &= (1 << SLF_INUSE); /* Clear ESCAPE & ERROR flags */ - dev->tbusy = 0; -/* dev->flags |= IFF_UP; */ - dev->start = 1; - + netif_start_queue(dev); + /* * Now attach LAPB */ @@ -551,12 +541,9 @@ static int x25_asy_close(struct net_device *dev) return -EBUSY; sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue(dev); if((err=lapb_unregister(sl))!=LAPB_OK) printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err); - -/* dev->flags &= ~IFF_UP; */ return 0; } @@ -576,7 +563,7 @@ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp, { struct x25_asy *sl = (struct x25_asy *) tty->disc_data; - if (!sl || sl->magic != X25_ASY_MAGIC || !sl->dev->start) + if (!sl || sl->magic != X25_ASY_MAGIC || !test_bit(LINK_STATE_START, &sl->dev->state)) return; /* @@ -876,6 +863,8 @@ int x25_asy_init(struct net_device *dev) dev->mtu = SL_MTU; dev->hard_start_xmit = x25_asy_xmit; + dev->tx_timeout = x25_asy_timeout; + dev->watchdog_timeo = HZ*20; dev->open = x25_asy_open_dev; dev->stop = x25_asy_close; dev->get_stats = x25_asy_get_stats; @@ -914,7 +903,7 @@ cleanup_module(void) * VSV = if dev->start==0, then device * unregistered while close proc. */ - if (x25_asy_ctrls[i]->dev.start) + if (test_bit(LINK_STATE_START, &x25_asy_ctrls[i]->dev.state)) unregister_netdev(&(x25_asy_ctrls[i]->dev)); kfree(x25_asy_ctrls[i]); diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c index c5e1c4bd52b6..2ff818b04eb9 100644 --- a/drivers/net/wan/z85230.c +++ b/drivers/net/wan/z85230.c @@ -54,12 +54,23 @@ static spinlock_t z8530_buffer_lock = SPIN_LOCK_UNLOCKED; -/* +/** + * z8530_read_port: + * @p: port to read + * * Provided port access methods. The Comtrol SV11 requires no delays * between accesses and uses PC I/O. Some drivers may need a 5uS delay + * + * In the longer term this should become an architecture specific + * section so that this can become a generic driver interface for all + * platforms. For now we only handle PC I/O ports with or without the + * dread 5uS sanity delay. + * + * The caller must hold sufficient locks to avoid violating the horrible + * 5uS delay rule. */ -extern __inline__ int z8530_read_port(int p) +extern __inline__ int z8530_read_port(unsigned long p) { u8 r=inb(Z8530_PORT_OF(p)); if(p&Z8530_PORT_SLEEP) /* gcc should figure this out efficiently ! */ @@ -67,7 +78,23 @@ extern __inline__ int z8530_read_port(int p) return r; } -extern __inline__ void z8530_write_port(int p, u8 d) +/** + * z8530_write_port: + * @p: port to write + * @d: value to write + * + * Write a value to a port with delays if need be. Note that the + * caller must hold locks to avoid read/writes from other contexts + * violating the 5uS rule + * + * In the longer term this should become an architecture specific + * section so that this can become a generic driver interface for all + * platforms. For now we only handle PC I/O ports with or without the + * dread 5uS sanity delay. + */ + + +extern __inline__ void z8530_write_port(unsigned long p, u8 d) { outb(d,Z8530_PORT_OF(p)); if(p&Z8530_PORT_SLEEP) @@ -80,8 +107,16 @@ static void z8530_rx_done(struct z8530_channel *c); static void z8530_tx_done(struct z8530_channel *c); -/* - * Port accesses +/** + * read_zsreg: + * @c: Z8530 channel to read from (2 per chip) + * @reg: Register to read + * FIXME: Use a spinlock. + * + * Most of the Z8530 registers are indexed off the control registers. + * A read is done by writing to the control register and reading the + * register back. We do the locking needed to protect this + * operation. */ extern inline u8 read_zsreg(struct z8530_channel *c, u8 reg) @@ -97,6 +132,14 @@ extern inline u8 read_zsreg(struct z8530_channel *c, u8 reg) return r; } +/** + * read_zsdata: + * @c: The Z8530 channel to read the data port from + * + * The data port provides fast access to some things. We still + * have all the 5uS delays to worry about. + */ + extern inline u8 read_zsdata(struct z8530_channel *c) { u8 r; @@ -104,6 +147,17 @@ extern inline u8 read_zsdata(struct z8530_channel *c) return r; } +/** + * write_zsreg: + * @c: The Z8530 channel + * @reg: Register number + * @val: Value to write + * + * Write a value to an indexed register. Perform the locking needed + * to honour the irritating delay rules. We know about register 0 + * being fast to access. + */ + extern inline void write_zsreg(struct z8530_channel *c, u8 reg, u8 val) { unsigned long flags; @@ -194,8 +248,16 @@ u8 z8530_hdlc_kilostream_85230[]= EXPORT_SYMBOL(z8530_hdlc_kilostream_85230); -/* - * Flush the FIFO +/** + * z8530_flush_fifo: + * @c: Channel to flush + * + * Flush the receive FIFO. There is no specific option for this, we + * blindly read bytes and discard them. Reading when there is no data + * is harmless. The 8530 has a 4 byte FIFO, the 85230 has 8 bytes. + * + * All locking is handled for the caller. On return data may still be + * present if it arrived during the flush. */ static void z8530_flush_fifo(struct z8530_channel *c) @@ -213,7 +275,16 @@ static void z8530_flush_fifo(struct z8530_channel *c) } } -/* Sets or clears DTR/RTS on the requested line */ +/** + * z8530_rtsdtr: + * @c: The Z8530 channel to contro; + * @set: 1 to set, 0 to clear + * + * Sets or clears DTR/RTS on the requested line. All locking is handled + * for the caller. For now we assume all boards use the actual RTS/DTR + * on the chip. Apparently one or two don't. We'll scream about them + * later. + */ static void z8530_rtsdtr(struct z8530_channel *c, int set) { @@ -224,9 +295,12 @@ static void z8530_rtsdtr(struct z8530_channel *c, int set) write_zsreg(c, R5, c->regs[5]); } -/* - * Receive handler. This is much like the async one but not quite the - * same or as complex +/** + * z8530_rx: + * @c: Z8530 channel to process + * + * Receive handler for receiving in PIO mode. This is much like the + * async one but not quite the same or as complex * * Note: Its intended that this handler can easily be separated from * the main code to run realtime. That'll be needed for some machines @@ -238,9 +312,9 @@ static void z8530_rtsdtr(struct z8530_channel *c, int set) * other code - this is true in the RT case too. * * We only cover the sync cases for this. If you want 2Mbit async - * do it yourself but consider medical assistance first. - * - * This non DMA synchronous mode is portable code. + * do it yourself but consider medical assistance first. This non DMA + * synchronous mode is portable code. The DMA mode assumes PCI like + * ISA DMA */ static void z8530_rx(struct z8530_channel *c) @@ -303,8 +377,14 @@ static void z8530_rx(struct z8530_channel *c) } -/* - * Z8530 transmit interrupt handler +/** + * z8530_tx: + * @c: Z8530 channel to process + * + * Z8530 transmit interrupt handler for the PIO mode. The basic + * idea is to attempt to keep the FIFO fed. We fill as many bytes + * in as possible, its quite possible that we won't keep up with the + * data rate otherwise. */ static void z8530_tx(struct z8530_channel *c) @@ -340,6 +420,17 @@ static void z8530_tx(struct z8530_channel *c) write_zsctrl(c, RES_H_IUS); } +/** + * z8530_status: + * @chan: Z8530 channel to process + * + * A status event occured in PIO synchronous mode. There are several + * reasons the chip will bother us here. A transmit underrun means we + * failed to feed the chip fast enough and just broke a packet. A DCD + * change is a line up or down. We communicate that back to the protocol + * layer for synchronous PPP to renegotiate. + */ + static void z8530_status(struct z8530_channel *chan) { u8 status=read_zsreg(chan, R0); @@ -387,9 +478,14 @@ struct z8530_irqhandler z8530_sync= EXPORT_SYMBOL(z8530_sync); -/* +/** + * z8530_dma_rx: + * @chan: Channel to handle + * * Non bus mastering DMA interfaces for the Z8x30 devices. This - * is really pretty PC specific. + * is really pretty PC specific. The DMA mode means that most receive + * events are handled by the DMA hardware. We get a kick here only if + * a frame ended. */ static void z8530_dma_rx(struct z8530_channel *chan) @@ -417,6 +513,14 @@ static void z8530_dma_rx(struct z8530_channel *chan) } } +/** + * z8530_dma_tx: + * @chan: The Z8530 channel to handle + * + * We have received an interrupt while doing DMA transmissions. It + * shouldn't happen. Scream loudly if it does. + */ + static void z8530_dma_tx(struct z8530_channel *chan) { if(!chan->dma_tx) @@ -430,6 +534,17 @@ static void z8530_dma_tx(struct z8530_channel *chan) z8530_tx(chan); } +/** + * z8530_dma_status: + * @chan: Z8530 channel to process + * + * A status event occured on the Z8530. We receive these for two reasons + * when in DMA mode. Firstly if we finished a packet transfer we get one + * and kick the next packet out. Secondly we may see a DCD change and + * have to poke the protocol layer. + * + */ + static void z8530_dma_status(struct z8530_channel *chan) { unsigned long flags; @@ -490,8 +605,11 @@ struct z8530_irqhandler z8530_txdma_sync= EXPORT_SYMBOL(z8530_txdma_sync); -/* - * Interrupt vectors for a Z8530 that is in 'parked' mode. +/** + * z8530_rx_clear: + * @c: Z8530 channel to shut up + * + * Receive interrupt vectors for a Z8530 that is in 'parked' mode. * For machines with PCI Z85x30 cards, or level triggered interrupts * (eg the MacII) we must clear the interrupt cause or die. */ @@ -516,12 +634,30 @@ static void z8530_rx_clear(struct z8530_channel *c) write_zsctrl(c, RES_H_IUS); } +/** + * z8530_tx_clear: + * @c: Z8530 channel to shut up + * + * Transmit interrupt vectors for a Z8530 that is in 'parked' mode. + * For machines with PCI Z85x30 cards, or level triggered interrupts + * (eg the MacII) we must clear the interrupt cause or die. + */ + static void z8530_tx_clear(struct z8530_channel *c) { write_zsctrl(c, RES_Tx_P); write_zsctrl(c, RES_H_IUS); } +/** + * z8530_status_clear: + * @chan: Z8530 channel to shut up + * + * Status interrupt vectors for a Z8530 that is in 'parked' mode. + * For machines with PCI Z85x30 cards, or level triggered interrupts + * (eg the MacII) we must clear the interrupt cause or die. + */ + static void z8530_status_clear(struct z8530_channel *chan) { u8 status=read_zsreg(chan, R0); @@ -541,8 +677,17 @@ struct z8530_irqhandler z8530_nop= EXPORT_SYMBOL(z8530_nop); -/* - * A Z85[2]30 device has stuck its hand in the air for attention +/** + * z8530_interrupt: + * @irq: Interrupt number + * @dev_id: The Z8530 device that is interrupting. + * @regs: unused + * + * A Z85[2]30 device has stuck its hand in the air for attention. + * We scan both the channels on the chip for events and then call + * the channel specific call backs for each channel that has events. + * We have to use callback functions because the two channels can be + * in different modes. */ void z8530_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -612,6 +757,15 @@ static char reg_init[16]= }; +/** + * z8530_sync_open: + * @dev: The network interface we are using + * @c: The Z8530 channel to open in synchronous PIO mode + * + * Switch a Z8530 into synchronous mode without DMA assist. We + * raise the RTS/DTR and commence network operation. + */ + int z8530_sync_open(struct net_device *dev, struct z8530_channel *c) { c->sync = 1; @@ -634,6 +788,15 @@ int z8530_sync_open(struct net_device *dev, struct z8530_channel *c) EXPORT_SYMBOL(z8530_sync_open); +/** + * z8530_sync_close: + * @dev: Network device to close + * @c: Z8530 channel to disassociate and move to idle + * + * Close down a Z8530 interface and switch its interrupt handlers + * to discard future events. + */ + int z8530_sync_close(struct net_device *dev, struct z8530_channel *c) { u8 chk; @@ -650,6 +813,16 @@ int z8530_sync_close(struct net_device *dev, struct z8530_channel *c) EXPORT_SYMBOL(z8530_sync_close); +/** + * z8530_sync_dma_open: + * @dev: The network device to attach + * @c: The Z8530 channel to configure in sync DMA mode. + * + * Set up a Z85x30 device for synchronous DMA in both directions. Two + * ISA DMA channels must be available for this to work. We assume ISA + * DMA driven I/O and PC limits on access. + */ + int z8530_sync_dma_open(struct net_device *dev, struct z8530_channel *c) { unsigned long flags; @@ -760,6 +933,15 @@ int z8530_sync_dma_open(struct net_device *dev, struct z8530_channel *c) EXPORT_SYMBOL(z8530_sync_dma_open); +/** + * z8530_sync_dma_close: + * @dev: Network device to detach + * @c: Z8530 channel to move into discard mode + * + * Shut down a DMA mode synchronous interface. Halt the DMA, and + * free the buffers. + */ + int z8530_sync_dma_close(struct net_device *dev, struct z8530_channel *c) { u8 chk; @@ -816,6 +998,16 @@ int z8530_sync_dma_close(struct net_device *dev, struct z8530_channel *c) EXPORT_SYMBOL(z8530_sync_dma_close); +/** + * z8530_sync_txdma_open: + * @dev: The network device to attach + * @c: The Z8530 channel to configure in sync DMA mode. + * + * Set up a Z85x30 device for synchronous DMA tranmission. One + * ISA DMA channel must be available for this to work. The receive + * side is run in PIO mode, but then it has the bigger FIFO. + */ + int z8530_sync_txdma_open(struct net_device *dev, struct z8530_channel *c) { unsigned long flags; @@ -905,7 +1097,16 @@ int z8530_sync_txdma_open(struct net_device *dev, struct z8530_channel *c) } EXPORT_SYMBOL(z8530_sync_txdma_open); - + +/** + * z8530_sync_txdma_close: + * @dev: Network device to detach + * @c: Z8530 channel to move into discard mode + * + * Shut down a DMA/PIO split mode synchronous interface. Halt the DMA, + * and free the buffers. + */ + int z8530_sync_txdma_close(struct net_device *dev, struct z8530_channel *c) { unsigned long flags; @@ -954,21 +1155,32 @@ int z8530_sync_txdma_close(struct net_device *dev, struct z8530_channel *c) EXPORT_SYMBOL(z8530_sync_txdma_close); + /* - * Describe a Z8530 in a standard format. We must pass the I/O as - * the port offset isnt predictable. The main reason for this function - * is to try and get a common format of report. + * Name strings for Z8530 chips. SGI claim to have a 130, Zilog deny + * it exists... */ - + static char *z8530_type_name[]={ "Z8530", "Z85C30", "Z85230" }; -void z8530_describe(struct z8530_dev *dev, char *mapping, int io) +/** + * z8530_describe: + * @dev: Z8530 device to describe + * @mapping: string holding mapping type (eg "I/O" or "Mem") + * @io: the port value in question + * + * Describe a Z8530 in a standard format. We must pass the I/O as + * the port offset isnt predictable. The main reason for this function + * is to try and get a common format of report. + */ + +void z8530_describe(struct z8530_dev *dev, char *mapping, unsigned long io) { - printk(KERN_INFO "%s: %s found at %s 0x%X, IRQ %d.\n", + printk(KERN_INFO "%s: %s found at %s 0x%lX, IRQ %d.\n", dev->name, z8530_type_name[dev->type], mapping, @@ -978,8 +1190,21 @@ void z8530_describe(struct z8530_dev *dev, char *mapping, int io) EXPORT_SYMBOL(z8530_describe); -/* - * Configure up a Z8530 +/** + * z8530_init: + * @dev: Z8530 device to initialise. + * + * Configure up a Z8530/Z85C30 or Z85230 chip. We check the device + * is present, identify the type and then program it to hopefully + * keep quite and behave. This matters a lot, a Z8530 in the wrong + * state will sometimes get into stupid modes generating 10Khz + * interrupt streams and the like. + * + * We set the interrupt handler up to discard any events, in case + * we get them during reset or setp. + * + * Return 0 for success, or a negative value indicating the problem + * in errno form. */ @@ -1047,6 +1272,15 @@ int z8530_init(struct z8530_dev *dev) EXPORT_SYMBOL(z8530_init); +/** + * z8530_shutdown: + * @dev: The Z8530 chip to shutdown + * + * We set the interrupt handlers to silence any interrupts. We then + * reset the chip and wait 100uS to be sure the reset completed. Just + * in case the caller then tries to do stuff. + */ + int z8530_shutdown(struct z8530_dev *dev) { /* Reset the chip */ @@ -1059,9 +1293,15 @@ int z8530_shutdown(struct z8530_dev *dev) EXPORT_SYMBOL(z8530_shutdown); -/* - * Load a Z8530 channel up from the system data - * We use +16 to indicate the 'prime' registers +/** + * z8530_channel_load: + * @c: Z8530 channel to configure + * @rtable: Table of register, value pairs + * FIXME: ioctl to allow user uploaded tables + * + * Load a Z8530 channel up from the system data> We use +16 to + * indicate the 'prime' registers. The value 255 terminates the + * table */ int z8530_channel_load(struct z8530_channel *c, u8 *rtable) @@ -1092,8 +1332,16 @@ int z8530_channel_load(struct z8530_channel *c, u8 *rtable) EXPORT_SYMBOL(z8530_channel_load); -/* - * Higher level shovelling - transmit chains +/** + * z8530_tx_begin: + * @c: The Z8530 channel to kick + * + * This is the speed sensitive side of transmission. If we are called + * and no buffer is being transmitted we commence the next buffer. If + * nothing is queued we idle the sync. + * + * Note: We are handling this code path in the interrupt path, keep it + * fast or bad things will happen. */ static void z8530_tx_begin(struct z8530_channel *c) @@ -1180,7 +1428,15 @@ static void z8530_tx_begin(struct z8530_channel *c) } } } - + +/** + * z8530_tx_done: + * @c: The channel that completed a transmit. + * + * This is called when we complete a packet send. We wake the queue, + * start the next packet going and then free the buffer of the existing + * packet. This code is fairly timing sensitive. + */ static void z8530_tx_done(struct z8530_channel *c) { @@ -1201,11 +1457,16 @@ static void z8530_tx_done(struct z8530_channel *c) spin_unlock_irqrestore(&z8530_buffer_lock, flags); c->stats.tx_packets++; c->stats.tx_bytes+=skb->len; - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); } -/* - * Higher level shovelling - receive chains +/** + * z8530_null_rx: + * @c: The channel the packet arrived on + * @skb: The buffer + * + * We point the receive handler at this function when idle. Instead + * of syncppp processing the frames we get to throw them away. */ void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb) @@ -1215,6 +1476,17 @@ void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb) EXPORT_SYMBOL(z8530_null_rx); +/** + * z8530_rx_done: + * @c: The channel that completed a receive + * + * A new packet is complete. Our goal here is to get back into receive + * mode as fast as possible. On the Z85230 we could change to using + * ESCC mode, but on the older chips we have no choice. We flip to the + * new buffer immediately in DMA mode so that the DMA of the next + * frame can occur while we are copying the previous buffer to an sk_buff + */ + static void z8530_rx_done(struct z8530_channel *c) { struct sk_buff *skb; @@ -1269,7 +1541,7 @@ static void z8530_rx_done(struct z8530_channel *c) else /* Can't occur as we dont reenable the DMA irq until after the flip is done */ - printk("DMA flip overrun!\n"); + printk(KERN_WARNING "%s: DMA flip overrun!\n", c->netdevice->name); release_dma_lock(flags); @@ -1357,8 +1629,12 @@ static void z8530_rx_done(struct z8530_channel *c) } } -/* - * Cannot DMA over a 64K boundary on a PC +/** + * spans_boundary: + * @skb: The buffer to check + * + * Returns true if the buffer cross a DMA boundary on a PC. The poor + * thing can only DMA within a 64K block not across the edges of it. */ extern inline int spans_boundary(struct sk_buff *skb) @@ -1373,7 +1649,11 @@ extern inline int spans_boundary(struct sk_buff *skb) return 0; } -/* +/** + * z8530_queue_xmit: + * @c: The channel to use + * @skb: The packet to kick down the channel + * * Queue a packet for transmission. Because we have rather * hard to hit interrupt latencies for the Z85230 per packet * even in DMA mode we do the flip to DMA buffer if needed here @@ -1426,6 +1706,14 @@ int z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb) EXPORT_SYMBOL(z8530_queue_xmit); +/** + * z8530_get_stats: + * @c: The channel to use + * + * Get the statistics block. We keep the statistics in software as + * the chip doesn't do it for us. + */ + struct net_device_stats *z8530_get_stats(struct z8530_channel *c) { return &c->stats; diff --git a/drivers/net/wan/z85230.h b/drivers/net/wan/z85230.h index dcad711b07b3..8dc92a535600 100644 --- a/drivers/net/wan/z85230.h +++ b/drivers/net/wan/z85230.h @@ -304,8 +304,8 @@ struct z8530_channel */ struct z8530_dev *dev; /* Z85230 chip instance we are from */ - int ctrlio; /* I/O ports */ - int dataio; + unsigned long ctrlio; /* I/O ports */ + unsigned long dataio; /* * For PC we encode this way. @@ -395,7 +395,7 @@ extern u8 z8530_dead_port[]; extern u8 z8530_hdlc_kilostream_85230[]; extern u8 z8530_hdlc_kilostream[]; extern void z8530_interrupt(int, void *, struct pt_regs *); -extern void z8530_describe(struct z8530_dev *, char *mapping,int io); +extern void z8530_describe(struct z8530_dev *, char *mapping, unsigned long io); extern int z8530_init(struct z8530_dev *); extern int z8530_shutdown(struct z8530_dev *); extern int z8530_sync_open(struct net_device *, struct z8530_channel *); diff --git a/drivers/net/wavelan.c b/drivers/net/wavelan.c index 73771fc96ce1..59d8621ca04a 100644 --- a/drivers/net/wavelan.c +++ b/drivers/net/wavelan.c @@ -6,9 +6,9 @@ * Reorganisation and extension of the driver. * Original copyright follows (also see the end of this file). * See wavelan.p.h for details. - */ - -/* + * + * + * * AT&T GIS (nee NCR) WaveLAN card: * An Ethernet-like radio transceiver * controlled by an Intel 82586 coprocessor. @@ -26,54 +26,49 @@ /* * Wrapper for disabling interrupts. */ -static inline unsigned long -wv_splhi(void) -{ - unsigned long flags; - save_flags(flags); - cli(); - - return(flags); +static inline unsigned long wv_splhi(void) +{ + unsigned long flags; + save_flags(flags); + cli(); + return (flags); } /*------------------------------------------------------------------*/ /* * Wrapper for re-enabling interrupts. */ -static inline void -wv_splx(unsigned long flags) +static inline void wv_splx(unsigned long flags) { - restore_flags(flags); + restore_flags(flags); } /*------------------------------------------------------------------*/ /* * Translate irq number to PSA irq parameter */ -static u_char -wv_irq_to_psa(int irq) +static u8 wv_irq_to_psa(int irq) { - if(irq < 0 || irq >= NELS(irqvals)) - return 0; + if (irq < 0 || irq >= NELS(irqvals)) + return 0; - return irqvals[irq]; + return irqvals[irq]; } /*------------------------------------------------------------------*/ /* * Translate PSA irq parameter to irq number */ -static int __init -wv_psa_to_irq(u_char irqval) +static int __init wv_psa_to_irq(u8 irqval) { - int irq; + int irq; - for(irq = 0; irq < NELS(irqvals); irq++) - if(irqvals[irq] == irqval) - return irq; + for (irq = 0; irq < NELS(irqvals); irq++) + if (irqvals[irq] == irqval) + return irq; - return -1; + return -1; } #ifdef STRUCT_CHECK @@ -82,21 +77,20 @@ wv_psa_to_irq(u_char irqval) * Sanity routine to verify the sizes of the various WaveLAN interface * structures. */ -static char * -wv_struct_check(void) +static char *wv_struct_check(void) { #define SC(t,s,n) if (sizeof(t) != s) return(n); - SC(psa_t, PSA_SIZE, "psa_t"); - SC(mmw_t, MMW_SIZE, "mmw_t"); - SC(mmr_t, MMR_SIZE, "mmr_t"); - SC(ha_t, HA_SIZE, "ha_t"); + SC(psa_t, PSA_SIZE, "psa_t"); + SC(mmw_t, MMW_SIZE, "mmw_t"); + SC(mmr_t, MMR_SIZE, "mmr_t"); + SC(ha_t, HA_SIZE, "ha_t"); #undef SC - return((char *) NULL); -} /* wv_struct_check */ -#endif /* STRUCT_CHECK */ + return ((char *) NULL); +} /* wv_struct_check */ +#endif /* STRUCT_CHECK */ /********************* HOST ADAPTER SUBROUTINES *********************/ /* @@ -111,120 +105,106 @@ wv_struct_check(void) /* * Read from card's Host Adaptor Status Register. */ -static inline u_short -hasr_read(u_long ioaddr) +static inline u16 hasr_read(unsigned long ioaddr) { - return(inw(HASR(ioaddr))); -} /* hasr_read */ + return (inw(HASR(ioaddr))); +} /* hasr_read */ /*------------------------------------------------------------------*/ /* * Write to card's Host Adapter Command Register. */ -static inline void -hacr_write(u_long ioaddr, - u_short hacr) +static inline void hacr_write(unsigned long ioaddr, u16 hacr) { - outw(hacr, HACR(ioaddr)); -} /* hacr_write */ + outw(hacr, HACR(ioaddr)); +} /* hacr_write */ /*------------------------------------------------------------------*/ /* * Write to card's Host Adapter Command Register. Include a delay for * those times when it is needed. */ -static inline void -hacr_write_slow(u_long ioaddr, - u_short hacr) +static inline void hacr_write_slow(unsigned long ioaddr, u16 hacr) { - hacr_write(ioaddr, hacr); - /* delay might only be needed sometimes */ - mdelay(1); -} /* hacr_write_slow */ + hacr_write(ioaddr, hacr); + /* delay might only be needed sometimes */ + mdelay(1); +} /* hacr_write_slow */ /*------------------------------------------------------------------*/ /* * Set the channel attention bit. */ -static inline void -set_chan_attn(u_long ioaddr, - u_short hacr) +static inline void set_chan_attn(unsigned long ioaddr, u16 hacr) { - hacr_write(ioaddr, hacr | HACR_CA); -} /* set_chan_attn */ + hacr_write(ioaddr, hacr | HACR_CA); +} /* set_chan_attn */ /*------------------------------------------------------------------*/ /* * Reset, and then set host adaptor into default mode. */ -static inline void -wv_hacr_reset(u_long ioaddr) +static inline void wv_hacr_reset(unsigned long ioaddr) { - hacr_write_slow(ioaddr, HACR_RESET); - hacr_write(ioaddr, HACR_DEFAULT); -} /* wv_hacr_reset */ + hacr_write_slow(ioaddr, HACR_RESET); + hacr_write(ioaddr, HACR_DEFAULT); +} /* wv_hacr_reset */ /*------------------------------------------------------------------*/ /* * Set the I/O transfer over the ISA bus to 8-bit mode */ -static inline void -wv_16_off(u_long ioaddr, - u_short hacr) +static inline void wv_16_off(unsigned long ioaddr, u16 hacr) { - hacr &= ~HACR_16BITS; - hacr_write(ioaddr, hacr); -} /* wv_16_off */ + hacr &= ~HACR_16BITS; + hacr_write(ioaddr, hacr); +} /* wv_16_off */ /*------------------------------------------------------------------*/ /* * Set the I/O transfer over the ISA bus to 8-bit mode */ -static inline void -wv_16_on(u_long ioaddr, - u_short hacr) +static inline void wv_16_on(unsigned long ioaddr, u16 hacr) { - hacr |= HACR_16BITS; - hacr_write(ioaddr, hacr); -} /* wv_16_on */ + hacr |= HACR_16BITS; + hacr_write(ioaddr, hacr); +} /* wv_16_on */ /*------------------------------------------------------------------*/ /* * Disable interrupts on the WaveLAN hardware. */ -static inline void -wv_ints_off(device * dev) +static inline void wv_ints_off(device * dev) { - net_local * lp = (net_local *)dev->priv; - u_long ioaddr = dev->base_addr; - u_long x; - - x = wv_splhi(); + net_local *lp = (net_local *) dev->priv; + unsigned long ioaddr = dev->base_addr; + unsigned long flags; - lp->hacr &= ~HACR_INTRON; - hacr_write(ioaddr, lp->hacr); + save_flags(flags); + cli(); + + lp->hacr &= ~HACR_INTRON; + hacr_write(ioaddr, lp->hacr); - wv_splx(x); -} /* wv_ints_off */ + restore_flags(flags); +} /* wv_ints_off */ /*------------------------------------------------------------------*/ /* * Enable interrupts on the WaveLAN hardware. */ -static inline void -wv_ints_on(device * dev) +static inline void wv_ints_on(device * dev) { - net_local * lp = (net_local *)dev->priv; - u_long ioaddr = dev->base_addr; - u_long x; - - x = wv_splhi(); - - lp->hacr |= HACR_INTRON; - hacr_write(ioaddr, lp->hacr); + net_local *lp = (net_local *) dev->priv; + unsigned long ioaddr = dev->base_addr; + unsigned long flags; - wv_splx(x); -} /* wv_ints_on */ + save_flags(flags); + cli(); + lp->hacr |= HACR_INTRON; + hacr_write(ioaddr, lp->hacr); + restore_flags(flags); +} /* wv_ints_on */ /******************* MODEM MANAGEMENT SUBROUTINES *******************/ /* @@ -238,57 +218,48 @@ wv_ints_on(device * dev) /* * Read bytes from the PSA. */ -static void -psa_read(u_long ioaddr, - u_short hacr, - int o, /* offset in PSA */ - u_char * b, /* buffer to fill */ - int n) /* size to read */ -{ - wv_16_off(ioaddr, hacr); - - while(n-- > 0) - { - outw(o, PIOR2(ioaddr)); - o++; - *b++ = inb(PIOP2(ioaddr)); - } +static void psa_read(unsigned long ioaddr, u16 hacr, int o, /* offset in PSA */ + u8 * b, /* buffer to fill */ + int n) +{ /* size to read */ + wv_16_off(ioaddr, hacr); + + while (n-- > 0) { + outw(o, PIOR2(ioaddr)); + o++; + *b++ = inb(PIOP2(ioaddr)); + } - wv_16_on(ioaddr, hacr); -} /* psa_read */ + wv_16_on(ioaddr, hacr); +} /* psa_read */ /*------------------------------------------------------------------*/ /* * Write the Parameter Storage Area to the WaveLAN card's memory. */ -static void -psa_write(u_long ioaddr, - u_short hacr, - int o, /* Offset in PSA */ - u_char * b, /* Buffer in memory */ - int n) /* Length of buffer */ -{ - int count = 0; +static void psa_write(unsigned long ioaddr, u16 hacr, int o, /* Offset in PSA */ + u8 * b, /* Buffer in memory */ + int n) +{ /* Length of buffer */ + int count = 0; - wv_16_off(ioaddr, hacr); + wv_16_off(ioaddr, hacr); - while(n-- > 0) - { - outw(o, PIOR2(ioaddr)); - o++; + while (n-- > 0) { + outw(o, PIOR2(ioaddr)); + o++; - outb(*b, PIOP2(ioaddr)); - b++; + outb(*b, PIOP2(ioaddr)); + b++; - /* Wait for the memory to finish its write cycle */ - count = 0; - while((count++ < 100) && - (hasr_read(ioaddr) & HASR_PSA_BUSY)) - mdelay(1); - } + /* Wait for the memory to finish its write cycle */ + count = 0; + while ((count++ < 100) && + (hasr_read(ioaddr) & HASR_PSA_BUSY)) mdelay(1); + } - wv_16_on(ioaddr, hacr); -} /* psa_write */ + wv_16_on(ioaddr, hacr); +} /* psa_write */ #ifdef SET_PSA_CRC /*------------------------------------------------------------------*/ @@ -301,88 +272,80 @@ psa_write(u_long ioaddr, * The Windows drivers don't use the CRC, but the AP and the PtP tool * depend on it. */ -static inline u_short -psa_crc(u_char * psa, /* The PSA */ - int size) /* Number of short for CRC */ -{ - int byte_cnt; /* Loop on the PSA */ - u_short crc_bytes = 0; /* Data in the PSA */ - int bit_cnt; /* Loop on the bits of the short */ - - for(byte_cnt = 0; byte_cnt < size; byte_cnt++ ) - { - crc_bytes ^= psa[byte_cnt]; /* Its an xor */ - - for(bit_cnt = 1; bit_cnt < 9; bit_cnt++ ) - { - if(crc_bytes & 0x0001) - crc_bytes = (crc_bytes >> 1) ^ 0xA001; - else - crc_bytes >>= 1 ; - } - } +static inline u16 psa_crc(u8 * psa, /* The PSA */ + int size) +{ /* Number of short for CRC */ + int byte_cnt; /* Loop on the PSA */ + u16 crc_bytes = 0; /* Data in the PSA */ + int bit_cnt; /* Loop on the bits of the short */ + + for (byte_cnt = 0; byte_cnt < size; byte_cnt++) { + crc_bytes ^= psa[byte_cnt]; /* Its an xor */ + + for (bit_cnt = 1; bit_cnt < 9; bit_cnt++) { + if (crc_bytes & 0x0001) + crc_bytes = (crc_bytes >> 1) ^ 0xA001; + else + crc_bytes >>= 1; + } + } - return crc_bytes; -} /* psa_crc */ -#endif /* SET_PSA_CRC */ + return crc_bytes; +} /* psa_crc */ +#endif /* SET_PSA_CRC */ /*------------------------------------------------------------------*/ /* * update the checksum field in the Wavelan's PSA */ -static void -update_psa_checksum(device * dev, - u_long ioaddr, - u_short hacr) +static void update_psa_checksum(device * dev, unsigned long ioaddr, u16 hacr) { #ifdef SET_PSA_CRC - psa_t psa; - u_short crc; + psa_t psa; + u16 crc; - /* read the parameter storage area */ - psa_read(ioaddr, hacr, 0, (unsigned char *) &psa, sizeof(psa)); + /* read the parameter storage area */ + psa_read(ioaddr, hacr, 0, (unsigned char *) &psa, sizeof(psa)); - /* update the checksum */ - crc = psa_crc((unsigned char *) &psa, - sizeof(psa) - sizeof(psa.psa_crc[0]) - sizeof(psa.psa_crc[1]) - - sizeof(psa.psa_crc_status)); + /* update the checksum */ + crc = psa_crc((unsigned char *) &psa, + sizeof(psa) - sizeof(psa.psa_crc[0]) - + sizeof(psa.psa_crc[1]) + - sizeof(psa.psa_crc_status)); - psa.psa_crc[0] = crc & 0xFF; - psa.psa_crc[1] = (crc & 0xFF00) >> 8; + psa.psa_crc[0] = crc & 0xFF; + psa.psa_crc[1] = (crc & 0xFF00) >> 8; - /* Write it ! */ - psa_write(ioaddr, hacr, (char *)&psa.psa_crc - (char *)&psa, - (unsigned char *)&psa.psa_crc, 2); + /* Write it ! */ + psa_write(ioaddr, hacr, (char *) &psa.psa_crc - (char *) &psa, + (unsigned char *) &psa.psa_crc, 2); #ifdef DEBUG_IOCTL_INFO - printk (KERN_DEBUG "%s: update_psa_checksum(): crc = 0x%02x%02x\n", - dev->name, psa.psa_crc[0], psa.psa_crc[1]); + printk(KERN_DEBUG "%s: update_psa_checksum(): crc = 0x%02x%02x\n", + dev->name, psa.psa_crc[0], psa.psa_crc[1]); - /* Check again (luxury !) */ - crc = psa_crc ((unsigned char *) &psa, - sizeof(psa) - sizeof(psa.psa_crc_status)); + /* Check again (luxury !) */ + crc = psa_crc((unsigned char *) &psa, + sizeof(psa) - sizeof(psa.psa_crc_status)); - if(crc != 0) - printk(KERN_WARNING "%s: update_psa_checksum(): CRC does not agree with PSA data (even after recalculating)\n", dev->name); -#endif /* DEBUG_IOCTL_INFO */ -#endif /* SET_PSA_CRC */ -} /* update_psa_checksum */ + if (crc != 0) + printk(KERN_WARNING + "%s: update_psa_checksum(): CRC does not agree with PSA data (even after recalculating)\n", + dev->name); +#endif /* DEBUG_IOCTL_INFO */ +#endif /* SET_PSA_CRC */ +} /* update_psa_checksum */ /*------------------------------------------------------------------*/ /* * Write 1 byte to the MMC. */ -static inline void -mmc_out(u_long ioaddr, - u_short o, - u_char d) +static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d) { - /* Wait for MMC to go idle */ - while(inw(HASR(ioaddr)) & HASR_MMC_BUSY) - ; + /* Wait for MMC to go idle */ + while (inw(HASR(ioaddr)) & HASR_MMC_BUSY); - outw((u_short) (((u_short) d << 8) | (o << 1) | 1), - MMCR(ioaddr)); + outw((u16) (((u16) d << 8) | (o << 1) | 1), MMCR(ioaddr)); } /*------------------------------------------------------------------*/ @@ -390,35 +353,27 @@ mmc_out(u_long ioaddr, * Routine to write bytes to the Modem Management Controller. * We start at the end because it is the way it should be! */ -static inline void -mmc_write(u_long ioaddr, - u_char o, - u_char * b, - int n) +static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n) { - o += n; - b += n; + o += n; + b += n; - while(n-- > 0 ) - mmc_out(ioaddr, --o, *(--b)); -} /* mmc_write */ + while (n-- > 0) + mmc_out(ioaddr, --o, *(--b)); +} /* mmc_write */ /*------------------------------------------------------------------*/ /* * Read a byte from the MMC. * Optimised version for 1 byte, avoid using memory. */ -static inline u_char -mmc_in(u_long ioaddr, - u_short o) +static inline u8 mmc_in(unsigned long ioaddr, u16 o) { - while(inw(HASR(ioaddr)) & HASR_MMC_BUSY) - ; - outw(o << 1, MMCR(ioaddr)); + while (inw(HASR(ioaddr)) & HASR_MMC_BUSY); + outw(o << 1, MMCR(ioaddr)); - while(inw(HASR(ioaddr)) & HASR_MMC_BUSY) - ; - return (u_char) (inw(MMCR(ioaddr)) >> 8); + while (inw(HASR(ioaddr)) & HASR_MMC_BUSY); + return (u8) (inw(MMCR(ioaddr)) >> 8); } /*------------------------------------------------------------------*/ @@ -429,33 +384,28 @@ mmc_in(u_long ioaddr, * (code has just been moved in the above function) * We start at the end because it is the way it should be! */ -static inline void -mmc_read(u_long ioaddr, - u_char o, - u_char * b, - int n) +static inline void mmc_read(unsigned long ioaddr, u8 o, u8 * b, int n) { - o += n; - b += n; + o += n; + b += n; - while(n-- > 0) - *(--b) = mmc_in(ioaddr, --o); -} /* mmc_read */ + while (n-- > 0) + *(--b) = mmc_in(ioaddr, --o); +} /* mmc_read */ /*------------------------------------------------------------------*/ /* * Get the type of encryption available. */ -static inline int -mmc_encr(u_long ioaddr) /* I/O port of the card */ -{ - int temp; - - temp = mmc_in(ioaddr, mmroff(0, mmr_des_avail)); - if((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES)) - return 0; - else - return temp; +static inline int mmc_encr(unsigned long ioaddr) +{ /* I/O port of the card */ + int temp; + + temp = mmc_in(ioaddr, mmroff(0, mmr_des_avail)); + if ((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES)) + return 0; + else + return temp; } /*------------------------------------------------------------------*/ @@ -463,49 +413,47 @@ mmc_encr(u_long ioaddr) /* I/O port of the card */ * Wait for the frequency EEPROM to complete a command. * I hope this one will be optimally inlined. */ -static inline void -fee_wait(u_long ioaddr, /* I/O port of the card */ - int delay, /* Base delay to wait for */ - int number) /* Number of time to wait */ -{ - int count = 0; /* Wait only a limited time */ - - while((count++ < number) && - (mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & MMR_FEE_STATUS_BUSY)) - udelay(delay); +static inline void fee_wait(unsigned long ioaddr, /* I/O port of the card */ + int delay, /* Base delay to wait for */ + int number) +{ /* Number of time to wait */ + int count = 0; /* Wait only a limited time */ + + while ((count++ < number) && + (mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & + MMR_FEE_STATUS_BUSY)) udelay(delay); } /*------------------------------------------------------------------*/ /* * Read bytes from the Frequency EEPROM (frequency select cards). */ -static void -fee_read(u_long ioaddr, /* I/O port of the card */ - u_short o, /* destination offset */ - u_short * b, /* data buffer */ - int n) /* number of registers */ -{ - b += n; /* Position at the end of the area */ - - /* Write the address */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1); - - /* Loop on all buffer */ - while(n-- > 0) - { - /* Write the read command */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_READ); - - /* Wait until EEPROM is ready (should be quick). */ - fee_wait(ioaddr, 10, 100); - - /* Read the value. */ - *--b = ((mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)) << 8) | - mmc_in(ioaddr, mmroff(0, mmr_fee_data_l))); - } +static void fee_read(unsigned long ioaddr, /* I/O port of the card */ + u16 o, /* destination offset */ + u16 * b, /* data buffer */ + int n) +{ /* number of registers */ + b += n; /* Position at the end of the area */ + + /* Write the address */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1); + + /* Loop on all buffer */ + while (n-- > 0) { + /* Write the read command */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), + MMW_FEE_CTRL_READ); + + /* Wait until EEPROM is ready (should be quick). */ + fee_wait(ioaddr, 10, 100); + + /* Read the value. */ + *--b = ((mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)) << 8) | + mmc_in(ioaddr, mmroff(0, mmr_fee_data_l))); + } } -#ifdef WIRELESS_EXT /* if the wireless extension exists in the kernel */ +#ifdef WIRELESS_EXT /* if the wireless extension exists in the kernel */ /*------------------------------------------------------------------*/ /* @@ -514,83 +462,82 @@ fee_read(u_long ioaddr, /* I/O port of the card */ * be unprotected and the write enabled. * Jean II */ -static void -fee_write(u_long ioaddr, /* I/O port of the card */ - u_short o, /* destination offset */ - u_short * b, /* data buffer */ - int n) /* number of registers */ -{ - b += n; /* Position at the end of the area. */ +static void fee_write(unsigned long ioaddr, /* I/O port of the card */ + u16 o, /* destination offset */ + u16 * b, /* data buffer */ + int n) +{ /* number of registers */ + b += n; /* Position at the end of the area. */ #ifdef EEPROM_IS_PROTECTED /* disabled */ #ifdef DOESNT_SEEM_TO_WORK /* disabled */ - /* Ask to read the protected register */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRREAD); + /* Ask to read the protected register */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRREAD); - fee_wait(ioaddr, 10, 100); + fee_wait(ioaddr, 10, 100); - /* Read the protected register. */ - printk("Protected 2: %02X-%02X\n", - mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)), - mmc_in(ioaddr, mmroff(0, mmr_fee_data_l))); -#endif /* DOESNT_SEEM_TO_WORK */ + /* Read the protected register. */ + printk("Protected 2: %02X-%02X\n", + mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)), + mmc_in(ioaddr, mmroff(0, mmr_fee_data_l))); +#endif /* DOESNT_SEEM_TO_WORK */ - /* Enable protected register. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PREN); + /* Enable protected register. */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN); + mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PREN); - fee_wait(ioaddr, 10, 100); + fee_wait(ioaddr, 10, 100); - /* Unprotect area. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE); + /* Unprotect area. */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n); + mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE); #ifdef DOESNT_SEEM_TO_WORK /* disabled */ - /* or use: */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRCLEAR); -#endif /* DOESNT_SEEM_TO_WORK */ + /* or use: */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRCLEAR); +#endif /* DOESNT_SEEM_TO_WORK */ - fee_wait(ioaddr, 10, 100); -#endif /* EEPROM_IS_PROTECTED */ + fee_wait(ioaddr, 10, 100); +#endif /* EEPROM_IS_PROTECTED */ - /* Write enable. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WREN); + /* Write enable. */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN); + mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WREN); - fee_wait(ioaddr, 10, 100); + fee_wait(ioaddr, 10, 100); - /* Write the EEPROM address. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1); + /* Write the EEPROM address. */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1); - /* Loop on all buffer */ - while(n-- > 0) - { - /* Write the value. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_data_h), (*--b) >> 8); - mmc_out(ioaddr, mmwoff(0, mmw_fee_data_l), *b & 0xFF); + /* Loop on all buffer */ + while (n-- > 0) { + /* Write the value. */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_data_h), (*--b) >> 8); + mmc_out(ioaddr, mmwoff(0, mmw_fee_data_l), *b & 0xFF); - /* Write the write command. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WRITE); + /* Write the write command. */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), + MMW_FEE_CTRL_WRITE); - /* WaveLAN documentation says to wait at least 10 ms for EEBUSY = 0 */ - mdelay(10); - fee_wait(ioaddr, 10, 100); - } + /* WaveLAN documentation says to wait at least 10 ms for EEBUSY = 0 */ + mdelay(10); + fee_wait(ioaddr, 10, 100); + } - /* Write disable. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_DS); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WDS); + /* Write disable. */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_DS); + mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WDS); - fee_wait(ioaddr, 10, 100); + fee_wait(ioaddr, 10, 100); #ifdef EEPROM_IS_PROTECTED /* disabled */ - /* Reprotect EEPROM. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x00); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE); + /* Reprotect EEPROM. */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x00); + mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE); - fee_wait(ioaddr, 10, 100); -#endif /* EEPROM_IS_PROTECTED */ + fee_wait(ioaddr, 10, 100); +#endif /* EEPROM_IS_PROTECTED */ } -#endif /* WIRELESS_EXT */ +#endif /* WIRELESS_EXT */ /************************ I82586 SUBROUTINES *************************/ /* @@ -602,68 +549,61 @@ fee_write(u_long ioaddr, /* I/O port of the card */ * Read bytes from the on-board RAM. * Why does inlining this function make it fail? */ -static /*inline*/ void -obram_read(u_long ioaddr, - u_short o, - u_char * b, - int n) +static /*inline */ void obram_read(unsigned long ioaddr, + u16 o, u8 * b, int n) { - outw(o, PIOR1(ioaddr)); - insw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1); + outw(o, PIOR1(ioaddr)); + insw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1); } /*------------------------------------------------------------------*/ /* * Write bytes to the on-board RAM. */ -static inline void -obram_write(u_long ioaddr, - u_short o, - u_char * b, - int n) +static inline void obram_write(unsigned long ioaddr, u16 o, u8 * b, int n) { - outw(o, PIOR1(ioaddr)); - outsw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1); + outw(o, PIOR1(ioaddr)); + outsw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1); } /*------------------------------------------------------------------*/ /* * Acknowledge the reading of the status issued by the i82586. */ -static void -wv_ack(device * dev) +static void wv_ack(device * dev) { - net_local * lp = (net_local *)dev->priv; - u_long ioaddr = dev->base_addr; - u_short scb_cs; - int i; + net_local *lp = (net_local *) dev->priv; + unsigned long ioaddr = dev->base_addr; + u16 scb_cs; + int i; - obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), - (unsigned char *) &scb_cs, sizeof(scb_cs)); - scb_cs &= SCB_ST_INT; + obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), + (unsigned char *) &scb_cs, sizeof(scb_cs)); + scb_cs &= SCB_ST_INT; - if(scb_cs == 0) - return; + if (scb_cs == 0) + return; - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cs, sizeof(scb_cs)); + obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), + (unsigned char *) &scb_cs, sizeof(scb_cs)); - set_chan_attn(ioaddr, lp->hacr); + set_chan_attn(ioaddr, lp->hacr); - for(i = 1000; i > 0; i--) - { - obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); - if(scb_cs == 0) - break; + for (i = 1000; i > 0; i--) { + obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), + (unsigned char *) &scb_cs, sizeof(scb_cs)); + if (scb_cs == 0) + break; - udelay(10); - } - udelay(100); + udelay(10); + } + udelay(100); #ifdef DEBUG_CONFIG_ERROR - if(i <= 0) - printk(KERN_INFO "%s: wv_ack(): board not accepting command.\n", - dev->name); + if (i <= 0) + printk(KERN_INFO + "%s: wv_ack(): board not accepting command.\n", + dev->name); #endif } @@ -672,48 +612,45 @@ wv_ack(device * dev) * Set channel attention bit and busy wait until command has * completed, then acknowledge completion of the command. */ -static inline int -wv_synchronous_cmd(device * dev, - const char * str) +static inline int wv_synchronous_cmd(device * dev, const char *str) { - net_local * lp = (net_local *)dev->priv; - u_long ioaddr = dev->base_addr; - u_short scb_cmd; - ach_t cb; - int i; - - scb_cmd = SCB_CMD_CUC & SCB_CMD_CUC_GO; - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cmd, sizeof(scb_cmd)); - - set_chan_attn(ioaddr, lp->hacr); - - for (i = 1000; i > 0; i--) - { - obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); - if (cb.ac_status & AC_SFLD_C) - break; - - udelay(10); - } - udelay(100); - - if(i <= 0 || !(cb.ac_status & AC_SFLD_OK)) - { + net_local *lp = (net_local *) dev->priv; + unsigned long ioaddr = dev->base_addr; + u16 scb_cmd; + ach_t cb; + int i; + + scb_cmd = SCB_CMD_CUC & SCB_CMD_CUC_GO; + obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), + (unsigned char *) &scb_cmd, sizeof(scb_cmd)); + + set_chan_attn(ioaddr, lp->hacr); + + for (i = 1000; i > 0; i--) { + obram_read(ioaddr, OFFSET_CU, (unsigned char *) &cb, + sizeof(cb)); + if (cb.ac_status & AC_SFLD_C) + break; + + udelay(10); + } + udelay(100); + + if (i <= 0 || !(cb.ac_status & AC_SFLD_OK)) { #ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO "%s: %s failed; status = 0x%x\n", - dev->name, str, cb.ac_status); + printk(KERN_INFO "%s: %s failed; status = 0x%x\n", + dev->name, str, cb.ac_status); #endif #ifdef DEBUG_I82586_SHOW - wv_scb_show(ioaddr); + wv_scb_show(ioaddr); #endif - return -1; - } + return -1; + } - /* Ack the status */ - wv_ack(dev); + /* Ack the status */ + wv_ack(dev); - return 0; + return 0; } /*------------------------------------------------------------------*/ @@ -722,60 +659,64 @@ wv_synchronous_cmd(device * dev, * Check if done, and if OK. */ static inline int -wv_config_complete(device * dev, - u_long ioaddr, - net_local * lp) +wv_config_complete(device * dev, unsigned long ioaddr, net_local * lp) { - unsigned short mcs_addr; - unsigned short status; - int ret; + unsigned short mcs_addr; + unsigned short status; + int ret; #ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: ->wv_config_complete()\n", dev->name); + printk(KERN_DEBUG "%s: ->wv_config_complete()\n", dev->name); #endif - mcs_addr = lp->tx_first_in_use + sizeof(ac_tx_t) + sizeof(ac_nop_t) - + sizeof(tbd_t) + sizeof(ac_cfg_t) + sizeof(ac_ias_t); + mcs_addr = lp->tx_first_in_use + sizeof(ac_tx_t) + sizeof(ac_nop_t) + + sizeof(tbd_t) + sizeof(ac_cfg_t) + sizeof(ac_ias_t); - /* Read the status of the last command (set mc list). */ - obram_read(ioaddr, acoff(mcs_addr, ac_status), (unsigned char *)&status, sizeof(status)); + /* Read the status of the last command (set mc list). */ + obram_read(ioaddr, acoff(mcs_addr, ac_status), + (unsigned char *) &status, sizeof(status)); - /* If not completed -> exit */ - if((status & AC_SFLD_C) == 0) - ret = 0; /* Not ready to be scrapped */ - else - { + /* If not completed -> exit */ + if ((status & AC_SFLD_C) == 0) + ret = 0; /* Not ready to be scrapped */ + else { #ifdef DEBUG_CONFIG_ERROR - unsigned short cfg_addr; - unsigned short ias_addr; - - /* Check mc_config command */ - if((status & AC_SFLD_OK) != AC_SFLD_OK) - printk(KERN_INFO "%s: wv_config_complete(): set_multicast_address failed; status = 0x%x\n", - dev->name, status); - - /* check ia-config command */ - ias_addr = mcs_addr - sizeof(ac_ias_t); - obram_read(ioaddr, acoff(ias_addr, ac_status), (unsigned char *)&status, sizeof(status)); - if((status & AC_SFLD_OK) != AC_SFLD_OK) - printk(KERN_INFO "%s: wv_config_complete(): set_MAC_address failed; status = 0x%x\n", - dev->name, status); - - /* Check config command. */ - cfg_addr = ias_addr - sizeof(ac_cfg_t); - obram_read(ioaddr, acoff(cfg_addr, ac_status), (unsigned char *)&status, sizeof(status)); - if((status & AC_SFLD_OK) != AC_SFLD_OK) - printk(KERN_INFO "%s: wv_config_complete(): configure failed; status = 0x%x\n", - dev->name, status); -#endif /* DEBUG_CONFIG_ERROR */ - - ret = 1; /* Ready to be scrapped */ - } + unsigned short cfg_addr; + unsigned short ias_addr; + + /* Check mc_config command */ + if ((status & AC_SFLD_OK) != AC_SFLD_OK) + printk(KERN_INFO + "%s: wv_config_complete(): set_multicast_address failed; status = 0x%x\n", + dev->name, status); + + /* check ia-config command */ + ias_addr = mcs_addr - sizeof(ac_ias_t); + obram_read(ioaddr, acoff(ias_addr, ac_status), + (unsigned char *) &status, sizeof(status)); + if ((status & AC_SFLD_OK) != AC_SFLD_OK) + printk(KERN_INFO + "%s: wv_config_complete(): set_MAC_address failed; status = 0x%x\n", + dev->name, status); + + /* Check config command. */ + cfg_addr = ias_addr - sizeof(ac_cfg_t); + obram_read(ioaddr, acoff(cfg_addr, ac_status), + (unsigned char *) &status, sizeof(status)); + if ((status & AC_SFLD_OK) != AC_SFLD_OK) + printk(KERN_INFO + "%s: wv_config_complete(): configure failed; status = 0x%x\n", + dev->name, status); +#endif /* DEBUG_CONFIG_ERROR */ + + ret = 1; /* Ready to be scrapped */ + } #ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: <-wv_config_complete() - %d\n", dev->name, ret); + printk(KERN_DEBUG "%s: <-wv_config_complete() - %d\n", dev->name, + ret); #endif - return ret; + return ret; } /*------------------------------------------------------------------*/ @@ -783,141 +724,137 @@ wv_config_complete(device * dev, * Command completion interrupt. * Reclaim as many freed tx buffers as we can. */ -static int -wv_complete(device * dev, - u_long ioaddr, - net_local * lp) +static int wv_complete(device * dev, unsigned long ioaddr, net_local * lp) { - int nreaped = 0; + int nreaped = 0; #ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: ->wv_complete()\n", dev->name); + printk(KERN_DEBUG "%s: ->wv_complete()\n", dev->name); #endif - /* Loop on all the transmit buffers */ - while(lp->tx_first_in_use != I82586NULL) - { - unsigned short tx_status; + /* Loop on all the transmit buffers */ + while (lp->tx_first_in_use != I82586NULL) { + unsigned short tx_status; - /* Read the first transmit buffer */ - obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status), (unsigned char *)&tx_status, sizeof(tx_status)); + /* Read the first transmit buffer */ + obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status), + (unsigned char *) &tx_status, + sizeof(tx_status)); - /* If not completed -> exit */ - if((tx_status & AC_SFLD_C) == 0) - break; + /* If not completed -> exit */ + if ((tx_status & AC_SFLD_C) == 0) + break; - /* Hack for reconfiguration */ - if(tx_status == 0xFFFF) - if(!wv_config_complete(dev, ioaddr, lp)) - break; /* Not completed */ + /* Hack for reconfiguration */ + if (tx_status == 0xFFFF) + if (!wv_config_complete(dev, ioaddr, lp)) + break; /* Not completed */ - /* We now remove this buffer */ - nreaped++; - --lp->tx_n_in_use; + /* We now remove this buffer */ + nreaped++; + --lp->tx_n_in_use; /* if (lp->tx_n_in_use > 0) printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]); */ - /* Was it the last one? */ - if(lp->tx_n_in_use <= 0) - lp->tx_first_in_use = I82586NULL; - else - { - /* Next one in the chain */ - lp->tx_first_in_use += TXBLOCKZ; - if(lp->tx_first_in_use >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) - lp->tx_first_in_use -= NTXBLOCKS * TXBLOCKZ; - } - - /* Hack for reconfiguration */ - if(tx_status == 0xFFFF) - continue; - - /* Now, check status of the finished command */ - if(tx_status & AC_SFLD_OK) - { - int ncollisions; - - lp->stats.tx_packets++; - ncollisions = tx_status & AC_SFLD_MAXCOL; - lp->stats.collisions += ncollisions; + /* Was it the last one? */ + if (lp->tx_n_in_use <= 0) + lp->tx_first_in_use = I82586NULL; + else { + /* Next one in the chain */ + lp->tx_first_in_use += TXBLOCKZ; + if (lp->tx_first_in_use >= + OFFSET_CU + + NTXBLOCKS * TXBLOCKZ) lp->tx_first_in_use -= + NTXBLOCKS * TXBLOCKZ; + } + + /* Hack for reconfiguration */ + if (tx_status == 0xFFFF) + continue; + + /* Now, check status of the finished command */ + if (tx_status & AC_SFLD_OK) { + int ncollisions; + + lp->stats.tx_packets++; + ncollisions = tx_status & AC_SFLD_MAXCOL; + lp->stats.collisions += ncollisions; #ifdef DEBUG_TX_INFO - if(ncollisions > 0) - printk(KERN_DEBUG "%s: wv_complete(): tx completed after %d collisions.\n", - dev->name, ncollisions); + if (ncollisions > 0) + printk(KERN_DEBUG + "%s: wv_complete(): tx completed after %d collisions.\n", + dev->name, ncollisions); #endif - } - else - { - lp->stats.tx_errors++; - if(tx_status & AC_SFLD_S10) - { - lp->stats.tx_carrier_errors++; + } else { + lp->stats.tx_errors++; + if (tx_status & AC_SFLD_S10) { + lp->stats.tx_carrier_errors++; #ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG "%s: wv_complete(): tx error: no CS.\n", - dev->name); + printk(KERN_DEBUG + "%s: wv_complete(): tx error: no CS.\n", + dev->name); #endif - } - if(tx_status & AC_SFLD_S9) - { - lp->stats.tx_carrier_errors++; + } + if (tx_status & AC_SFLD_S9) { + lp->stats.tx_carrier_errors++; #ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG "%s: wv_complete(): tx error: lost CTS.\n", - dev->name); + printk(KERN_DEBUG + "%s: wv_complete(): tx error: lost CTS.\n", + dev->name); #endif - } - if(tx_status & AC_SFLD_S8) - { - lp->stats.tx_fifo_errors++; + } + if (tx_status & AC_SFLD_S8) { + lp->stats.tx_fifo_errors++; #ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG "%s: wv_complete(): tx error: slow DMA.\n", - dev->name); + printk(KERN_DEBUG + "%s: wv_complete(): tx error: slow DMA.\n", + dev->name); #endif - } - if(tx_status & AC_SFLD_S6) - { - lp->stats.tx_heartbeat_errors++; + } + if (tx_status & AC_SFLD_S6) { + lp->stats.tx_heartbeat_errors++; #ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG "%s: wv_complete(): tx error: heart beat.\n", - dev->name); + printk(KERN_DEBUG + "%s: wv_complete(): tx error: heart beat.\n", + dev->name); #endif - } - if(tx_status & AC_SFLD_S5) - { - lp->stats.tx_aborted_errors++; + } + if (tx_status & AC_SFLD_S5) { + lp->stats.tx_aborted_errors++; #ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG "%s: wv_complete(): tx error: too many collisions.\n", - dev->name); + printk(KERN_DEBUG + "%s: wv_complete(): tx error: too many collisions.\n", + dev->name); #endif - } - } + } + } #ifdef DEBUG_TX_INFO - printk(KERN_DEBUG "%s: wv_complete(): tx completed, tx_status 0x%04x\n", - dev->name, tx_status); + printk(KERN_DEBUG + "%s: wv_complete(): tx completed, tx_status 0x%04x\n", + dev->name, tx_status); #endif - } + } #ifdef DEBUG_INTERRUPT_INFO - if(nreaped > 1) - printk(KERN_DEBUG "%s: wv_complete(): reaped %d\n", dev->name, nreaped); + if (nreaped > 1) + printk(KERN_DEBUG "%s: wv_complete(): reaped %d\n", + dev->name, nreaped); #endif - /* - * Inform upper layers. - */ - if(lp->tx_n_in_use < NTXBLOCKS - 1) - { - dev->tbusy = 0; - mark_bh(NET_BH); - } - + /* + * Inform upper layers. + */ + if (lp->tx_n_in_use < NTXBLOCKS - 1) { + netif_wake_queue(dev); + } #ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: <-wv_complete()\n", dev->name); + printk(KERN_DEBUG "%s: <-wv_complete()\n", dev->name); #endif - return nreaped; + return nreaped; } /*------------------------------------------------------------------*/ @@ -929,22 +866,21 @@ if (lp->tx_n_in_use > 0) * wavelan_interrupt is not an option), so you may experience * delays sometimes. */ -static inline void -wv_82586_reconfig(device * dev) +static inline void wv_82586_reconfig(device * dev) { - net_local * lp = (net_local *)dev->priv; + net_local *lp = (net_local *) dev->priv; - /* Check if we can do it now ! */ - if(!(dev->start) || (test_and_set_bit(0, (void *)&dev->tbusy) != 0)) - { - lp->reconfig_82586 = 1; + /* Check if we can do it now ! */ + if (!test_bit(LINK_STATE_START, &dev->state) && + test_bit(LINK_STATE_XOFF, &dev->state)) { + lp->reconfig_82586 = 1; #ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "%s: wv_82586_reconfig(): delayed (busy = %ld, start = %d)\n", - dev->name, dev->tbusy, dev->start); + printk(KERN_DEBUG + "%s: wv_82586_reconfig(): delayed (state = %lX)\n", + dev->name, dev->state); #endif - } - else - wv_82586_config(dev); + } else + wv_82586_config(dev); } /********************* DEBUG & INFO SUBROUTINES *********************/ @@ -958,89 +894,73 @@ wv_82586_reconfig(device * dev) /* * Print the formatted contents of the Parameter Storage Area. */ -static void -wv_psa_show(psa_t * p) +static void wv_psa_show(psa_t * p) { - printk(KERN_DEBUG "##### WaveLAN PSA contents: #####\n"); - printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n", - p->psa_io_base_addr_1, - p->psa_io_base_addr_2, - p->psa_io_base_addr_3, - p->psa_io_base_addr_4); - printk(KERN_DEBUG "psa_rem_boot_addr_1: 0x%02X %02X %02X\n", - p->psa_rem_boot_addr_1, - p->psa_rem_boot_addr_2, - p->psa_rem_boot_addr_3); - printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params); - printk("psa_int_req_no: %d\n", p->psa_int_req_no); + printk(KERN_DEBUG "##### WaveLAN PSA contents: #####\n"); + printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n", + p->psa_io_base_addr_1, + p->psa_io_base_addr_2, + p->psa_io_base_addr_3, p->psa_io_base_addr_4); + printk(KERN_DEBUG "psa_rem_boot_addr_1: 0x%02X %02X %02X\n", + p->psa_rem_boot_addr_1, + p->psa_rem_boot_addr_2, p->psa_rem_boot_addr_3); + printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params); + printk("psa_int_req_no: %d\n", p->psa_int_req_no); #ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "psa_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - p->psa_unused0[0], - p->psa_unused0[1], - p->psa_unused0[2], - p->psa_unused0[3], - p->psa_unused0[4], - p->psa_unused0[5], - p->psa_unused0[6]); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "psa_univ_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n", - p->psa_univ_mac_addr[0], - p->psa_univ_mac_addr[1], - p->psa_univ_mac_addr[2], - p->psa_univ_mac_addr[3], - p->psa_univ_mac_addr[4], - p->psa_univ_mac_addr[5]); - printk(KERN_DEBUG "psa_local_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n", - p->psa_local_mac_addr[0], - p->psa_local_mac_addr[1], - p->psa_local_mac_addr[2], - p->psa_local_mac_addr[3], - p->psa_local_mac_addr[4], - p->psa_local_mac_addr[5]); - printk(KERN_DEBUG "psa_univ_local_sel: %d, ", p->psa_univ_local_sel); - printk("psa_comp_number: %d, ", p->psa_comp_number); - printk("psa_thr_pre_set: 0x%02x\n", p->psa_thr_pre_set); - printk(KERN_DEBUG "psa_feature_select/decay_prm: 0x%02x, ", - p->psa_feature_select); - printk("psa_subband/decay_update_prm: %d\n", p->psa_subband); - printk(KERN_DEBUG "psa_quality_thr: 0x%02x, ", p->psa_quality_thr); - printk("psa_mod_delay: 0x%02x\n", p->psa_mod_delay); - printk(KERN_DEBUG "psa_nwid: 0x%02x%02x, ", p->psa_nwid[0], p->psa_nwid[1]); - printk("psa_nwid_select: %d\n", p->psa_nwid_select); - printk(KERN_DEBUG "psa_encryption_select: %d, ", p->psa_encryption_select); - printk("psa_encryption_key[]: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - p->psa_encryption_key[0], - p->psa_encryption_key[1], - p->psa_encryption_key[2], - p->psa_encryption_key[3], - p->psa_encryption_key[4], - p->psa_encryption_key[5], - p->psa_encryption_key[6], - p->psa_encryption_key[7]); - printk(KERN_DEBUG "psa_databus_width: %d\n", p->psa_databus_width); - printk(KERN_DEBUG "psa_call_code/auto_squelch: 0x%02x, ", - p->psa_call_code[0]); - printk("psa_call_code[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - p->psa_call_code[0], - p->psa_call_code[1], - p->psa_call_code[2], - p->psa_call_code[3], - p->psa_call_code[4], - p->psa_call_code[5], - p->psa_call_code[6], - p->psa_call_code[7]); + printk(KERN_DEBUG + "psa_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X\n", + p->psa_unused0[0], p->psa_unused0[1], p->psa_unused0[2], + p->psa_unused0[3], p->psa_unused0[4], p->psa_unused0[5], + p->psa_unused0[6]); +#endif /* DEBUG_SHOW_UNUSED */ + printk(KERN_DEBUG + "psa_univ_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n", + p->psa_univ_mac_addr[0], p->psa_univ_mac_addr[1], + p->psa_univ_mac_addr[2], p->psa_univ_mac_addr[3], + p->psa_univ_mac_addr[4], p->psa_univ_mac_addr[5]); + printk(KERN_DEBUG + "psa_local_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n", + p->psa_local_mac_addr[0], p->psa_local_mac_addr[1], + p->psa_local_mac_addr[2], p->psa_local_mac_addr[3], + p->psa_local_mac_addr[4], p->psa_local_mac_addr[5]); + printk(KERN_DEBUG "psa_univ_local_sel: %d, ", + p->psa_univ_local_sel); + printk("psa_comp_number: %d, ", p->psa_comp_number); + printk("psa_thr_pre_set: 0x%02x\n", p->psa_thr_pre_set); + printk(KERN_DEBUG "psa_feature_select/decay_prm: 0x%02x, ", + p->psa_feature_select); + printk("psa_subband/decay_update_prm: %d\n", p->psa_subband); + printk(KERN_DEBUG "psa_quality_thr: 0x%02x, ", p->psa_quality_thr); + printk("psa_mod_delay: 0x%02x\n", p->psa_mod_delay); + printk(KERN_DEBUG "psa_nwid: 0x%02x%02x, ", p->psa_nwid[0], + p->psa_nwid[1]); + printk("psa_nwid_select: %d\n", p->psa_nwid_select); + printk(KERN_DEBUG "psa_encryption_select: %d, ", + p->psa_encryption_select); + printk + ("psa_encryption_key[]: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + p->psa_encryption_key[0], p->psa_encryption_key[1], + p->psa_encryption_key[2], p->psa_encryption_key[3], + p->psa_encryption_key[4], p->psa_encryption_key[5], + p->psa_encryption_key[6], p->psa_encryption_key[7]); + printk(KERN_DEBUG "psa_databus_width: %d\n", p->psa_databus_width); + printk(KERN_DEBUG "psa_call_code/auto_squelch: 0x%02x, ", + p->psa_call_code[0]); + printk + ("psa_call_code[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", + p->psa_call_code[0], p->psa_call_code[1], p->psa_call_code[2], + p->psa_call_code[3], p->psa_call_code[4], p->psa_call_code[5], + p->psa_call_code[6], p->psa_call_code[7]); #ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "psa_reserved[]: %02X:%02X:%02X:%02X\n", - p->psa_reserved[0], - p->psa_reserved[1], - p->psa_reserved[2], - p->psa_reserved[3]); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "psa_conf_status: %d, ", p->psa_conf_status); - printk("psa_crc: 0x%02x%02x, ", p->psa_crc[0], p->psa_crc[1]); - printk("psa_crc_status: 0x%02x\n", p->psa_crc_status); -} /* wv_psa_show */ -#endif /* DEBUG_PSA_SHOW */ + printk(KERN_DEBUG "psa_reserved[]: %02X:%02X:%02X:%02X\n", + p->psa_reserved[0], + p->psa_reserved[1], p->psa_reserved[2], p->psa_reserved[3]); +#endif /* DEBUG_SHOW_UNUSED */ + printk(KERN_DEBUG "psa_conf_status: %d, ", p->psa_conf_status); + printk("psa_crc: 0x%02x%02x, ", p->psa_crc[0], p->psa_crc[1]); + printk("psa_crc_status: 0x%02x\n", p->psa_crc_status); +} /* wv_psa_show */ +#endif /* DEBUG_PSA_SHOW */ #ifdef DEBUG_MMC_SHOW /*------------------------------------------------------------------*/ @@ -1048,411 +968,432 @@ wv_psa_show(psa_t * p) * Print the formatted status of the Modem Management Controller. * This function needs to be completed. */ -static void -wv_mmc_show(device * dev) +static void wv_mmc_show(device * dev) { - u_long ioaddr = dev->base_addr; - net_local * lp = (net_local *)dev->priv; - mmr_t m; - - /* Basic check */ - if(hasr_read(ioaddr) & HASR_NO_CLK) - { - printk(KERN_WARNING "%s: wv_mmc_show: modem not connected\n", - dev->name); - return; - } - - /* Read the mmc */ - mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); - mmc_read(ioaddr, 0, (u_char *)&m, sizeof(m)); - mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0); - -#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */ - /* Don't forget to update statistics */ - lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l; -#endif /* WIRELESS_EXT */ - - printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n"); + unsigned long ioaddr = dev->base_addr; + net_local *lp = (net_local *) dev->priv; + mmr_t m; + + /* Basic check */ + if (hasr_read(ioaddr) & HASR_NO_CLK) { + printk(KERN_WARNING + "%s: wv_mmc_show: modem not connected\n", + dev->name); + return; + } + + /* Read the mmc */ + mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); + mmc_read(ioaddr, 0, (u8 *) & m, sizeof(m)); + mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0); + +#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */ + /* Don't forget to update statistics */ + lp->wstats.discard.nwid += + (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l; +#endif /* WIRELESS_EXT */ + + printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n"); #ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "mmc_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - m.mmr_unused0[0], - m.mmr_unused0[1], - m.mmr_unused0[2], - m.mmr_unused0[3], - m.mmr_unused0[4], - m.mmr_unused0[5], - m.mmr_unused0[6], - m.mmr_unused0[7]); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "Encryption algorithm: %02X - Status: %02X\n", - m.mmr_des_avail, m.mmr_des_status); + printk(KERN_DEBUG + "mmc_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", + m.mmr_unused0[0], m.mmr_unused0[1], m.mmr_unused0[2], + m.mmr_unused0[3], m.mmr_unused0[4], m.mmr_unused0[5], + m.mmr_unused0[6], m.mmr_unused0[7]); +#endif /* DEBUG_SHOW_UNUSED */ + printk(KERN_DEBUG "Encryption algorithm: %02X - Status: %02X\n", + m.mmr_des_avail, m.mmr_des_status); #ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "mmc_unused1[]: %02X:%02X:%02X:%02X:%02X\n", - m.mmr_unused1[0], - m.mmr_unused1[1], - m.mmr_unused1[2], - m.mmr_unused1[3], - m.mmr_unused1[4]); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "dce_status: 0x%x [%s%s%s%s]\n", - m.mmr_dce_status, - (m.mmr_dce_status & MMR_DCE_STATUS_RX_BUSY) ? "energy detected,":"", - (m.mmr_dce_status & MMR_DCE_STATUS_LOOPT_IND) ? - "loop test indicated," : "", - (m.mmr_dce_status & MMR_DCE_STATUS_TX_BUSY) ? "transmitter on," : "", - (m.mmr_dce_status & MMR_DCE_STATUS_JBR_EXPIRED) ? - "jabber timer expired," : ""); - printk(KERN_DEBUG "Dsp ID: %02X\n", - m.mmr_dsp_id); + printk(KERN_DEBUG "mmc_unused1[]: %02X:%02X:%02X:%02X:%02X\n", + m.mmr_unused1[0], + m.mmr_unused1[1], + m.mmr_unused1[2], m.mmr_unused1[3], m.mmr_unused1[4]); +#endif /* DEBUG_SHOW_UNUSED */ + printk(KERN_DEBUG "dce_status: 0x%x [%s%s%s%s]\n", + m.mmr_dce_status, + (m. + mmr_dce_status & MMR_DCE_STATUS_RX_BUSY) ? + "energy detected," : "", + (m. + mmr_dce_status & MMR_DCE_STATUS_LOOPT_IND) ? + "loop test indicated," : "", + (m. + mmr_dce_status & MMR_DCE_STATUS_TX_BUSY) ? + "transmitter on," : "", + (m. + mmr_dce_status & MMR_DCE_STATUS_JBR_EXPIRED) ? + "jabber timer expired," : ""); + printk(KERN_DEBUG "Dsp ID: %02X\n", m.mmr_dsp_id); #ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "mmc_unused2[]: %02X:%02X\n", - m.mmr_unused2[0], - m.mmr_unused2[1]); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "# correct_nwid: %d, # wrong_nwid: %d\n", - (m.mmr_correct_nwid_h << 8) | m.mmr_correct_nwid_l, - (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l); - printk(KERN_DEBUG "thr_pre_set: 0x%x [current signal %s]\n", - m.mmr_thr_pre_set & MMR_THR_PRE_SET, - (m.mmr_thr_pre_set & MMR_THR_PRE_SET_CUR) ? "above" : "below"); - printk(KERN_DEBUG "signal_lvl: %d [%s], ", - m.mmr_signal_lvl & MMR_SIGNAL_LVL, - (m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) ? "new msg" : "no new msg"); - printk("silence_lvl: %d [%s], ", m.mmr_silence_lvl & MMR_SILENCE_LVL, - (m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) ? "update done" : "no new update"); - printk("sgnl_qual: 0x%x [%s]\n", - m.mmr_sgnl_qual & MMR_SGNL_QUAL, - (m.mmr_sgnl_qual & MMR_SGNL_QUAL_ANT) ? "Antenna 1" : "Antenna 0"); + printk(KERN_DEBUG "mmc_unused2[]: %02X:%02X\n", + m.mmr_unused2[0], m.mmr_unused2[1]); +#endif /* DEBUG_SHOW_UNUSED */ + printk(KERN_DEBUG "# correct_nwid: %d, # wrong_nwid: %d\n", + (m.mmr_correct_nwid_h << 8) | m.mmr_correct_nwid_l, + (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l); + printk(KERN_DEBUG "thr_pre_set: 0x%x [current signal %s]\n", + m.mmr_thr_pre_set & MMR_THR_PRE_SET, + (m. + mmr_thr_pre_set & MMR_THR_PRE_SET_CUR) ? "above" : + "below"); + printk(KERN_DEBUG "signal_lvl: %d [%s], ", + m.mmr_signal_lvl & MMR_SIGNAL_LVL, + (m. + mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) ? "new msg" : + "no new msg"); + printk("silence_lvl: %d [%s], ", + m.mmr_silence_lvl & MMR_SILENCE_LVL, + (m. + mmr_silence_lvl & MMR_SILENCE_LVL_VALID) ? "update done" : + "no new update"); + printk("sgnl_qual: 0x%x [%s]\n", m.mmr_sgnl_qual & MMR_SGNL_QUAL, + (m. + mmr_sgnl_qual & MMR_SGNL_QUAL_ANT) ? "Antenna 1" : + "Antenna 0"); #ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "netw_id_l: %x\n", m.mmr_netw_id_l); -#endif /* DEBUG_SHOW_UNUSED */ -} /* wv_mmc_show */ -#endif /* DEBUG_MMC_SHOW */ + printk(KERN_DEBUG "netw_id_l: %x\n", m.mmr_netw_id_l); +#endif /* DEBUG_SHOW_UNUSED */ +} /* wv_mmc_show */ +#endif /* DEBUG_MMC_SHOW */ #ifdef DEBUG_I82586_SHOW /*------------------------------------------------------------------*/ /* * Print the last block of the i82586 memory. */ -static void -wv_scb_show(u_long ioaddr) +static void wv_scb_show(unsigned long ioaddr) { - scb_t scb; - - obram_read(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb)); - - printk(KERN_DEBUG "##### WaveLAN system control block: #####\n"); - - printk(KERN_DEBUG "status: "); - printk("stat 0x%x[%s%s%s%s] ", - (scb.scb_status & (SCB_ST_CX | SCB_ST_FR | SCB_ST_CNA | SCB_ST_RNR)) >> 12, - (scb.scb_status & SCB_ST_CX) ? "command completion interrupt," : "", - (scb.scb_status & SCB_ST_FR) ? "frame received," : "", - (scb.scb_status & SCB_ST_CNA) ? "command unit not active," : "", - (scb.scb_status & SCB_ST_RNR) ? "receiving unit not ready," : ""); - printk("cus 0x%x[%s%s%s] ", - (scb.scb_status & SCB_ST_CUS) >> 8, - ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_IDLE) ? "idle" : "", - ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_SUSP) ? "suspended" : "", - ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_ACTV) ? "active" : ""); - printk("rus 0x%x[%s%s%s%s]\n", - (scb.scb_status & SCB_ST_RUS) >> 4, - ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_IDLE) ? "idle" : "", - ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_SUSP) ? "suspended" : "", - ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_NRES) ? "no resources" : "", - ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_RDY) ? "ready" : ""); - - printk(KERN_DEBUG "command: "); - printk("ack 0x%x[%s%s%s%s] ", - (scb.scb_command & (SCB_CMD_ACK_CX | SCB_CMD_ACK_FR | SCB_CMD_ACK_CNA | SCB_CMD_ACK_RNR)) >> 12, - (scb.scb_command & SCB_CMD_ACK_CX) ? "ack cmd completion," : "", - (scb.scb_command & SCB_CMD_ACK_FR) ? "ack frame received," : "", - (scb.scb_command & SCB_CMD_ACK_CNA) ? "ack CU not active," : "", - (scb.scb_command & SCB_CMD_ACK_RNR) ? "ack RU not ready," : ""); - printk("cuc 0x%x[%s%s%s%s%s] ", - (scb.scb_command & SCB_CMD_CUC) >> 8, - ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_NOP) ? "nop" : "", - ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_GO) ? "start cbl_offset" : "", - ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_RES) ? "resume execution" : "", - ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_SUS) ? "suspend execution" : "", - ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_ABT) ? "abort execution" : ""); - printk("ruc 0x%x[%s%s%s%s%s]\n", - (scb.scb_command & SCB_CMD_RUC) >> 4, - ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_NOP) ? "nop" : "", - ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_GO) ? "start rfa_offset" : "", - ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_RES) ? "resume reception" : "", - ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_SUS) ? "suspend reception" : "", - ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_ABT) ? "abort reception" : ""); - - printk(KERN_DEBUG "cbl_offset 0x%x ", scb.scb_cbl_offset); - printk("rfa_offset 0x%x\n", scb.scb_rfa_offset); - - printk(KERN_DEBUG "crcerrs %d ", scb.scb_crcerrs); - printk("alnerrs %d ", scb.scb_alnerrs); - printk("rscerrs %d ", scb.scb_rscerrs); - printk("ovrnerrs %d\n", scb.scb_ovrnerrs); + scb_t scb; + + obram_read(ioaddr, OFFSET_SCB, (unsigned char *) &scb, + sizeof(scb)); + + printk(KERN_DEBUG "##### WaveLAN system control block: #####\n"); + + printk(KERN_DEBUG "status: "); + printk("stat 0x%x[%s%s%s%s] ", + (scb. + scb_status & (SCB_ST_CX | SCB_ST_FR | SCB_ST_CNA | + SCB_ST_RNR)) >> 12, + (scb. + scb_status & SCB_ST_CX) ? "command completion interrupt," : + "", (scb.scb_status & SCB_ST_FR) ? "frame received," : "", + (scb. + scb_status & SCB_ST_CNA) ? "command unit not active," : "", + (scb. + scb_status & SCB_ST_RNR) ? "receiving unit not ready," : + ""); + printk("cus 0x%x[%s%s%s] ", (scb.scb_status & SCB_ST_CUS) >> 8, + ((scb.scb_status & SCB_ST_CUS) == + SCB_ST_CUS_IDLE) ? "idle" : "", + ((scb.scb_status & SCB_ST_CUS) == + SCB_ST_CUS_SUSP) ? "suspended" : "", + ((scb.scb_status & SCB_ST_CUS) == + SCB_ST_CUS_ACTV) ? "active" : ""); + printk("rus 0x%x[%s%s%s%s]\n", (scb.scb_status & SCB_ST_RUS) >> 4, + ((scb.scb_status & SCB_ST_RUS) == + SCB_ST_RUS_IDLE) ? "idle" : "", + ((scb.scb_status & SCB_ST_RUS) == + SCB_ST_RUS_SUSP) ? "suspended" : "", + ((scb.scb_status & SCB_ST_RUS) == + SCB_ST_RUS_NRES) ? "no resources" : "", + ((scb.scb_status & SCB_ST_RUS) == + SCB_ST_RUS_RDY) ? "ready" : ""); + + printk(KERN_DEBUG "command: "); + printk("ack 0x%x[%s%s%s%s] ", + (scb. + scb_command & (SCB_CMD_ACK_CX | SCB_CMD_ACK_FR | + SCB_CMD_ACK_CNA | SCB_CMD_ACK_RNR)) >> 12, + (scb. + scb_command & SCB_CMD_ACK_CX) ? "ack cmd completion," : "", + (scb. + scb_command & SCB_CMD_ACK_FR) ? "ack frame received," : "", + (scb. + scb_command & SCB_CMD_ACK_CNA) ? "ack CU not active," : "", + (scb. + scb_command & SCB_CMD_ACK_RNR) ? "ack RU not ready," : ""); + printk("cuc 0x%x[%s%s%s%s%s] ", + (scb.scb_command & SCB_CMD_CUC) >> 8, + ((scb.scb_command & SCB_CMD_CUC) == + SCB_CMD_CUC_NOP) ? "nop" : "", + ((scb.scb_command & SCB_CMD_CUC) == + SCB_CMD_CUC_GO) ? "start cbl_offset" : "", + ((scb.scb_command & SCB_CMD_CUC) == + SCB_CMD_CUC_RES) ? "resume execution" : "", + ((scb.scb_command & SCB_CMD_CUC) == + SCB_CMD_CUC_SUS) ? "suspend execution" : "", + ((scb.scb_command & SCB_CMD_CUC) == + SCB_CMD_CUC_ABT) ? "abort execution" : ""); + printk("ruc 0x%x[%s%s%s%s%s]\n", + (scb.scb_command & SCB_CMD_RUC) >> 4, + ((scb.scb_command & SCB_CMD_RUC) == + SCB_CMD_RUC_NOP) ? "nop" : "", + ((scb.scb_command & SCB_CMD_RUC) == + SCB_CMD_RUC_GO) ? "start rfa_offset" : "", + ((scb.scb_command & SCB_CMD_RUC) == + SCB_CMD_RUC_RES) ? "resume reception" : "", + ((scb.scb_command & SCB_CMD_RUC) == + SCB_CMD_RUC_SUS) ? "suspend reception" : "", + ((scb.scb_command & SCB_CMD_RUC) == + SCB_CMD_RUC_ABT) ? "abort reception" : ""); + + printk(KERN_DEBUG "cbl_offset 0x%x ", scb.scb_cbl_offset); + printk("rfa_offset 0x%x\n", scb.scb_rfa_offset); + + printk(KERN_DEBUG "crcerrs %d ", scb.scb_crcerrs); + printk("alnerrs %d ", scb.scb_alnerrs); + printk("rscerrs %d ", scb.scb_rscerrs); + printk("ovrnerrs %d\n", scb.scb_ovrnerrs); } /*------------------------------------------------------------------*/ /* * Print the formatted status of the i82586's receive unit. */ -static void -wv_ru_show(device * dev) +static void wv_ru_show(device * dev) { - /* net_local *lp = (net_local *) dev->priv; */ + /* net_local *lp = (net_local *) dev->priv; */ - printk(KERN_DEBUG "##### WaveLAN i82586 receiver unit status: #####\n"); - printk(KERN_DEBUG "ru:"); - /* - * Not implemented yet - */ - printk("\n"); -} /* wv_ru_show */ + printk(KERN_DEBUG + "##### WaveLAN i82586 receiver unit status: #####\n"); + printk(KERN_DEBUG "ru:"); + /* + * Not implemented yet + */ + printk("\n"); +} /* wv_ru_show */ /*------------------------------------------------------------------*/ /* * Display info about one control block of the i82586 memory. */ -static void -wv_cu_show_one(device * dev, - net_local * lp, - int i, - u_short p) +static void wv_cu_show_one(device * dev, net_local * lp, int i, u16 p) { - u_long ioaddr; - ac_tx_t actx; + unsigned long ioaddr; + ac_tx_t actx; - ioaddr = dev->base_addr; + ioaddr = dev->base_addr; - printk("%d: 0x%x:", i, p); + printk("%d: 0x%x:", i, p); - obram_read(ioaddr, p, (unsigned char *)&actx, sizeof(actx)); - printk(" status=0x%x,", actx.tx_h.ac_status); - printk(" command=0x%x,", actx.tx_h.ac_command); + obram_read(ioaddr, p, (unsigned char *) &actx, sizeof(actx)); + printk(" status=0x%x,", actx.tx_h.ac_status); + printk(" command=0x%x,", actx.tx_h.ac_command); - /* - { - tbd_t tbd; + /* + { + tbd_t tbd; - obram_read(ioaddr, actx.tx_tbd_offset, (unsigned char *)&tbd, sizeof(tbd)); - printk(" tbd_status=0x%x,", tbd.tbd_status); - } - */ + obram_read(ioaddr, actx.tx_tbd_offset, (unsigned char *)&tbd, sizeof(tbd)); + printk(" tbd_status=0x%x,", tbd.tbd_status); + } + */ - printk("|"); + printk("|"); } /*------------------------------------------------------------------*/ /* * Print status of the command unit of the i82586. */ -static void -wv_cu_show(device * dev) +static void wv_cu_show(device * dev) { - net_local * lp = (net_local *)dev->priv; - unsigned int i; - u_short p; - - printk(KERN_DEBUG "##### WaveLAN i82586 command unit status: #####\n"); - - printk(KERN_DEBUG); - for(i = 0, p = lp->tx_first_in_use; i < NTXBLOCKS; i++) - { - wv_cu_show_one(dev, lp, i, p); - - p += TXBLOCKZ; - if(p >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) - p -= NTXBLOCKS * TXBLOCKZ; - } - printk("\n"); + net_local *lp = (net_local *) dev->priv; + unsigned int i; + u16 p; + + printk(KERN_DEBUG + "##### WaveLAN i82586 command unit status: #####\n"); + + printk(KERN_DEBUG); + for (i = 0, p = lp->tx_first_in_use; i < NTXBLOCKS; i++) { + wv_cu_show_one(dev, lp, i, p); + + p += TXBLOCKZ; + if (p >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) + p -= NTXBLOCKS * TXBLOCKZ; + } + printk("\n"); } -#endif /* DEBUG_I82586_SHOW */ +#endif /* DEBUG_I82586_SHOW */ #ifdef DEBUG_DEVICE_SHOW /*------------------------------------------------------------------*/ /* * Print the formatted status of the WaveLAN PCMCIA device driver. */ -static void -wv_dev_show(device * dev) +static void wv_dev_show(device * dev) { - printk(KERN_DEBUG "dev:"); - printk(" start=%d,", dev->start); - printk(" tbusy=%ld,", dev->tbusy); - printk(" interrupt=%d,", dev->interrupt); - printk(" trans_start=%ld,", dev->trans_start); - printk(" flags=0x%x,", dev->flags); - printk("\n"); -} /* wv_dev_show */ + printk(KERN_DEBUG "dev:"); + printk(" state=%lX,", dev->state); + printk(" trans_start=%ld,", dev->trans_start); + printk(" flags=0x%x,", dev->flags); + printk("\n"); +} /* wv_dev_show */ /*------------------------------------------------------------------*/ /* * Print the formatted status of the WaveLAN PCMCIA device driver's * private information. */ -static void -wv_local_show(device * dev) +static void wv_local_show(device * dev) { - net_local *lp; + net_local *lp; - lp = (net_local *)dev->priv; + lp = (net_local *) dev->priv; - printk(KERN_DEBUG "local:"); - printk(" tx_n_in_use=%d,", lp->tx_n_in_use); - printk(" hacr=0x%x,", lp->hacr); - printk(" rx_head=0x%x,", lp->rx_head); - printk(" rx_last=0x%x,", lp->rx_last); - printk(" tx_first_free=0x%x,", lp->tx_first_free); - printk(" tx_first_in_use=0x%x,", lp->tx_first_in_use); - printk("\n"); -} /* wv_local_show */ -#endif /* DEBUG_DEVICE_SHOW */ + printk(KERN_DEBUG "local:"); + printk(" tx_n_in_use=%d,", lp->tx_n_in_use); + printk(" hacr=0x%x,", lp->hacr); + printk(" rx_head=0x%x,", lp->rx_head); + printk(" rx_last=0x%x,", lp->rx_last); + printk(" tx_first_free=0x%x,", lp->tx_first_free); + printk(" tx_first_in_use=0x%x,", lp->tx_first_in_use); + printk("\n"); +} /* wv_local_show */ +#endif /* DEBUG_DEVICE_SHOW */ #if defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO) /*------------------------------------------------------------------*/ /* * Dump packet header (and content if necessary) on the screen */ -static inline void -wv_packet_info(u_char * p, /* Packet to dump */ - int length, /* Length of the packet */ - char * msg1, /* Name of the device */ - char * msg2) /* Name of the function */ -{ - int i; - int maxi; - - printk(KERN_DEBUG "%s: %s(): dest %02X:%02X:%02X:%02X:%02X:%02X, length %d\n", - msg1, msg2, p[0], p[1], p[2], p[3], p[4], p[5], length); - printk(KERN_DEBUG "%s: %s(): src %02X:%02X:%02X:%02X:%02X:%02X, type 0x%02X%02X\n", - msg1, msg2, p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13]); +static inline void wv_packet_info(u8 * p, /* Packet to dump */ + int length, /* Length of the packet */ + char *msg1, /* Name of the device */ + char *msg2) +{ /* Name of the function */ + int i; + int maxi; + + printk(KERN_DEBUG + "%s: %s(): dest %02X:%02X:%02X:%02X:%02X:%02X, length %d\n", + msg1, msg2, p[0], p[1], p[2], p[3], p[4], p[5], length); + printk(KERN_DEBUG + "%s: %s(): src %02X:%02X:%02X:%02X:%02X:%02X, type 0x%02X%02X\n", + msg1, msg2, p[6], p[7], p[8], p[9], p[10], p[11], p[12], + p[13]); #ifdef DEBUG_PACKET_DUMP - printk(KERN_DEBUG "data=\""); - - if((maxi = length) > DEBUG_PACKET_DUMP) - maxi = DEBUG_PACKET_DUMP; - for(i = 14; i < maxi; i++) - if(p[i] >= ' ' && p[i] <= '~') - printk(" %c", p[i]); - else - printk("%02X", p[i]); - if(maxi < length) - printk(".."); - printk("\"\n"); - printk(KERN_DEBUG "\n"); -#endif /* DEBUG_PACKET_DUMP */ + printk(KERN_DEBUG "data=\""); + + if ((maxi = length) > DEBUG_PACKET_DUMP) + maxi = DEBUG_PACKET_DUMP; + for (i = 14; i < maxi; i++) + if (p[i] >= ' ' && p[i] <= '~') + printk(" %c", p[i]); + else + printk("%02X", p[i]); + if (maxi < length) + printk(".."); + printk("\"\n"); + printk(KERN_DEBUG "\n"); +#endif /* DEBUG_PACKET_DUMP */ } -#endif /* defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO) */ +#endif /* defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO) */ /*------------------------------------------------------------------*/ /* * This is the information which is displayed by the driver at startup. * There are lots of flags for configuring it to your liking. */ -static inline void -wv_init_info(device * dev) +static inline void wv_init_info(device * dev) { - short ioaddr = dev->base_addr; - net_local * lp = (net_local *)dev->priv; - psa_t psa; - int i; + short ioaddr = dev->base_addr; + net_local *lp = (net_local *) dev->priv; + psa_t psa; + int i; - /* Read the parameter storage area */ - psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa)); + /* Read the parameter storage area */ + psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa)); #ifdef DEBUG_PSA_SHOW - wv_psa_show(&psa); + wv_psa_show(&psa); #endif #ifdef DEBUG_MMC_SHOW - wv_mmc_show(dev); + wv_mmc_show(dev); #endif #ifdef DEBUG_I82586_SHOW - wv_cu_show(dev); + wv_cu_show(dev); #endif #ifdef DEBUG_BASIC_SHOW - /* Now, let's go for the basic stuff. */ - printk(KERN_NOTICE "%s: WaveLAN at %#x,", dev->name, ioaddr); - for(i = 0; i < WAVELAN_ADDR_SIZE; i++) - printk("%s%02X", (i == 0) ? " " : ":", dev->dev_addr[i]); - printk(", IRQ %d", dev->irq); - - /* Print current network ID. */ - if(psa.psa_nwid_select) - printk(", nwid 0x%02X-%02X", psa.psa_nwid[0], psa.psa_nwid[1]); - else - printk(", nwid off"); - - /* If 2.00 card */ - if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) - { - unsigned short freq; - - /* Ask the EEPROM to read the frequency from the first area. */ - fee_read(ioaddr, 0x00, &freq, 1); - - /* Print frequency */ - printk(", 2.00, %ld", (freq >> 6) + 2400L); - - /* Hack! */ - if(freq & 0x20) - printk(".5"); - } - else - { - printk(", PC"); - switch(psa.psa_comp_number) - { - case PSA_COMP_PC_AT_915: - case PSA_COMP_PC_AT_2400: - printk("-AT"); - break; - case PSA_COMP_PC_MC_915: - case PSA_COMP_PC_MC_2400: - printk("-MC"); - break; - case PSA_COMP_PCMCIA_915: - printk("MCIA"); - break; - default: - printk("?"); + /* Now, let's go for the basic stuff. */ + printk(KERN_NOTICE "%s: WaveLAN at %#x,", dev->name, ioaddr); + for (i = 0; i < WAVELAN_ADDR_SIZE; i++) + printk("%s%02X", (i == 0) ? " " : ":", dev->dev_addr[i]); + printk(", IRQ %d", dev->irq); + + /* Print current network ID. */ + if (psa.psa_nwid_select) + printk(", nwid 0x%02X-%02X", psa.psa_nwid[0], + psa.psa_nwid[1]); + else + printk(", nwid off"); + + /* If 2.00 card */ + if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & + (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { + unsigned short freq; + + /* Ask the EEPROM to read the frequency from the first area. */ + fee_read(ioaddr, 0x00, &freq, 1); + + /* Print frequency */ + printk(", 2.00, %ld", (freq >> 6) + 2400L); + + /* Hack! */ + if (freq & 0x20) + printk(".5"); + } else { + printk(", PC"); + switch (psa.psa_comp_number) { + case PSA_COMP_PC_AT_915: + case PSA_COMP_PC_AT_2400: + printk("-AT"); + break; + case PSA_COMP_PC_MC_915: + case PSA_COMP_PC_MC_2400: + printk("-MC"); + break; + case PSA_COMP_PCMCIA_915: + printk("MCIA"); + break; + default: + printk("?"); + } + printk(", "); + switch (psa.psa_subband) { + case PSA_SUBBAND_915: + printk("915"); + break; + case PSA_SUBBAND_2425: + printk("2425"); + break; + case PSA_SUBBAND_2460: + printk("2460"); + break; + case PSA_SUBBAND_2484: + printk("2484"); + break; + case PSA_SUBBAND_2430_5: + printk("2430.5"); + break; + default: + printk("?"); + } } - printk(", "); - switch (psa.psa_subband) - { - case PSA_SUBBAND_915: - printk("915"); - break; - case PSA_SUBBAND_2425: - printk("2425"); - break; - case PSA_SUBBAND_2460: - printk("2460"); - break; - case PSA_SUBBAND_2484: - printk("2484"); - break; - case PSA_SUBBAND_2430_5: - printk("2430.5"); - break; - default: - printk("?"); - } - } - printk(" MHz\n"); -#endif /* DEBUG_BASIC_SHOW */ + printk(" MHz\n"); +#endif /* DEBUG_BASIC_SHOW */ #ifdef DEBUG_VERSION_SHOW - /* Print version information */ - printk(KERN_NOTICE "%s", version); + /* Print version information */ + printk(KERN_NOTICE "%s", version); #endif -} /* wv_init_info */ +} /* wv_init_info */ /********************* IOCTL, STATS & RECONFIG *********************/ /* @@ -1468,14 +1409,13 @@ wv_init_info(device * dev) * card open or closed. * Used when the user read /proc/net/dev */ -static en_stats * -wavelan_get_stats(device * dev) +static en_stats *wavelan_get_stats(device * dev) { #ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name); + printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name); #endif - return(&((net_local *) dev->priv)->stats); + return (&((net_local *) dev->priv)->stats); } /*------------------------------------------------------------------*/ @@ -1486,76 +1426,70 @@ wavelan_get_stats(device * dev) * num_addrs > 0 Multicast mode, receive normal and MC packets, * and do best-effort filtering. */ -static void -wavelan_set_multicast_list(device * dev) +static void wavelan_set_multicast_list(device * dev) { - net_local * lp = (net_local *) dev->priv; + net_local *lp = (net_local *) dev->priv; #ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n", dev->name); + printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n", + dev->name); #endif #ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "%s: wavelan_set_multicast_list(): setting Rx mode %02X to %d addresses.\n", - dev->name, dev->flags, dev->mc_count); + printk(KERN_DEBUG + "%s: wavelan_set_multicast_list(): setting Rx mode %02X to %d addresses.\n", + dev->name, dev->flags, dev->mc_count); #endif - /* Are we asking for promiscuous mode, - * or all multicast addresses (we don't have that!) - * or too many multicast addresses for the hardware filter? */ - if((dev->flags & IFF_PROMISC) || - (dev->flags & IFF_ALLMULTI) || - (dev->mc_count > I82586_MAX_MULTICAST_ADDRESSES)) - { - /* - * Enable promiscuous mode: receive all packets. - */ - if(!lp->promiscuous) - { - lp->promiscuous = 1; - lp->mc_count = 0; - - wv_82586_reconfig(dev); - - /* Tell the kernel that we are doing a really bad job. */ - dev->flags |= IFF_PROMISC; - } - } - else - /* Are there multicast addresses to send? */ - if(dev->mc_list != (struct dev_mc_list *) NULL) - { - /* - * Disable promiscuous mode, but receive all packets - * in multicast list - */ + /* Are we asking for promiscuous mode, + * or all multicast addresses (we don't have that!) + * or too many multicast addresses for the hardware filter? */ + if ((dev->flags & IFF_PROMISC) || + (dev->flags & IFF_ALLMULTI) || + (dev->mc_count > I82586_MAX_MULTICAST_ADDRESSES)) { + /* + * Enable promiscuous mode: receive all packets. + */ + if (!lp->promiscuous) { + lp->promiscuous = 1; + lp->mc_count = 0; + + wv_82586_reconfig(dev); + + /* Tell the kernel that we are doing a really bad job. */ + dev->flags |= IFF_PROMISC; + } + } else + /* Are there multicast addresses to send? */ + if (dev->mc_list != (struct dev_mc_list *) NULL) { + /* + * Disable promiscuous mode, but receive all packets + * in multicast list + */ #ifdef MULTICAST_AVOID - if(lp->promiscuous || - (dev->mc_count != lp->mc_count)) + if (lp->promiscuous || (dev->mc_count != lp->mc_count)) #endif - { - lp->promiscuous = 0; - lp->mc_count = dev->mc_count; - - wv_82586_reconfig(dev); - } - } - else - { - /* - * Switch to normal mode: disable promiscuous mode and - * clear the multicast list. - */ - if(lp->promiscuous || lp->mc_count == 0) - { - lp->promiscuous = 0; - lp->mc_count = 0; - - wv_82586_reconfig(dev); - } - } + { + lp->promiscuous = 0; + lp->mc_count = dev->mc_count; + + wv_82586_reconfig(dev); + } + } else { + /* + * Switch to normal mode: disable promiscuous mode and + * clear the multicast list. + */ + if (lp->promiscuous || lp->mc_count == 0) { + lp->promiscuous = 0; + lp->mc_count = 0; + + wv_82586_reconfig(dev); + } + } #ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: <-wavelan_set_multicast_list()\n", dev->name); + printk(KERN_DEBUG "%s: <-wavelan_set_multicast_list()\n", + dev->name); #endif } @@ -1565,23 +1499,21 @@ wavelan_set_multicast_list(device * dev) * (Note : it was a nice way to test the reconfigure stuff...) */ #ifdef SET_MAC_ADDRESS -static int -wavelan_set_mac_address(device * dev, - void * addr) +static int wavelan_set_mac_address(device * dev, void *addr) { - struct sockaddr * mac = addr; + struct sockaddr *mac = addr; - /* Copy the address. */ - memcpy(dev->dev_addr, mac->sa_data, WAVELAN_ADDR_SIZE); + /* Copy the address. */ + memcpy(dev->dev_addr, mac->sa_data, WAVELAN_ADDR_SIZE); - /* Reconfigure the beast. */ - wv_82586_reconfig(dev); + /* Reconfigure the beast. */ + wv_82586_reconfig(dev); - return 0; + return 0; } -#endif /* SET_MAC_ADDRESS */ +#endif /* SET_MAC_ADDRESS */ -#ifdef WIRELESS_EXT /* if wireless extensions exist in the kernel */ +#ifdef WIRELESS_EXT /* if wireless extensions exist in the kernel */ /*------------------------------------------------------------------*/ /* @@ -1589,232 +1521,215 @@ wavelan_set_mac_address(device * dev, * It's a bit complicated and you don't really want to look into it. * (called in wavelan_ioctl) */ -static inline int -wv_set_frequency(u_long ioaddr, /* I/O port of the card */ - iw_freq * frequency) +static inline int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */ + iw_freq * frequency) { - const int BAND_NUM = 10; /* Number of bands */ - long freq = 0L; /* offset to 2.4 GHz in .5 MHz */ + const int BAND_NUM = 10; /* Number of bands */ + long freq = 0L; /* offset to 2.4 GHz in .5 MHz */ #ifdef DEBUG_IOCTL_INFO - int i; + int i; #endif - /* Setting by frequency */ - /* Theoretically, you may set any frequency between - * the two limits with a 0.5 MHz precision. In practice, - * I don't want you to have trouble with local regulations. - */ - if((frequency->e == 1) && - (frequency->m >= (int) 2.412e8) && (frequency->m <= (int) 2.487e8)) - { - freq = ((frequency->m / 10000) - 24000L) / 5; - } - - /* Setting by channel (same as wfreqsel) */ - /* Warning: each channel is 22 MHz wide, so some of the channels - * will interfere. */ - if((frequency->e == 0) && - (frequency->m >= 0) && (frequency->m < BAND_NUM)) - { - /* Get frequency offset. */ - freq = channel_bands[frequency->m] >> 1; - } - - /* Verify that the frequency is allowed. */ - if(freq != 0L) - { - u_short table[10]; /* Authorized frequency table */ - - /* Read the frequency table. */ - fee_read(ioaddr, 0x71, table, 10); + /* Setting by frequency */ + /* Theoretically, you may set any frequency between + * the two limits with a 0.5 MHz precision. In practice, + * I don't want you to have trouble with local regulations. + */ + if ((frequency->e == 1) && + (frequency->m >= (int) 2.412e8) + && (frequency->m <= (int) 2.487e8)) { + freq = ((frequency->m / 10000) - 24000L) / 5; + } -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "Frequency table: "); - for(i = 0; i < 10; i++) - { - printk(" %04X", - table[i]); + /* Setting by channel (same as wfreqsel) */ + /* Warning: each channel is 22 MHz wide, so some of the channels + * will interfere. */ + if ((frequency->e == 0) && + (frequency->m >= 0) && (frequency->m < BAND_NUM)) { + /* Get frequency offset. */ + freq = channel_bands[frequency->m] >> 1; } - printk("\n"); -#endif - /* Look in the table to see whether the frequency is allowed. */ - if(!(table[9 - ((freq - 24) / 16)] & - (1 << ((freq - 24) % 16)))) - return -EINVAL; /* not allowed */ - } - else - return -EINVAL; - - /* if we get a usable frequency */ - if(freq != 0L) - { - unsigned short area[16]; - unsigned short dac[2]; - unsigned short area_verify[16]; - unsigned short dac_verify[2]; - /* Corresponding gain (in the power adjust value table) - * See AT&T WaveLAN Data Manual, REF 407-024689/E, page 3-8 - * and WCIN062D.DOC, page 6.2.9. */ - unsigned short power_limit[] = { 40, 80, 120, 160, 0 }; - int power_band = 0; /* Selected band */ - unsigned short power_adjust; /* Correct value */ - - /* Search for the gain. */ - power_band = 0; - while((freq > power_limit[power_band]) && - (power_limit[++power_band] != 0)) - ; - - /* Read the first area. */ - fee_read(ioaddr, 0x00, area, 16); - - /* Read the DAC. */ - fee_read(ioaddr, 0x60, dac, 2); - - /* Read the new power adjust value. */ - fee_read(ioaddr, 0x6B - (power_band >> 1), &power_adjust, 1); - if(power_band & 0x1) - power_adjust >>= 8; - else - power_adjust &= 0xFF; + /* Verify that the frequency is allowed. */ + if (freq != 0L) { + u16 table[10]; /* Authorized frequency table */ + + /* Read the frequency table. */ + fee_read(ioaddr, 0x71, table, 10); #ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "WaveLAN EEPROM Area 1: "); - for(i = 0; i < 16; i++) - { - printk(" %04X", - area[i]); - } - printk("\n"); + printk(KERN_DEBUG "Frequency table: "); + for (i = 0; i < 10; i++) { + printk(" %04X", table[i]); + } + printk("\n"); +#endif - printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n", - dac[0], dac[1]); + /* Look in the table to see whether the frequency is allowed. */ + if (!(table[9 - ((freq - 24) / 16)] & + (1 << ((freq - 24) % 16)))) return -EINVAL; /* not allowed */ + } else + return -EINVAL; + + /* if we get a usable frequency */ + if (freq != 0L) { + unsigned short area[16]; + unsigned short dac[2]; + unsigned short area_verify[16]; + unsigned short dac_verify[2]; + /* Corresponding gain (in the power adjust value table) + * See AT&T WaveLAN Data Manual, REF 407-024689/E, page 3-8 + * and WCIN062D.DOC, page 6.2.9. */ + unsigned short power_limit[] = { 40, 80, 120, 160, 0 }; + int power_band = 0; /* Selected band */ + unsigned short power_adjust; /* Correct value */ + + /* Search for the gain. */ + power_band = 0; + while ((freq > power_limit[power_band]) && + (power_limit[++power_band] != 0)); + + /* Read the first area. */ + fee_read(ioaddr, 0x00, area, 16); + + /* Read the DAC. */ + fee_read(ioaddr, 0x60, dac, 2); + + /* Read the new power adjust value. */ + fee_read(ioaddr, 0x6B - (power_band >> 1), &power_adjust, + 1); + if (power_band & 0x1) + power_adjust >>= 8; + else + power_adjust &= 0xFF; + +#ifdef DEBUG_IOCTL_INFO + printk(KERN_DEBUG "WaveLAN EEPROM Area 1: "); + for (i = 0; i < 16; i++) { + printk(" %04X", area[i]); + } + printk("\n"); + + printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n", + dac[0], dac[1]); #endif - /* Frequency offset (for info only) */ - area[0] = ((freq << 5) & 0xFFE0) | (area[0] & 0x1F); + /* Frequency offset (for info only) */ + area[0] = ((freq << 5) & 0xFFE0) | (area[0] & 0x1F); - /* Receiver Principle main divider coefficient */ - area[3] = (freq >> 1) + 2400L - 352L; - area[2] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF); + /* Receiver Principle main divider coefficient */ + area[3] = (freq >> 1) + 2400L - 352L; + area[2] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF); - /* Transmitter Main divider coefficient */ - area[13] = (freq >> 1) + 2400L; - area[12] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF); + /* Transmitter Main divider coefficient */ + area[13] = (freq >> 1) + 2400L; + area[12] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF); - /* Other parts of the area are flags, bit streams or unused. */ + /* Other parts of the area are flags, bit streams or unused. */ - /* Set the value in the DAC. */ - dac[1] = ((power_adjust >> 1) & 0x7F) | (dac[1] & 0xFF80); - dac[0] = ((power_adjust & 0x1) << 4) | (dac[0] & 0xFFEF); + /* Set the value in the DAC. */ + dac[1] = ((power_adjust >> 1) & 0x7F) | (dac[1] & 0xFF80); + dac[0] = ((power_adjust & 0x1) << 4) | (dac[0] & 0xFFEF); - /* Write the first area. */ - fee_write(ioaddr, 0x00, - area, 16); + /* Write the first area. */ + fee_write(ioaddr, 0x00, area, 16); - /* Write the DAC. */ - fee_write(ioaddr, 0x60, - dac, 2); + /* Write the DAC. */ + fee_write(ioaddr, 0x60, dac, 2); - /* We now should verify here that the writing of the EEPROM went OK. */ + /* We now should verify here that the writing of the EEPROM went OK. */ - /* Reread the first area. */ - fee_read(ioaddr, 0x00, area_verify, 16); + /* Reread the first area. */ + fee_read(ioaddr, 0x00, area_verify, 16); - /* Reread the DAC. */ - fee_read(ioaddr, 0x60, dac_verify, 2); + /* Reread the DAC. */ + fee_read(ioaddr, 0x60, dac_verify, 2); - /* Compare. */ - if(memcmp(area, area_verify, 16 * 2) || - memcmp(dac, dac_verify, 2 * 2)) - { + /* Compare. */ + if (memcmp(area, area_verify, 16 * 2) || + memcmp(dac, dac_verify, 2 * 2)) { #ifdef DEBUG_IOCTL_ERROR - printk(KERN_INFO "WaveLAN: wv_set_frequency: unable to write new frequency to EEPROM(?).\n"); + printk(KERN_INFO + "WaveLAN: wv_set_frequency: unable to write new frequency to EEPROM(?).\n"); #endif - return -EOPNOTSUPP; - } + return -EOPNOTSUPP; + } - /* We must download the frequency parameters to the - * synthesizers (from the EEPROM - area 1) - * Note: as the EEPROM is automatically decremented, we set the end - * if the area... */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x0F); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), - MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD); + /* We must download the frequency parameters to the + * synthesizers (from the EEPROM - area 1) + * Note: as the EEPROM is automatically decremented, we set the end + * if the area... */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x0F); + mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), + MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD); - /* Wait until the download is finished. */ - fee_wait(ioaddr, 100, 100); + /* Wait until the download is finished. */ + fee_wait(ioaddr, 100, 100); - /* We must now download the power adjust value (gain) to - * the synthesizers (from the EEPROM - area 7 - DAC). */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x61); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), - MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD); + /* We must now download the power adjust value (gain) to + * the synthesizers (from the EEPROM - area 7 - DAC). */ + mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x61); + mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), + MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD); - /* Wait for the download to finish. */ - fee_wait(ioaddr, 100, 100); + /* Wait for the download to finish. */ + fee_wait(ioaddr, 100, 100); #ifdef DEBUG_IOCTL_INFO - /* Verification of what we have done */ + /* Verification of what we have done */ - printk(KERN_DEBUG "WaveLAN EEPROM Area 1: "); - for(i = 0; i < 16; i++) - { - printk(" %04X", - area_verify[i]); - } - printk("\n"); + printk(KERN_DEBUG "WaveLAN EEPROM Area 1: "); + for (i = 0; i < 16; i++) { + printk(" %04X", area_verify[i]); + } + printk("\n"); - printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n", - dac_verify[0], dac_verify[1]); + printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n", + dac_verify[0], dac_verify[1]); #endif - return 0; - } - else - return -EINVAL; /* Bah, never get there... */ + return 0; + } else + return -EINVAL; /* Bah, never get there... */ } /*------------------------------------------------------------------*/ /* * Give the list of available frequencies. */ -static inline int -wv_frequency_list(u_long ioaddr, /* I/O port of the card */ - iw_freq * list, /* List of frequencies to fill */ - int max) /* Maximum number of frequencies */ -{ - u_short table[10]; /* Authorized frequency table */ - long freq = 0L; /* offset to 2.4 GHz in .5 MHz + 12 MHz */ - int i; /* index in the table */ - int c = 0; /* Channel number */ - - /* Read the frequency table. */ - fee_read(ioaddr, 0x71 /* frequency table */, table, 10); - - /* Check all frequencies. */ - i = 0; - for(freq = 0; freq < 150; freq++) - /* Look in the table if the frequency is allowed */ - if(table[9 - (freq / 16)] & (1 << (freq % 16))) - { - /* Compute approximate channel number */ - while((((channel_bands[c] >> 1) - 24) < freq) && - (c < NELS(channel_bands))) - c++; - list[i].i = c; /* Set the list index */ - - /* put in the list */ - list[i].m = (((freq + 24) * 5) + 24000L) * 10000; - list[i++].e = 1; - - /* Check number. */ - if(i >= max) - return(i); - } - - return(i); +static inline int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */ + iw_freq * list, /* List of frequencies to fill */ + int max) +{ /* Maximum number of frequencies */ + u16 table[10]; /* Authorized frequency table */ + long freq = 0L; /* offset to 2.4 GHz in .5 MHz + 12 MHz */ + int i; /* index in the table */ + int c = 0; /* Channel number */ + + /* Read the frequency table. */ + fee_read(ioaddr, 0x71 /* frequency table */ , table, 10); + + /* Check all frequencies. */ + i = 0; + for (freq = 0; freq < 150; freq++) + /* Look in the table if the frequency is allowed */ + if (table[9 - (freq / 16)] & (1 << (freq % 16))) { + /* Compute approximate channel number */ + while ((((channel_bands[c] >> 1) - 24) < freq) && + (c < NELS(channel_bands))) + c++; + list[i].i = c; /* Set the list index */ + + /* put in the list */ + list[i].m = (((freq + 24) * 5) + 24000L) * 10000; + list[i++].e = 1; + + /* Check number. */ + if (i >= max) + return (i); + } + + return (i); } #ifdef WIRELESS_SPY @@ -1824,27 +1739,24 @@ wv_frequency_list(u_long ioaddr, /* I/O port of the card */ * address with our list, and if they match, get the statistics. * Sorry, but this function really needs the wireless extensions. */ -static inline void -wl_spy_gather(device * dev, - u_char * mac, /* MAC address */ - u_char * stats) /* Statistics to gather */ -{ - net_local * lp = (net_local *) dev->priv; - int i; - - /* Check all addresses. */ - for(i = 0; i < lp->spy_number; i++) - /* If match */ - if(!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE)) - { - /* Update statistics */ - lp->spy_stat[i].qual = stats[2] & MMR_SGNL_QUAL; - lp->spy_stat[i].level = stats[0] & MMR_SIGNAL_LVL; - lp->spy_stat[i].noise = stats[1] & MMR_SILENCE_LVL; - lp->spy_stat[i].updated = 0x7; - } +static inline void wl_spy_gather(device * dev, u8 * mac, /* MAC address */ + u8 * stats) +{ /* Statistics to gather */ + net_local *lp = (net_local *) dev->priv; + int i; + + /* Check all addresses. */ + for (i = 0; i < lp->spy_number; i++) + /* If match */ + if (!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE)) { + /* Update statistics */ + lp->spy_stat[i].qual = stats[2] & MMR_SGNL_QUAL; + lp->spy_stat[i].level = stats[0] & MMR_SIGNAL_LVL; + lp->spy_stat[i].noise = stats[1] & MMR_SILENCE_LVL; + lp->spy_stat[i].updated = 0x7; + } } -#endif /* WIRELESS_SPY */ +#endif /* WIRELESS_SPY */ #ifdef HISTOGRAM /*------------------------------------------------------------------*/ @@ -1856,494 +1768,516 @@ wl_spy_gather(device * dev, * With this histogram you may detect if one WaveLAN is really weak, * or you may also calculate the mean and standard deviation of the level. */ -static inline void -wl_his_gather(device * dev, - u_char * stats) /* Statistics to gather */ -{ - net_local * lp = (net_local *) dev->priv; - u_char level = stats[0] & MMR_SIGNAL_LVL; - int i; - - /* Find the correct interval. */ - i = 0; - while((i < (lp->his_number - 1)) && (level >= lp->his_range[i++])) - ; - - /* Increment interval counter. */ - (lp->his_sum[i])++; +static inline void wl_his_gather(device * dev, u8 * stats) +{ /* Statistics to gather */ + net_local *lp = (net_local *) dev->priv; + u8 level = stats[0] & MMR_SIGNAL_LVL; + int i; + + /* Find the correct interval. */ + i = 0; + while ((i < (lp->his_number - 1)) + && (level >= lp->his_range[i++])); + + /* Increment interval counter. */ + (lp->his_sum[i])++; } -#endif /* HISTOGRAM */ +#endif /* HISTOGRAM */ /*------------------------------------------------------------------*/ /* * Perform ioctl for configuration and information. * It is here that the wireless extensions are treated (iwconfig). */ -static int -wavelan_ioctl(struct net_device * dev, /* device on which the ioctl is applied */ - struct ifreq * rq, /* data passed */ - int cmd) /* ioctl number */ -{ - u_long ioaddr = dev->base_addr; - net_local * lp = (net_local *)dev->priv; /* lp is not unused */ - struct iwreq * wrq = (struct iwreq *) rq; - psa_t psa; - mm_t m; - unsigned long x; - int ret = 0; +static int wavelan_ioctl(struct net_device *dev, /* device on which the ioctl is applied */ + struct ifreq *rq, /* data passed */ + int cmd) +{ /* ioctl number */ + unsigned long ioaddr = dev->base_addr; + net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + struct iwreq *wrq = (struct iwreq *) rq; + psa_t psa; + mm_t m; + unsigned long flags; + int ret = 0; #ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name, cmd); + printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name, + cmd); #endif - /* Disable interrupts and save flags. */ - x = wv_splhi(); - - /* Look what is the request */ - switch(cmd) - { - /* --------------- WIRELESS EXTENSIONS --------------- */ - - case SIOCGIWNAME: - strcpy(wrq->u.name, "WaveLAN"); - break; - - case SIOCSIWNWID: - /* Set NWID in WaveLAN. */ - if(!wrq->u.nwid.disabled) - { - /* Set NWID in psa */ - psa.psa_nwid[0] = (wrq->u.nwid.value & 0xFF00) >> 8; - psa.psa_nwid[1] = wrq->u.nwid.value & 0xFF; - psa.psa_nwid_select = 0x01; - psa_write(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa, - (unsigned char *)psa.psa_nwid, 3); - - /* Set NWID in mmc. */ - m.w.mmw_netw_id_l = psa.psa_nwid[1]; - m.w.mmw_netw_id_h = psa.psa_nwid[0]; - mmc_write(ioaddr, (char *)&m.w.mmw_netw_id_l - (char *)&m, - (unsigned char *)&m.w.mmw_netw_id_l, 2); - mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00); - } - else - { - /* Disable NWID in the psa. */ - psa.psa_nwid_select = 0x00; - psa_write(ioaddr, lp->hacr, - (char *)&psa.psa_nwid_select - (char *)&psa, - (unsigned char *)&psa.psa_nwid_select, 1); - - /* Disable NWID in the mmc (no filtering). */ - mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID); - } - /* update the Wavelan checksum */ - update_psa_checksum(dev, ioaddr, lp->hacr); - break; - - case SIOCGIWNWID: - /* Read the NWID. */ - psa_read(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa, - (unsigned char *)psa.psa_nwid, 3); - wrq->u.nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1]; - wrq->u.nwid.disabled = !(psa.psa_nwid_select); - wrq->u.nwid.fixed = 1; /* Superfluous */ - break; - - case SIOCSIWFREQ: - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */ - if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) - ret = wv_set_frequency(ioaddr, &(wrq->u.freq)); - else - ret = -EOPNOTSUPP; - break; - - case SIOCGIWFREQ: - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). - * Does it work for everybody, especially old cards? */ - if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) - { - unsigned short freq; - - /* Ask the EEPROM to read the frequency from the first area. */ - fee_read(ioaddr, 0x00, &freq, 1); - wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000; - wrq->u.freq.e = 1; - } - else - { - psa_read(ioaddr, lp->hacr, (char *)&psa.psa_subband - (char *)&psa, - (unsigned char *)&psa.psa_subband, 1); - - if(psa.psa_subband <= 4) - { - wrq->u.freq.m = fixed_bands[psa.psa_subband]; - wrq->u.freq.e = (psa.psa_subband != 0); - } - else - ret = -EOPNOTSUPP; - } - break; - - case SIOCSIWSENS: - /* Set the level threshold. */ - /* We should complain loudly if wrq->u.sens.fixed = 0, because we - * can't set auto mode... */ - psa.psa_thr_pre_set = wrq->u.sens.value & 0x3F; - psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa, - (unsigned char *) &psa.psa_thr_pre_set, 1); - /* update the Wavelan checksum */ - update_psa_checksum(dev, ioaddr, lp->hacr); - mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set), psa.psa_thr_pre_set); - break; - - case SIOCGIWSENS: - /* Read the level threshold. */ - psa_read(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa, - (unsigned char *) &psa.psa_thr_pre_set, 1); - wrq->u.sens.value = psa.psa_thr_pre_set & 0x3F; - wrq->u.sens.fixed = 1; - break; - - case SIOCSIWENCODE: - /* Set encryption key */ - if(!mmc_encr(ioaddr)) - { - ret = -EOPNOTSUPP; - break; - } - - /* Basic checking... */ - if(wrq->u.encoding.pointer != (caddr_t) 0) - { - /* Check the size of the key */ - if(wrq->u.encoding.length != 8) - { - ret = -EINVAL; - break; - } - - /* Copy the key in the driver */ - if(copy_from_user(psa.psa_encryption_key, wrq->u.encoding.pointer, - wrq->u.encoding.length)) - { - ret = -EFAULT; - break; - } - - psa.psa_encryption_select = 1; - psa_write(ioaddr, lp->hacr, - (char *) &psa.psa_encryption_select - (char *) &psa, - (unsigned char *) &psa.psa_encryption_select, 8+1); - - mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), - MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE); - mmc_write(ioaddr, mmwoff(0, mmw_encr_key), - (unsigned char *) &psa.psa_encryption_key, 8); - } - - if(wrq->u.encoding.flags & IW_ENCODE_DISABLED) - { /* disable encryption */ - psa.psa_encryption_select = 0; - psa_write(ioaddr, lp->hacr, - (char *) &psa.psa_encryption_select - (char *) &psa, - (unsigned char *) &psa.psa_encryption_select, 1); - - mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0); - } - /* update the Wavelan checksum */ - update_psa_checksum(dev, ioaddr, lp->hacr); - break; - - case SIOCGIWENCODE: - /* Read the encryption key */ - if(!mmc_encr(ioaddr)) - { - ret = -EOPNOTSUPP; - break; - } - - /* only super-user can see encryption key */ - if(!suser()) - { - ret = -EPERM; - break; - } - - /* Basic checking... */ - if(wrq->u.encoding.pointer != (caddr_t) 0) - { - /* Verify the user buffer */ - ret = verify_area(VERIFY_WRITE, wrq->u.encoding.pointer, 8); - if(ret) - break; - - psa_read(ioaddr, lp->hacr, - (char *) &psa.psa_encryption_select - (char *) &psa, - (unsigned char *) &psa.psa_encryption_select, 1+8); - - /* encryption is enabled ? */ - if(psa.psa_encryption_select) - wrq->u.encoding.flags = IW_ENCODE_ENABLED; - else - wrq->u.encoding.flags = IW_ENCODE_DISABLED; - wrq->u.encoding.flags |= mmc_encr(ioaddr); - - /* Copy the key to the user buffer */ - wrq->u.encoding.length = 8; - if(copy_to_user(wrq->u.encoding.pointer, psa.psa_encryption_key, 8)) - ret = -EFAULT; - } - break; - - case SIOCGIWRANGE: - /* basic checking */ - if(wrq->u.data.pointer != (caddr_t) 0) - { - struct iw_range range; - - /* Set the length (useless: it's constant). */ - wrq->u.data.length = sizeof(struct iw_range); - - /* Set information in the range struct. */ - range.throughput = 1.6 * 1000 * 1000; /* don't argue on this ! */ - range.min_nwid = 0x0000; - range.max_nwid = 0xFFFF; - - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */ - if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) - { - range.num_channels = 10; - range.num_frequency = wv_frequency_list(ioaddr, range.freq, + /* Disable interrupts and save flags. */ + save_flags(flags); + cli(); + /* FIXME: can't copy*user when cli this is broken! */ + + /* Look what is the request */ + switch (cmd) { + /* --------------- WIRELESS EXTENSIONS --------------- */ + + case SIOCGIWNAME: + strcpy(wrq->u.name, "WaveLAN"); + break; + + case SIOCSIWNWID: + /* Set NWID in WaveLAN. */ + if (!wrq->u.nwid.disabled) { + /* Set NWID in psa */ + psa.psa_nwid[0] = + (wrq->u.nwid.value & 0xFF00) >> 8; + psa.psa_nwid[1] = wrq->u.nwid.value & 0xFF; + psa.psa_nwid_select = 0x01; + psa_write(ioaddr, lp->hacr, + (char *) psa.psa_nwid - (char *) &psa, + (unsigned char *) psa.psa_nwid, 3); + + /* Set NWID in mmc. */ + m.w.mmw_netw_id_l = psa.psa_nwid[1]; + m.w.mmw_netw_id_h = psa.psa_nwid[0]; + mmc_write(ioaddr, + (char *) &m.w.mmw_netw_id_l - + (char *) &m, + (unsigned char *) &m.w.mmw_netw_id_l, 2); + mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00); + } else { + /* Disable NWID in the psa. */ + psa.psa_nwid_select = 0x00; + psa_write(ioaddr, lp->hacr, + (char *) &psa.psa_nwid_select - + (char *) &psa, + (unsigned char *) &psa.psa_nwid_select, + 1); + + /* Disable NWID in the mmc (no filtering). */ + mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), + MMW_LOOPT_SEL_DIS_NWID); + } + /* update the Wavelan checksum */ + update_psa_checksum(dev, ioaddr, lp->hacr); + break; + + case SIOCGIWNWID: + /* Read the NWID. */ + psa_read(ioaddr, lp->hacr, + (char *) psa.psa_nwid - (char *) &psa, + (unsigned char *) psa.psa_nwid, 3); + wrq->u.nwid.value = + (psa.psa_nwid[0] << 8) + psa.psa_nwid[1]; + wrq->u.nwid.disabled = !(psa.psa_nwid_select); + wrq->u.nwid.fixed = 1; /* Superfluous */ + break; + + case SIOCSIWFREQ: + /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */ + if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & + (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) + ret = wv_set_frequency(ioaddr, &(wrq->u.freq)); + else + ret = -EOPNOTSUPP; + break; + + case SIOCGIWFREQ: + /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). + * Does it work for everybody, especially old cards? */ + if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & + (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { + unsigned short freq; + + /* Ask the EEPROM to read the frequency from the first area. */ + fee_read(ioaddr, 0x00, &freq, 1); + wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000; + wrq->u.freq.e = 1; + } else { + psa_read(ioaddr, lp->hacr, + (char *) &psa.psa_subband - (char *) &psa, + (unsigned char *) &psa.psa_subband, 1); + + if (psa.psa_subband <= 4) { + wrq->u.freq.m = + fixed_bands[psa.psa_subband]; + wrq->u.freq.e = (psa.psa_subband != 0); + } else + ret = -EOPNOTSUPP; + } + break; + + case SIOCSIWSENS: + /* Set the level threshold. */ + /* We should complain loudly if wrq->u.sens.fixed = 0, because we + * can't set auto mode... */ + psa.psa_thr_pre_set = wrq->u.sens.value & 0x3F; + psa_write(ioaddr, lp->hacr, + (char *) &psa.psa_thr_pre_set - (char *) &psa, + (unsigned char *) &psa.psa_thr_pre_set, 1); + /* update the Wavelan checksum */ + update_psa_checksum(dev, ioaddr, lp->hacr); + mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set), + psa.psa_thr_pre_set); + break; + + case SIOCGIWSENS: + /* Read the level threshold. */ + psa_read(ioaddr, lp->hacr, + (char *) &psa.psa_thr_pre_set - (char *) &psa, + (unsigned char *) &psa.psa_thr_pre_set, 1); + wrq->u.sens.value = psa.psa_thr_pre_set & 0x3F; + wrq->u.sens.fixed = 1; + break; + + case SIOCSIWENCODE: + /* Set encryption key */ + if (!mmc_encr(ioaddr)) { + ret = -EOPNOTSUPP; + break; + } + + /* Basic checking... */ + if (wrq->u.encoding.pointer != (caddr_t) 0) { + /* Check the size of the key */ + if (wrq->u.encoding.length != 8) { + ret = -EINVAL; + break; + } + + /* Copy the key in the driver */ + if (copy_from_user + (psa.psa_encryption_key, + wrq->u.encoding.pointer, + wrq->u.encoding.length)) { + ret = -EFAULT; + break; + } + + psa.psa_encryption_select = 1; + psa_write(ioaddr, lp->hacr, + (char *) &psa.psa_encryption_select - + (char *) &psa, + (unsigned char *) &psa. + psa_encryption_select, 8 + 1); + + mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), + MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE); + mmc_write(ioaddr, mmwoff(0, mmw_encr_key), + (unsigned char *) &psa. + psa_encryption_key, 8); + } + + if (wrq->u.encoding.flags & IW_ENCODE_DISABLED) { /* disable encryption */ + psa.psa_encryption_select = 0; + psa_write(ioaddr, lp->hacr, + (char *) &psa.psa_encryption_select - + (char *) &psa, + (unsigned char *) &psa. + psa_encryption_select, 1); + + mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0); + } + /* update the Wavelan checksum */ + update_psa_checksum(dev, ioaddr, lp->hacr); + break; + + case SIOCGIWENCODE: + /* Read the encryption key */ + if (!mmc_encr(ioaddr)) { + ret = -EOPNOTSUPP; + break; + } + + /* only super-user can see encryption key */ + if (!suser()) { + ret = -EPERM; + break; + } + + /* Basic checking... */ + if (wrq->u.encoding.pointer != (caddr_t) 0) { + /* Verify the user buffer */ + ret = + verify_area(VERIFY_WRITE, + wrq->u.encoding.pointer, 8); + if (ret) + break; + + psa_read(ioaddr, lp->hacr, + (char *) &psa.psa_encryption_select - + (char *) &psa, + (unsigned char *) &psa. + psa_encryption_select, 1 + 8); + + /* encryption is enabled ? */ + if (psa.psa_encryption_select) + wrq->u.encoding.flags = IW_ENCODE_ENABLED; + else + wrq->u.encoding.flags = IW_ENCODE_DISABLED; + wrq->u.encoding.flags |= mmc_encr(ioaddr); + + /* Copy the key to the user buffer */ + wrq->u.encoding.length = 8; + if (copy_to_user + (wrq->u.encoding.pointer, + psa.psa_encryption_key, 8)) ret = -EFAULT; + } + break; + + case SIOCGIWRANGE: + /* basic checking */ + if (wrq->u.data.pointer != (caddr_t) 0) { + struct iw_range range; + + /* Set the length (useless: it's constant). */ + wrq->u.data.length = sizeof(struct iw_range); + + /* Set information in the range struct. */ + range.throughput = 1.6 * 1000 * 1000; /* don't argue on this ! */ + range.min_nwid = 0x0000; + range.max_nwid = 0xFFFF; + + /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */ + if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & + (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { + range.num_channels = 10; + range.num_frequency = + wv_frequency_list(ioaddr, range.freq, IW_MAX_FREQUENCIES); - } - else - range.num_channels = range.num_frequency = 0; - - range.sensitivity = 0x3F; - range.max_qual.qual = MMR_SGNL_QUAL; - range.max_qual.level = MMR_SIGNAL_LVL; - range.max_qual.noise = MMR_SILENCE_LVL; - - range.num_bitrates = 1; - range.bitrate[0] = 2000000; /* 2 Mb/s */ - - /* Encryption supported ? */ - if(mmc_encr(ioaddr)) - { - range.encoding_size[0] = 8; /* DES = 64 bits key */ - range.num_encoding_sizes = 1; - range.max_encoding_tokens = 1; /* Only one key possible */ - } - else - { - range.num_encoding_sizes = 0; - range.max_encoding_tokens = 0; - } - - /* Copy structure to the user buffer. */ - if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range))) - ret = -EFAULT; - } - break; - - case SIOCGIWPRIV: - /* Basic checking */ - if(wrq->u.data.pointer != (caddr_t) 0) - { - struct iw_priv_args priv[] = - { /* cmd, set_args, get_args, name */ - { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" }, - { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" }, - - { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16, 0, "sethisto" }, - { SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16, "gethisto" }, - }; - - /* Set the number of available ioctls. */ - wrq->u.data.length = 4; - - /* Copy structure to the user buffer. */ - if (copy_to_user(wrq->u.data.pointer, (u_char *) priv, sizeof(priv))) - ret = -EFAULT; - } - break; + } else + range.num_channels = range.num_frequency = + 0; + + range.sensitivity = 0x3F; + range.max_qual.qual = MMR_SGNL_QUAL; + range.max_qual.level = MMR_SIGNAL_LVL; + range.max_qual.noise = MMR_SILENCE_LVL; + + range.num_bitrates = 1; + range.bitrate[0] = 2000000; /* 2 Mb/s */ + + /* Encryption supported ? */ + if (mmc_encr(ioaddr)) { + range.encoding_size[0] = 8; /* DES = 64 bits key */ + range.num_encoding_sizes = 1; + range.max_encoding_tokens = 1; /* Only one key possible */ + } else { + range.num_encoding_sizes = 0; + range.max_encoding_tokens = 0; + } + + /* Copy structure to the user buffer. */ + if (copy_to_user + (wrq->u.data.pointer, &range, + sizeof(struct iw_range))) ret = -EFAULT; + } + break; + + case SIOCGIWPRIV: + /* Basic checking */ + if (wrq->u.data.pointer != (caddr_t) 0) { + struct iw_priv_args priv[] = { /* cmd, set_args, get_args, name */ + + {SIOCSIPQTHR, + IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | + 1, 0, "setqualthr"}, + {SIOCGIPQTHR, 0, + IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | + 1, "getqualthr"}, + + + {SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16, + 0, "sethisto"}, + {SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16, + "gethisto"}, + }; + + /* Set the number of available ioctls. */ + wrq->u.data.length = 4; + + /* Copy structure to the user buffer. */ + if (copy_to_user + (wrq->u.data.pointer, (u8 *) priv, + sizeof(priv))) ret = -EFAULT; + } + break; #ifdef WIRELESS_SPY - case SIOCSIWSPY: - /* Set the spy list */ - - /* Check the number of addresses. */ - if(wrq->u.data.length > IW_MAX_SPY) - { - ret = -E2BIG; - break; - } - lp->spy_number = wrq->u.data.length; - - /* Are there are addresses to copy? */ - if(lp->spy_number > 0) - { - struct sockaddr address[IW_MAX_SPY]; - int i; - - /* Copy addresses to the driver. */ - if (copy_from_user(address, wrq->u.data.pointer, sizeof(struct sockaddr) * lp->spy_number)) { - ret = -EFAULT; - break; - } - - /* Copy addresses to the lp structure. */ - for(i = 0; i < lp->spy_number; i++) - { - memcpy(lp->spy_address[i], address[i].sa_data, - WAVELAN_ADDR_SIZE); - } - - /* Reset structure. */ - memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY); + case SIOCSIWSPY: + /* Set the spy list */ + + /* Check the number of addresses. */ + if (wrq->u.data.length > IW_MAX_SPY) { + ret = -E2BIG; + break; + } + lp->spy_number = wrq->u.data.length; + + /* Are there are addresses to copy? */ + if (lp->spy_number > 0) { + struct sockaddr address[IW_MAX_SPY]; + int i; + + /* Copy addresses to the driver. */ + if (copy_from_user + (address, wrq->u.data.pointer, + sizeof(struct sockaddr) * lp->spy_number)) { + ret = -EFAULT; + break; + } + + /* Copy addresses to the lp structure. */ + for (i = 0; i < lp->spy_number; i++) { + memcpy(lp->spy_address[i], + address[i].sa_data, + WAVELAN_ADDR_SIZE); + } + + /* Reset structure. */ + memset(lp->spy_stat, 0x00, + sizeof(iw_qual) * IW_MAX_SPY); #ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "SetSpy: set of new addresses is: \n"); - for(i = 0; i < wrq->u.data.length; i++) - printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X \n", - lp->spy_address[i][0], - lp->spy_address[i][1], - lp->spy_address[i][2], - lp->spy_address[i][3], - lp->spy_address[i][4], - lp->spy_address[i][5]); -#endif /* DEBUG_IOCTL_INFO */ - } - - break; - - case SIOCGIWSPY: - /* Get the spy list and spy stats. */ - - /* Set the number of addresses */ - wrq->u.data.length = lp->spy_number; - - /* Does the user want to have the addresses back? */ - if((lp->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0)) - { - struct sockaddr address[IW_MAX_SPY]; - int i; - - /* Copy addresses from the lp structure. */ - for(i = 0; i < lp->spy_number; i++) - { - memcpy(address[i].sa_data, lp->spy_address[i], - WAVELAN_ADDR_SIZE); - address[i].sa_family = AF_UNIX; - } - - /* Copy addresses to the user buffer. */ - if (copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * lp->spy_number)) { - ret = -EFAULT; - break; - } - - /* Copy stats to the user buffer (just after). */ - if (copy_to_user(wrq->u.data.pointer + - (sizeof(struct sockaddr) * lp->spy_number), - lp->spy_stat, sizeof(iw_qual) * lp->spy_number)) { - ret = -EFAULT; - break; - } - - /* Reset updated flags. */ - for(i = 0; i < lp->spy_number; i++) - lp->spy_stat[i].updated = 0x0; - } /* if(pointer != NULL) */ - - break; -#endif /* WIRELESS_SPY */ - - /* ------------------ PRIVATE IOCTL ------------------ */ - - case SIOCSIPQTHR: - if(!suser()) - { - ret = -EPERM; - break; - } - psa.psa_quality_thr = *(wrq->u.name) & 0x0F; - psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa, - (unsigned char *)&psa.psa_quality_thr, 1); - /* update the Wavelan checksum */ - update_psa_checksum(dev, ioaddr, lp->hacr); - mmc_out(ioaddr, mmwoff(0, mmw_quality_thr), psa.psa_quality_thr); - break; - - case SIOCGIPQTHR: - psa_read(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa, - (unsigned char *)&psa.psa_quality_thr, 1); - *(wrq->u.name) = psa.psa_quality_thr & 0x0F; - break; + printk(KERN_DEBUG + "SetSpy: set of new addresses is: \n"); + for (i = 0; i < wrq->u.data.length; i++) + printk(KERN_DEBUG + "%02X:%02X:%02X:%02X:%02X:%02X \n", + lp->spy_address[i][0], + lp->spy_address[i][1], + lp->spy_address[i][2], + lp->spy_address[i][3], + lp->spy_address[i][4], + lp->spy_address[i][5]); +#endif /* DEBUG_IOCTL_INFO */ + } + + break; + + case SIOCGIWSPY: + /* Get the spy list and spy stats. */ + + /* Set the number of addresses */ + wrq->u.data.length = lp->spy_number; + + /* Does the user want to have the addresses back? */ + if ((lp->spy_number > 0) + && (wrq->u.data.pointer != (caddr_t) 0)) { + struct sockaddr address[IW_MAX_SPY]; + int i; + + /* Copy addresses from the lp structure. */ + for (i = 0; i < lp->spy_number; i++) { + memcpy(address[i].sa_data, + lp->spy_address[i], + WAVELAN_ADDR_SIZE); + address[i].sa_family = AF_UNIX; + } + + /* Copy addresses to the user buffer. */ + if (copy_to_user + (wrq->u.data.pointer, address, + sizeof(struct sockaddr) * lp->spy_number)) { + ret = -EFAULT; + break; + } + + /* Copy stats to the user buffer (just after). */ + if (copy_to_user(wrq->u.data.pointer + + (sizeof(struct sockaddr) * + lp->spy_number), lp->spy_stat, + sizeof(iw_qual) * lp->spy_number)) { + ret = -EFAULT; + break; + } + + /* Reset updated flags. */ + for (i = 0; i < lp->spy_number; i++) + lp->spy_stat[i].updated = 0x0; + } + /* if(pointer != NULL) */ + break; +#endif /* WIRELESS_SPY */ + + /* ------------------ PRIVATE IOCTL ------------------ */ + + case SIOCSIPQTHR: + if (!suser()) { + ret = -EPERM; + break; + } + psa.psa_quality_thr = *(wrq->u.name) & 0x0F; + psa_write(ioaddr, lp->hacr, + (char *) &psa.psa_quality_thr - (char *) &psa, + (unsigned char *) &psa.psa_quality_thr, 1); + /* update the Wavelan checksum */ + update_psa_checksum(dev, ioaddr, lp->hacr); + mmc_out(ioaddr, mmwoff(0, mmw_quality_thr), + psa.psa_quality_thr); + break; + + case SIOCGIPQTHR: + psa_read(ioaddr, lp->hacr, + (char *) &psa.psa_quality_thr - (char *) &psa, + (unsigned char *) &psa.psa_quality_thr, 1); + *(wrq->u.name) = psa.psa_quality_thr & 0x0F; + break; #ifdef HISTOGRAM - case SIOCSIPHISTO: - /* Verify that the user is root. */ - if(!suser()) - { - ret = -EPERM; - break; - } - - /* Check the number of intervals. */ - if(wrq->u.data.length > 16) - { - ret = -E2BIG; - break; - } - lp->his_number = wrq->u.data.length; + case SIOCSIPHISTO: + /* Verify that the user is root. */ + if (!suser()) { + ret = -EPERM; + break; + } + + /* Check the number of intervals. */ + if (wrq->u.data.length > 16) { + ret = -E2BIG; + break; + } + lp->his_number = wrq->u.data.length; + + /* Are there addresses to copy? */ + if (lp->his_number > 0) { + /* Copy interval ranges to the driver */ + if (copy_from_user + (lp->his_range, wrq->u.data.pointer, + sizeof(char) * lp->his_number)) { + ret = -EFAULT; + break; + } + + /* Reset structure. */ + memset(lp->his_sum, 0x00, sizeof(long) * 16); + } + break; + + case SIOCGIPHISTO: + /* Set the number of intervals. */ + wrq->u.data.length = lp->his_number; + + /* Give back the distribution statistics */ + if ((lp->his_number > 0) + && (wrq->u.data.pointer != (caddr_t) 0)) { + /* Copy data to the user buffer. */ + if (copy_to_user + (wrq->u.data.pointer, lp->his_sum, + sizeof(long) * lp->his_number)) + ret = -EFAULT; + + } /* if(pointer != NULL) */ + break; +#endif /* HISTOGRAM */ + + /* ------------------- OTHER IOCTL ------------------- */ - /* Are there addresses to copy? */ - if(lp->his_number > 0) - { - /* Copy interval ranges to the driver */ - if (copy_from_user(lp->his_range, wrq->u.data.pointer, sizeof(char) * lp->his_number)) { - ret = -EFAULT; - break; - } - - /* Reset structure. */ - memset(lp->his_sum, 0x00, sizeof(long) * 16); + default: + ret = -EOPNOTSUPP; } - break; - - case SIOCGIPHISTO: - /* Set the number of intervals. */ - wrq->u.data.length = lp->his_number; - - /* Give back the distribution statistics */ - if((lp->his_number > 0) && (wrq->u.data.pointer != (caddr_t) 0)) - { - /* Copy data to the user buffer. */ - if (copy_to_user(wrq->u.data.pointer, lp->his_sum, sizeof(long) * lp->his_number)) - ret = -EFAULT; - - } /* if(pointer != NULL) */ - break; -#endif /* HISTOGRAM */ - /* ------------------- OTHER IOCTL ------------------- */ - - default: - ret = -EOPNOTSUPP; - } - - /* Enable interrupts and restore flags. */ - wv_splx(x); + /* Enable interrupts and restore flags. */ + restore_flags(flags); #ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name); + printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name); #endif - return ret; + return ret; } /*------------------------------------------------------------------*/ @@ -2351,56 +2285,64 @@ wavelan_ioctl(struct net_device * dev, /* device on which the ioctl is applied * * Get wireless statistics. * Called by /proc/net/wireless */ -static iw_stats * -wavelan_get_wireless_stats(device * dev) +static iw_stats *wavelan_get_wireless_stats(device * dev) { - u_long ioaddr = dev->base_addr; - net_local * lp = (net_local *) dev->priv; - mmr_t m; - iw_stats * wstats; - unsigned long x; + unsigned long ioaddr = dev->base_addr; + net_local *lp = (net_local *) dev->priv; + mmr_t m; + iw_stats *wstats; + unsigned long flags; #ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", dev->name); + printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", + dev->name); #endif - /* Disable interrupts and save flags. */ - x = wv_splhi(); - - if(lp == (net_local *) NULL) - return (iw_stats *) NULL; - wstats = &lp->wstats; - - /* Get data from the mmc. */ - mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); - - mmc_read(ioaddr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, 1); - mmc_read(ioaddr, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l, 2); - mmc_read(ioaddr, mmroff(0, mmr_thr_pre_set), &m.mmr_thr_pre_set, 4); - - mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0); - - /* Copy data to wireless stuff. */ - wstats->status = m.mmr_dce_status & MMR_DCE_STATUS; - wstats->qual.qual = m.mmr_sgnl_qual & MMR_SGNL_QUAL; - wstats->qual.level = m.mmr_signal_lvl & MMR_SIGNAL_LVL; - wstats->qual.noise = m.mmr_silence_lvl & MMR_SILENCE_LVL; - wstats->qual.updated = (((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 7) | - ((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 6) | - ((m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) >> 5)); - wstats->discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l; - wstats->discard.code = 0L; - wstats->discard.misc = 0L; - - /* Enable interrupts and restore flags. */ - wv_splx(x); + /* Disable interrupts and save flags. */ + save_flags(flags); + cli(); + + if (lp == (net_local *) NULL) + { + restore_flags(flags); + return (iw_stats *) NULL; + } + + wstats = &lp->wstats; + + /* Get data from the mmc. */ + mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); + + mmc_read(ioaddr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, 1); + mmc_read(ioaddr, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l, + 2); + mmc_read(ioaddr, mmroff(0, mmr_thr_pre_set), &m.mmr_thr_pre_set, + 4); + + mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0); + + /* Copy data to wireless stuff. */ + wstats->status = m.mmr_dce_status & MMR_DCE_STATUS; + wstats->qual.qual = m.mmr_sgnl_qual & MMR_SGNL_QUAL; + wstats->qual.level = m.mmr_signal_lvl & MMR_SIGNAL_LVL; + wstats->qual.noise = m.mmr_silence_lvl & MMR_SILENCE_LVL; + wstats->qual.updated = (((m. mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 7) + | ((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 6) + | ((m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) >> 5)); + wstats->discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l; + wstats->discard.code = 0L; + wstats->discard.misc = 0L; + + /* Enable interrupts and restore flags. */ + restore_flags(flags); #ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", dev->name); + printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", + dev->name); #endif - return &lp->wstats; + return &lp->wstats; } -#endif /* WIRELESS_EXT */ +#endif /* WIRELESS_EXT */ /************************* PACKET RECEPTION *************************/ /* @@ -2423,90 +2365,90 @@ wavelan_get_wireless_stats(device * dev) * (called by wv_packet_rcv()) */ static inline void -wv_packet_read(device * dev, - u_short buf_off, - int sksize) +wv_packet_read(device * dev, u16 buf_off, int sksize) { - net_local * lp = (net_local *) dev->priv; - u_long ioaddr = dev->base_addr; - struct sk_buff * skb; + net_local *lp = (net_local *) dev->priv; + unsigned long ioaddr = dev->base_addr; + struct sk_buff *skb; #ifdef DEBUG_RX_TRACE - printk(KERN_DEBUG "%s: ->wv_packet_read(0x%X, %d)\n", - dev->name, buf_off, sksize); + printk(KERN_DEBUG "%s: ->wv_packet_read(0x%X, %d)\n", + dev->name, buf_off, sksize); #endif - /* Allocate buffer for the data */ - if((skb = dev_alloc_skb(sksize)) == (struct sk_buff *) NULL) - { + /* Allocate buffer for the data */ + if ((skb = dev_alloc_skb(sksize)) == (struct sk_buff *) NULL) { #ifdef DEBUG_RX_ERROR - printk(KERN_INFO "%s: wv_packet_read(): could not alloc_skb(%d, GFP_ATOMIC).\n", - dev->name, sksize); + printk(KERN_INFO + "%s: wv_packet_read(): could not alloc_skb(%d, GFP_ATOMIC).\n", + dev->name, sksize); #endif - lp->stats.rx_dropped++; - return; - } + lp->stats.rx_dropped++; + return; + } - skb->dev = dev; + skb->dev = dev; - /* Copy the packet to the buffer. */ - obram_read(ioaddr, buf_off, skb_put(skb, sksize), sksize); - skb->protocol=eth_type_trans(skb, dev); + /* Copy the packet to the buffer. */ + obram_read(ioaddr, buf_off, skb_put(skb, sksize), sksize); + skb->protocol = eth_type_trans(skb, dev); #ifdef DEBUG_RX_INFO - wv_packet_info(skb->mac.raw, sksize, dev->name, "wv_packet_read"); -#endif /* DEBUG_RX_INFO */ + wv_packet_info(skb->mac.raw, sksize, dev->name, "wv_packet_read"); +#endif /* DEBUG_RX_INFO */ - /* Statistics-gathering and associated stuff. - * It seem a bit messy with all the define, but it's really simple... */ + /* Statistics-gathering and associated stuff. + * It seem a bit messy with all the define, but it's really simple... */ #if defined(WIRELESS_SPY) || defined(HISTOGRAM) - if( + if ( #ifdef WIRELESS_SPY - (lp->spy_number > 0) || -#endif /* WIRELESS_SPY */ + (lp->spy_number > 0) || +#endif /* WIRELESS_SPY */ #ifdef HISTOGRAM - (lp->his_number > 0) || -#endif /* HISTOGRAM */ - 0) - { - u_char stats[3]; /* signal level, noise level, signal quality */ - - /* Read signal level, silence level and signal quality bytes. */ - /* Note: in the PCMCIA hardware, these are part of the frame. It seems - * that for the ISA hardware, it's nowhere to be found in the frame, - * so I'm obliged to do this (it has a side effect on /proc/net/wireless). - * Any ideas? - */ - mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); - mmc_read(ioaddr, mmroff(0, mmr_signal_lvl), stats, 3); - mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0); + (lp->his_number > 0) || +#endif /* HISTOGRAM */ + 0) { + u8 stats[3]; /* signal level, noise level, signal quality */ + + /* Read signal level, silence level and signal quality bytes. */ + /* Note: in the PCMCIA hardware, these are part of the frame. It seems + * that for the ISA hardware, it's nowhere to be found in the frame, + * so I'm obliged to do this (it has a side effect on /proc/net/wireless). + * Any ideas? + */ + mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); + mmc_read(ioaddr, mmroff(0, mmr_signal_lvl), stats, 3); + mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0); #ifdef DEBUG_RX_INFO - printk(KERN_DEBUG "%s: wv_packet_read(): Signal level %d/63, Silence level %d/63, signal quality %d/16\n", - dev->name, stats[0] & 0x3F, stats[1] & 0x3F, stats[2] & 0x0F); + printk(KERN_DEBUG + "%s: wv_packet_read(): Signal level %d/63, Silence level %d/63, signal quality %d/16\n", + dev->name, stats[0] & 0x3F, stats[1] & 0x3F, + stats[2] & 0x0F); #endif - /* Spying stuff */ + /* Spying stuff */ #ifdef WIRELESS_SPY - wl_spy_gather(dev, skb->mac.raw + WAVELAN_ADDR_SIZE, stats); -#endif /* WIRELESS_SPY */ + wl_spy_gather(dev, skb->mac.raw + WAVELAN_ADDR_SIZE, + stats); +#endif /* WIRELESS_SPY */ #ifdef HISTOGRAM - wl_his_gather(dev, stats); -#endif /* HISTOGRAM */ - } -#endif /* defined(WIRELESS_SPY) || defined(HISTOGRAM) */ + wl_his_gather(dev, stats); +#endif /* HISTOGRAM */ + } +#endif /* defined(WIRELESS_SPY) || defined(HISTOGRAM) */ - /* - * Hand the packet to the network module. - */ - netif_rx(skb); + /* + * Hand the packet to the network module. + */ + netif_rx(skb); - /* Keep statistics up to date */ - lp->stats.rx_packets++; - lp->stats.rx_bytes += skb->len; + /* Keep statistics up to date */ + lp->stats.rx_packets++; + lp->stats.rx_bytes += skb->len; #ifdef DEBUG_RX_TRACE - printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name); + printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name); #endif } @@ -2516,150 +2458,160 @@ wv_packet_read(device * dev, * from the device RAM. * Called by the interrupt handler. */ -static inline void -wv_receive(device * dev) +static inline void wv_receive(device * dev) { - u_long ioaddr = dev->base_addr; - net_local * lp = (net_local *)dev->priv; - fd_t fd; - rbd_t rbd; - int nreaped = 0; + unsigned long ioaddr = dev->base_addr; + net_local *lp = (net_local *) dev->priv; + fd_t fd; + rbd_t rbd; + int nreaped = 0; #ifdef DEBUG_RX_TRACE - printk(KERN_DEBUG "%s: ->wv_receive()\n", dev->name); + printk(KERN_DEBUG "%s: ->wv_receive()\n", dev->name); #endif - /* Loop on each received packet. */ - for(;;) - { - obram_read(ioaddr, lp->rx_head, (unsigned char *) &fd, sizeof(fd)); - - /* Note about the status : - * It start up to be 0 (the value we set). Then, when the RU - * grab the buffer to prepare for reception, it sets the - * FD_STATUS_B flag. When the RU has finished receiving the - * frame, it clears FD_STATUS_B, set FD_STATUS_C to indicate - * completion and set the other flags to indicate the eventual - * errors. FD_STATUS_OK indicates that the reception was OK. - */ - - /* If the current frame is not complete, we have reached the end. */ - if((fd.fd_status & FD_STATUS_C) != FD_STATUS_C) - break; /* This is how we exit the loop. */ - - nreaped++; - - /* Check whether frame was correctly received. */ - if((fd.fd_status & FD_STATUS_OK) == FD_STATUS_OK) - { - /* Does the frame contain a pointer to the data? Let's check. */ - if(fd.fd_rbd_offset != I82586NULL) - { - /* Read the receive buffer descriptor */ - obram_read(ioaddr, fd.fd_rbd_offset, - (unsigned char *) &rbd, sizeof(rbd)); + /* Loop on each received packet. */ + for (;;) { + obram_read(ioaddr, lp->rx_head, (unsigned char *) &fd, + sizeof(fd)); + + /* Note about the status : + * It start up to be 0 (the value we set). Then, when the RU + * grab the buffer to prepare for reception, it sets the + * FD_STATUS_B flag. When the RU has finished receiving the + * frame, it clears FD_STATUS_B, set FD_STATUS_C to indicate + * completion and set the other flags to indicate the eventual + * errors. FD_STATUS_OK indicates that the reception was OK. + */ + + /* If the current frame is not complete, we have reached the end. */ + if ((fd.fd_status & FD_STATUS_C) != FD_STATUS_C) + break; /* This is how we exit the loop. */ + + nreaped++; + + /* Check whether frame was correctly received. */ + if ((fd.fd_status & FD_STATUS_OK) == FD_STATUS_OK) { + /* Does the frame contain a pointer to the data? Let's check. */ + if (fd.fd_rbd_offset != I82586NULL) { + /* Read the receive buffer descriptor */ + obram_read(ioaddr, fd.fd_rbd_offset, + (unsigned char *) &rbd, + sizeof(rbd)); #ifdef DEBUG_RX_ERROR - if((rbd.rbd_status & RBD_STATUS_EOF) != RBD_STATUS_EOF) - printk(KERN_INFO "%s: wv_receive(): missing EOF flag.\n", - dev->name); - - if((rbd.rbd_status & RBD_STATUS_F) != RBD_STATUS_F) - printk(KERN_INFO "%s: wv_receive(): missing F flag.\n", - dev->name); -#endif /* DEBUG_RX_ERROR */ - - /* Read the packet and transmit to Linux */ - wv_packet_read(dev, rbd.rbd_bufl, - rbd.rbd_status & RBD_STATUS_ACNT); - } + if ((rbd.rbd_status & RBD_STATUS_EOF) != + RBD_STATUS_EOF) printk(KERN_INFO + "%s: wv_receive(): missing EOF flag.\n", + dev->name); + + if ((rbd.rbd_status & RBD_STATUS_F) != + RBD_STATUS_F) printk(KERN_INFO + "%s: wv_receive(): missing F flag.\n", + dev->name); +#endif /* DEBUG_RX_ERROR */ + + /* Read the packet and transmit to Linux */ + wv_packet_read(dev, rbd.rbd_bufl, + rbd. + rbd_status & + RBD_STATUS_ACNT); + } #ifdef DEBUG_RX_ERROR - else /* if frame has no data */ - printk(KERN_INFO "%s: wv_receive(): frame has no data.\n", - dev->name); + else /* if frame has no data */ + printk(KERN_INFO + "%s: wv_receive(): frame has no data.\n", + dev->name); #endif - } - else /* If reception was no successful */ - { - lp->stats.rx_errors++; + } else { /* If reception was no successful */ + + lp->stats.rx_errors++; #ifdef DEBUG_RX_INFO - printk(KERN_DEBUG "%s: wv_receive(): frame not received successfully (%X).\n", - dev->name, fd.fd_status); + printk(KERN_DEBUG + "%s: wv_receive(): frame not received successfully (%X).\n", + dev->name, fd.fd_status); #endif #ifdef DEBUG_RX_ERROR - if((fd.fd_status & FD_STATUS_S6) != 0) - printk(KERN_INFO "%s: wv_receive(): no EOF flag.\n", dev->name); + if ((fd.fd_status & FD_STATUS_S6) != 0) + printk(KERN_INFO + "%s: wv_receive(): no EOF flag.\n", + dev->name); #endif - if((fd.fd_status & FD_STATUS_S7) != 0) - { - lp->stats.rx_length_errors++; + if ((fd.fd_status & FD_STATUS_S7) != 0) { + lp->stats.rx_length_errors++; #ifdef DEBUG_RX_FAIL - printk(KERN_DEBUG "%s: wv_receive(): frame too short.\n", - dev->name); + printk(KERN_DEBUG + "%s: wv_receive(): frame too short.\n", + dev->name); #endif - } + } - if((fd.fd_status & FD_STATUS_S8) != 0) - { - lp->stats.rx_over_errors++; + if ((fd.fd_status & FD_STATUS_S8) != 0) { + lp->stats.rx_over_errors++; #ifdef DEBUG_RX_FAIL - printk(KERN_DEBUG "%s: wv_receive(): rx DMA overrun.\n", - dev->name); + printk(KERN_DEBUG + "%s: wv_receive(): rx DMA overrun.\n", + dev->name); #endif - } + } - if((fd.fd_status & FD_STATUS_S9) != 0) - { - lp->stats.rx_fifo_errors++; + if ((fd.fd_status & FD_STATUS_S9) != 0) { + lp->stats.rx_fifo_errors++; #ifdef DEBUG_RX_FAIL - printk(KERN_DEBUG "%s: wv_receive(): ran out of resources.\n", - dev->name); + printk(KERN_DEBUG + "%s: wv_receive(): ran out of resources.\n", + dev->name); #endif - } + } - if((fd.fd_status & FD_STATUS_S10) != 0) - { - lp->stats.rx_frame_errors++; + if ((fd.fd_status & FD_STATUS_S10) != 0) { + lp->stats.rx_frame_errors++; #ifdef DEBUG_RX_FAIL - printk(KERN_DEBUG "%s: wv_receive(): alignment error.\n", - dev->name); + printk(KERN_DEBUG + "%s: wv_receive(): alignment error.\n", + dev->name); #endif - } + } - if((fd.fd_status & FD_STATUS_S11) != 0) - { - lp->stats.rx_crc_errors++; + if ((fd.fd_status & FD_STATUS_S11) != 0) { + lp->stats.rx_crc_errors++; #ifdef DEBUG_RX_FAIL - printk(KERN_DEBUG "%s: wv_receive(): CRC error.\n", dev->name); + printk(KERN_DEBUG + "%s: wv_receive(): CRC error.\n", + dev->name); #endif - } - } + } + } - fd.fd_status = 0; - obram_write(ioaddr, fdoff(lp->rx_head, fd_status), - (unsigned char *) &fd.fd_status, sizeof(fd.fd_status)); + fd.fd_status = 0; + obram_write(ioaddr, fdoff(lp->rx_head, fd_status), + (unsigned char *) &fd.fd_status, + sizeof(fd.fd_status)); - fd.fd_command = FD_COMMAND_EL; - obram_write(ioaddr, fdoff(lp->rx_head, fd_command), - (unsigned char *) &fd.fd_command, sizeof(fd.fd_command)); + fd.fd_command = FD_COMMAND_EL; + obram_write(ioaddr, fdoff(lp->rx_head, fd_command), + (unsigned char *) &fd.fd_command, + sizeof(fd.fd_command)); - fd.fd_command = 0; - obram_write(ioaddr, fdoff(lp->rx_last, fd_command), - (unsigned char *) &fd.fd_command, sizeof(fd.fd_command)); + fd.fd_command = 0; + obram_write(ioaddr, fdoff(lp->rx_last, fd_command), + (unsigned char *) &fd.fd_command, + sizeof(fd.fd_command)); - lp->rx_last = lp->rx_head; - lp->rx_head = fd.fd_link_offset; - } /* for(;;) -> loop on all frames */ + lp->rx_last = lp->rx_head; + lp->rx_head = fd.fd_link_offset; + } /* for(;;) -> loop on all frames */ #ifdef DEBUG_RX_INFO - if(nreaped > 1) - printk(KERN_DEBUG "%s: wv_receive(): reaped %d\n", dev->name, nreaped); + if (nreaped > 1) + printk(KERN_DEBUG "%s: wv_receive(): reaped %d\n", + dev->name, nreaped); #endif #ifdef DEBUG_RX_TRACE - printk(KERN_DEBUG "%s: <-wv_receive()\n", dev->name); + printk(KERN_DEBUG "%s: <-wv_receive()\n", dev->name); #endif } @@ -2689,130 +2641,124 @@ wv_receive(device * dev) * * (called in wavelan_packet_xmit()) */ -static inline void -wv_packet_write(device * dev, - void * buf, - short length) +static inline void wv_packet_write(device * dev, void *buf, short length) { - net_local * lp = (net_local *) dev->priv; - u_long ioaddr = dev->base_addr; - unsigned short txblock; - unsigned short txpred; - unsigned short tx_addr; - unsigned short nop_addr; - unsigned short tbd_addr; - unsigned short buf_addr; - ac_tx_t tx; - ac_nop_t nop; - tbd_t tbd; - int clen = length; - unsigned long x; + net_local *lp = (net_local *) dev->priv; + unsigned long ioaddr = dev->base_addr; + unsigned short txblock; + unsigned short txpred; + unsigned short tx_addr; + unsigned short nop_addr; + unsigned short tbd_addr; + unsigned short buf_addr; + ac_tx_t tx; + ac_nop_t nop; + tbd_t tbd; + int clen = length; + unsigned long flags; #ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, length); + printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, + length); #endif - /* Do we need some padding? */ - if(clen < ETH_ZLEN) - clen = ETH_ZLEN; + /* Do we need some padding? */ + if (clen < ETH_ZLEN) + clen = ETH_ZLEN; + + save_flags(flags); + cli(); + + /* Calculate addresses of next block and previous block. */ + txblock = lp->tx_first_free; + txpred = txblock - TXBLOCKZ; + if (txpred < OFFSET_CU) + txpred += NTXBLOCKS * TXBLOCKZ; + lp->tx_first_free += TXBLOCKZ; + if (lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) + lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ; + + lp->tx_n_in_use++; + + /* Calculate addresses of the different parts of the block. */ + tx_addr = txblock; + nop_addr = tx_addr + sizeof(tx); + tbd_addr = nop_addr + sizeof(nop); + buf_addr = tbd_addr + sizeof(tbd); - x = wv_splhi(); + /* + * Transmit command + */ + tx.tx_h.ac_status = 0; + obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status), + (unsigned char *) &tx.tx_h.ac_status, + sizeof(tx.tx_h.ac_status)); - /* Calculate addresses of next block and previous block. */ - txblock = lp->tx_first_free; - txpred = txblock - TXBLOCKZ; - if(txpred < OFFSET_CU) - txpred += NTXBLOCKS * TXBLOCKZ; - lp->tx_first_free += TXBLOCKZ; - if(lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) - lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ; + /* + * NOP command + */ + nop.nop_h.ac_status = 0; + obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), + (unsigned char *) &nop.nop_h.ac_status, + sizeof(nop.nop_h.ac_status)); + nop.nop_h.ac_link = nop_addr; + obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), + (unsigned char *) &nop.nop_h.ac_link, + sizeof(nop.nop_h.ac_link)); -/* -if (lp->tx_n_in_use > 0) - printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]); -*/ + /* + * Transmit buffer descriptor + */ + tbd.tbd_status = TBD_STATUS_EOF | (TBD_STATUS_ACNT & clen); + tbd.tbd_next_bd_offset = I82586NULL; + tbd.tbd_bufl = buf_addr; + tbd.tbd_bufh = 0; + obram_write(ioaddr, tbd_addr, (unsigned char *) &tbd, sizeof(tbd)); + + /* + * Data + */ + obram_write(ioaddr, buf_addr, buf, length); + + /* + * Overwrite the predecessor NOP link + * so that it points to this txblock. + */ + nop_addr = txpred + sizeof(tx); + nop.nop_h.ac_status = 0; + obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), + (unsigned char *) &nop.nop_h.ac_status, + sizeof(nop.nop_h.ac_status)); + nop.nop_h.ac_link = txblock; + obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), + (unsigned char *) &nop.nop_h.ac_link, + sizeof(nop.nop_h.ac_link)); + + /* Keep stats up to date. */ + lp->stats.tx_bytes += length; + + /* If watchdog not already active, activate it... */ + if (lp->watchdog.prev == (timer_list *) NULL) { + /* Set timer to expire in WATCHDOG_JIFFIES. */ + lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES; + add_timer(&lp->watchdog); + } - lp->tx_n_in_use++; - - /* Calculate addresses of the different parts of the block. */ - tx_addr = txblock; - nop_addr = tx_addr + sizeof(tx); - tbd_addr = nop_addr + sizeof(nop); - buf_addr = tbd_addr + sizeof(tbd); - - /* - * Transmit command - */ - tx.tx_h.ac_status = 0; - obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status), - (unsigned char *) &tx.tx_h.ac_status, - sizeof(tx.tx_h.ac_status)); - - /* - * NOP command - */ - nop.nop_h.ac_status = 0; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), - (unsigned char *) &nop.nop_h.ac_status, - sizeof(nop.nop_h.ac_status)); - nop.nop_h.ac_link = nop_addr; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), - (unsigned char *) &nop.nop_h.ac_link, - sizeof(nop.nop_h.ac_link)); - - /* - * Transmit buffer descriptor - */ - tbd.tbd_status = TBD_STATUS_EOF | (TBD_STATUS_ACNT & clen); - tbd.tbd_next_bd_offset = I82586NULL; - tbd.tbd_bufl = buf_addr; - tbd.tbd_bufh = 0; - obram_write(ioaddr, tbd_addr, (unsigned char *)&tbd, sizeof(tbd)); - - /* - * Data - */ - obram_write(ioaddr, buf_addr, buf, length); - - /* - * Overwrite the predecessor NOP link - * so that it points to this txblock. - */ - nop_addr = txpred + sizeof(tx); - nop.nop_h.ac_status = 0; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), - (unsigned char *)&nop.nop_h.ac_status, - sizeof(nop.nop_h.ac_status)); - nop.nop_h.ac_link = txblock; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), - (unsigned char *) &nop.nop_h.ac_link, - sizeof(nop.nop_h.ac_link)); - - /* Keep stats up to date. */ - lp->stats.tx_bytes += length; - - /* If watchdog not already active, activate it... */ - if(lp->watchdog.prev == (timer_list *) NULL) - { - /* Set timer to expire in WATCHDOG_JIFFIES. */ - lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES; - add_timer(&lp->watchdog); - } - - if(lp->tx_first_in_use == I82586NULL) - lp->tx_first_in_use = txblock; - - if(lp->tx_n_in_use < NTXBLOCKS - 1) - dev->tbusy = 0; - - wv_splx(x); + if (lp->tx_first_in_use == I82586NULL) + lp->tx_first_in_use = txblock; + if (lp->tx_n_in_use < NTXBLOCKS - 1) + netif_wake_queue(dev); + + restore_flags(flags); + #ifdef DEBUG_TX_INFO - wv_packet_info((u_char *) buf, length, dev->name, "wv_packet_write"); -#endif /* DEBUG_TX_INFO */ + wv_packet_info((u8 *) buf, length, dev->name, + "wv_packet_write"); +#endif /* DEBUG_TX_INFO */ #ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name); + printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name); #endif } @@ -2823,59 +2769,41 @@ if (lp->tx_n_in_use > 0) * the packet. We also prevent reentrance. Then we call the function * to send the packet. */ -static int -wavelan_packet_xmit(struct sk_buff * skb, - device * dev) +static int wavelan_packet_xmit(struct sk_buff *skb, device * dev) { - net_local * lp = (net_local *)dev->priv; + net_local *lp = (net_local *) dev->priv; #ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name, - (unsigned) skb); + printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name, + (unsigned) skb); #endif - /* This flag indicate that the hardware can't perform a transmission. - * Theoretically, NET3 checks it before sending a packet to the driver, - * but in fact it never does that and pools continuously. - * As the watchdog will abort overly long transmissions, we are quite safe. - */ - if(dev->tbusy) - return 1; - - /* - * Block a timer-based transmit from overlapping. - * In other words, prevent reentering this routine. - */ - if(test_and_set_bit(0, (void *)&dev->tbusy) != 0) -#ifdef DEBUG_TX_ERROR - printk(KERN_INFO "%s: Transmitter access conflict.\n", dev->name); -#endif - else - { - /* If somebody has asked to reconfigure the controller, - * we can do it now. - */ - if(lp->reconfig_82586) - { - wv_82586_config(dev); - if(dev->tbusy) - return 1; - } + /* + * Block a timer-based transmit from overlapping. + * In other words, prevent reentering this routine. + */ + netif_stop_queue(dev); + + /* If somebody has asked to reconfigure the controller, + * we can do it now. + */ + if (lp->reconfig_82586) { + wv_82586_config(dev); + } #ifdef DEBUG_TX_ERROR - if(skb->next) - printk(KERN_INFO "skb has next\n"); + if (skb->next) + printk(KERN_INFO "skb has next\n"); #endif - wv_packet_write(dev, skb->data, skb->len); - } + wv_packet_write(dev, skb->data, skb->len); - dev_kfree_skb(skb); + dev_kfree_skb(skb); #ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name); + printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name); #endif - return 0; + return 0; } /*********************** HARDWARE CONFIGURATION ***********************/ @@ -2888,166 +2816,170 @@ wavelan_packet_xmit(struct sk_buff * skb, * Routine to initialize the Modem Management Controller. * (called by wv_hw_reset()) */ -static inline int -wv_mmc_init(device * dev) +static inline int wv_mmc_init(device * dev) { - u_long ioaddr = dev->base_addr; - net_local * lp = (net_local *)dev->priv; - psa_t psa; - mmw_t m; - int configured; + unsigned long ioaddr = dev->base_addr; + net_local *lp = (net_local *) dev->priv; + psa_t psa; + mmw_t m; + int configured; #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_mmc_init()\n", dev->name); + printk(KERN_DEBUG "%s: ->wv_mmc_init()\n", dev->name); #endif - /* Read the parameter storage area. */ - psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa)); + /* Read the parameter storage area. */ + psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa)); #ifdef USE_PSA_CONFIG - configured = psa.psa_conf_status & 1; + configured = psa.psa_conf_status & 1; #else - configured = 0; + configured = 0; #endif - /* Is the PSA is not configured */ - if(!configured) - { - /* User will be able to configure NWID later (with iwconfig). */ - psa.psa_nwid[0] = 0; - psa.psa_nwid[1] = 0; - - /* no NWID checking since NWID is not set */ - psa.psa_nwid_select = 0; - - /* Disable encryption */ - psa.psa_encryption_select = 0; - - /* Set to standard values: - * 0x04 for AT, - * 0x01 for MCA, - * 0x04 for PCMCIA and 2.00 card (AT&T 407-024689/E document) - */ - if (psa.psa_comp_number & 1) - psa.psa_thr_pre_set = 0x01; - else - psa.psa_thr_pre_set = 0x04; - psa.psa_quality_thr = 0x03; - - /* It is configured */ - psa.psa_conf_status |= 1; + /* Is the PSA is not configured */ + if (!configured) { + /* User will be able to configure NWID later (with iwconfig). */ + psa.psa_nwid[0] = 0; + psa.psa_nwid[1] = 0; + + /* no NWID checking since NWID is not set */ + psa.psa_nwid_select = 0; + + /* Disable encryption */ + psa.psa_encryption_select = 0; + + /* Set to standard values: + * 0x04 for AT, + * 0x01 for MCA, + * 0x04 for PCMCIA and 2.00 card (AT&T 407-024689/E document) + */ + if (psa.psa_comp_number & 1) + psa.psa_thr_pre_set = 0x01; + else + psa.psa_thr_pre_set = 0x04; + psa.psa_quality_thr = 0x03; + + /* It is configured */ + psa.psa_conf_status |= 1; #ifdef USE_PSA_CONFIG - /* Write the psa. */ - psa_write(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa, - (unsigned char *)psa.psa_nwid, 4); - psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa, - (unsigned char *)&psa.psa_thr_pre_set, 1); - psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa, - (unsigned char *)&psa.psa_quality_thr, 1); - psa_write(ioaddr, lp->hacr, (char *)&psa.psa_conf_status - (char *)&psa, - (unsigned char *)&psa.psa_conf_status, 1); - /* update the Wavelan checksum */ - update_psa_checksum(dev, ioaddr, lp->hacr); + /* Write the psa. */ + psa_write(ioaddr, lp->hacr, + (char *) psa.psa_nwid - (char *) &psa, + (unsigned char *) psa.psa_nwid, 4); + psa_write(ioaddr, lp->hacr, + (char *) &psa.psa_thr_pre_set - (char *) &psa, + (unsigned char *) &psa.psa_thr_pre_set, 1); + psa_write(ioaddr, lp->hacr, + (char *) &psa.psa_quality_thr - (char *) &psa, + (unsigned char *) &psa.psa_quality_thr, 1); + psa_write(ioaddr, lp->hacr, + (char *) &psa.psa_conf_status - (char *) &psa, + (unsigned char *) &psa.psa_conf_status, 1); + /* update the Wavelan checksum */ + update_psa_checksum(dev, ioaddr, lp->hacr); #endif - } - - /* Zero the mmc structure. */ - memset(&m, 0x00, sizeof(m)); - - /* Copy PSA info to the mmc. */ - m.mmw_netw_id_l = psa.psa_nwid[1]; - m.mmw_netw_id_h = psa.psa_nwid[0]; - - if(psa.psa_nwid_select & 1) - m.mmw_loopt_sel = 0x00; - else - m.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID; - - memcpy(&m.mmw_encr_key, &psa.psa_encryption_key, - sizeof(m.mmw_encr_key)); - - if(psa.psa_encryption_select) - m.mmw_encr_enable = MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE; - else - m.mmw_encr_enable = 0; - - m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F; - m.mmw_quality_thr = psa.psa_quality_thr & 0x0F; - - /* - * Set default modem control parameters. - * See NCR document 407-0024326 Rev. A. - */ - m.mmw_jabber_enable = 0x01; - m.mmw_freeze = 0; - m.mmw_anten_sel = MMW_ANTEN_SEL_ALG_EN; - m.mmw_ifs = 0x20; - m.mmw_mod_delay = 0x04; - m.mmw_jam_time = 0x38; - - m.mmw_des_io_invert = 0; - m.mmw_decay_prm = 0; - m.mmw_decay_updat_prm = 0; - - /* Write all info to MMC. */ - mmc_write(ioaddr, 0, (u_char *)&m, sizeof(m)); - - /* The following code starts the modem of the 2.00 frequency - * selectable cards at power on. It's not strictly needed for the - * following boots. - * The original patch was by Joe Finney for the PCMCIA driver, but - * I've cleaned it up a bit and added documentation. - * Thanks to Loeke Brederveld from Lucent for the info. - */ - - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) - * Does it work for everybody, especially old cards? */ - /* Note: WFREQSEL verifies that it is able to read a sensible - * frequency from EEPROM (address 0x00) and that MMR_FEE_STATUS_ID - * is 0xA (Xilinx version) or 0xB (Ariadne version). - * My test is more crude but does work. */ - if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) - { - /* We must download the frequency parameters to the - * synthesizers (from the EEPROM - area 1) - * Note: as the EEPROM is automatically decremented, we set the end - * if the area... */ - m.mmw_fee_addr = 0x0F; - m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD; - mmc_write(ioaddr, (char *)&m.mmw_fee_ctrl - (char *)&m, - (unsigned char *)&m.mmw_fee_ctrl, 2); - - /* Wait until the download is finished. */ - fee_wait(ioaddr, 100, 100); + } + + /* Zero the mmc structure. */ + memset(&m, 0x00, sizeof(m)); + + /* Copy PSA info to the mmc. */ + m.mmw_netw_id_l = psa.psa_nwid[1]; + m.mmw_netw_id_h = psa.psa_nwid[0]; + + if (psa.psa_nwid_select & 1) + m.mmw_loopt_sel = 0x00; + else + m.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID; + + memcpy(&m.mmw_encr_key, &psa.psa_encryption_key, + sizeof(m.mmw_encr_key)); + + if (psa.psa_encryption_select) + m.mmw_encr_enable = + MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE; + else + m.mmw_encr_enable = 0; + + m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F; + m.mmw_quality_thr = psa.psa_quality_thr & 0x0F; + + /* + * Set default modem control parameters. + * See NCR document 407-0024326 Rev. A. + */ + m.mmw_jabber_enable = 0x01; + m.mmw_freeze = 0; + m.mmw_anten_sel = MMW_ANTEN_SEL_ALG_EN; + m.mmw_ifs = 0x20; + m.mmw_mod_delay = 0x04; + m.mmw_jam_time = 0x38; + + m.mmw_des_io_invert = 0; + m.mmw_decay_prm = 0; + m.mmw_decay_updat_prm = 0; + + /* Write all info to MMC. */ + mmc_write(ioaddr, 0, (u8 *) & m, sizeof(m)); + + /* The following code starts the modem of the 2.00 frequency + * selectable cards at power on. It's not strictly needed for the + * following boots. + * The original patch was by Joe Finney for the PCMCIA driver, but + * I've cleaned it up a bit and added documentation. + * Thanks to Loeke Brederveld from Lucent for the info. + */ + + /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) + * Does it work for everybody, especially old cards? */ + /* Note: WFREQSEL verifies that it is able to read a sensible + * frequency from EEPROM (address 0x00) and that MMR_FEE_STATUS_ID + * is 0xA (Xilinx version) or 0xB (Ariadne version). + * My test is more crude but does work. */ + if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & + (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { + /* We must download the frequency parameters to the + * synthesizers (from the EEPROM - area 1) + * Note: as the EEPROM is automatically decremented, we set the end + * if the area... */ + m.mmw_fee_addr = 0x0F; + m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD; + mmc_write(ioaddr, (char *) &m.mmw_fee_ctrl - (char *) &m, + (unsigned char *) &m.mmw_fee_ctrl, 2); + + /* Wait until the download is finished. */ + fee_wait(ioaddr, 100, 100); #ifdef DEBUG_CONFIG_INFO - /* The frequency was in the last word downloaded. */ - mmc_read(ioaddr, (char *)&m.mmw_fee_data_l - (char *)&m, - (unsigned char *)&m.mmw_fee_data_l, 2); - - /* Print some info for the user. */ - printk(KERN_DEBUG "%s: WaveLAN 2.00 recognised (frequency select). Current frequency = %ld\n", - dev->name, - ((m.mmw_fee_data_h << 4) | - (m.mmw_fee_data_l >> 4)) * 5 / 2 + 24000L); + /* The frequency was in the last word downloaded. */ + mmc_read(ioaddr, (char *) &m.mmw_fee_data_l - (char *) &m, + (unsigned char *) &m.mmw_fee_data_l, 2); + + /* Print some info for the user. */ + printk(KERN_DEBUG + "%s: WaveLAN 2.00 recognised (frequency select). Current frequency = %ld\n", + dev->name, + ((m. + mmw_fee_data_h << 4) | (m.mmw_fee_data_l >> 4)) * + 5 / 2 + 24000L); #endif - /* We must now download the power adjust value (gain) to - * the synthesizers (from the EEPROM - area 7 - DAC). */ - m.mmw_fee_addr = 0x61; - m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD; - mmc_write(ioaddr, (char *)&m.mmw_fee_ctrl - (char *)&m, - (unsigned char *)&m.mmw_fee_ctrl, 2); - - /* Wait until the download is finished. */ - } /* if 2.00 card */ + /* We must now download the power adjust value (gain) to + * the synthesizers (from the EEPROM - area 7 - DAC). */ + m.mmw_fee_addr = 0x61; + m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD; + mmc_write(ioaddr, (char *) &m.mmw_fee_ctrl - (char *) &m, + (unsigned char *) &m.mmw_fee_ctrl, 2); + /* Wait until the download is finished. */ + } + /* if 2.00 card */ #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_mmc_init()\n", dev->name); + printk(KERN_DEBUG "%s: <-wv_mmc_init()\n", dev->name); #endif - return 0; + return 0; } /*------------------------------------------------------------------*/ @@ -3056,81 +2988,79 @@ wv_mmc_init(device * dev) * Start the receive unit. * (called by wv_hw_reset()) */ -static inline int -wv_ru_start(device * dev) +static inline int wv_ru_start(device * dev) { - net_local * lp = (net_local *) dev->priv; - u_long ioaddr = dev->base_addr; - u_short scb_cs; - fd_t fd; - rbd_t rbd; - u_short rx; - u_short rx_next; - int i; + net_local *lp = (net_local *) dev->priv; + unsigned long ioaddr = dev->base_addr; + u16 scb_cs; + fd_t fd; + rbd_t rbd; + u16 rx; + u16 rx_next; + int i; #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_ru_start()\n", dev->name); + printk(KERN_DEBUG "%s: ->wv_ru_start()\n", dev->name); #endif - obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *)&scb_cs, sizeof(scb_cs)); - if((scb_cs & SCB_ST_RUS) == SCB_ST_RUS_RDY) - return 0; + obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), + (unsigned char *) &scb_cs, sizeof(scb_cs)); + if ((scb_cs & SCB_ST_RUS) == SCB_ST_RUS_RDY) + return 0; - lp->rx_head = OFFSET_RU; + lp->rx_head = OFFSET_RU; - for(i = 0, rx = lp->rx_head; i < NRXBLOCKS; i++, rx = rx_next) - { - rx_next = (i == NRXBLOCKS - 1) ? lp->rx_head : rx + RXBLOCKZ; + for (i = 0, rx = lp->rx_head; i < NRXBLOCKS; i++, rx = rx_next) { + rx_next = + (i == NRXBLOCKS - 1) ? lp->rx_head : rx + RXBLOCKZ; - fd.fd_status = 0; - fd.fd_command = (i == NRXBLOCKS - 1) ? FD_COMMAND_EL : 0; - fd.fd_link_offset = rx_next; - fd.fd_rbd_offset = rx + sizeof(fd); - obram_write(ioaddr, rx, (unsigned char *)&fd, sizeof(fd)); + fd.fd_status = 0; + fd.fd_command = (i == NRXBLOCKS - 1) ? FD_COMMAND_EL : 0; + fd.fd_link_offset = rx_next; + fd.fd_rbd_offset = rx + sizeof(fd); + obram_write(ioaddr, rx, (unsigned char *) &fd, sizeof(fd)); - rbd.rbd_status = 0; - rbd.rbd_next_rbd_offset = I82586NULL; - rbd.rbd_bufl = rx + sizeof(fd) + sizeof(rbd); - rbd.rbd_bufh = 0; - rbd.rbd_el_size = RBD_EL | (RBD_SIZE & MAXDATAZ); - obram_write(ioaddr, rx + sizeof(fd), - (unsigned char *) &rbd, sizeof(rbd)); + rbd.rbd_status = 0; + rbd.rbd_next_rbd_offset = I82586NULL; + rbd.rbd_bufl = rx + sizeof(fd) + sizeof(rbd); + rbd.rbd_bufh = 0; + rbd.rbd_el_size = RBD_EL | (RBD_SIZE & MAXDATAZ); + obram_write(ioaddr, rx + sizeof(fd), + (unsigned char *) &rbd, sizeof(rbd)); - lp->rx_last = rx; - } + lp->rx_last = rx; + } - obram_write(ioaddr, scboff(OFFSET_SCB, scb_rfa_offset), - (unsigned char *) &lp->rx_head, sizeof(lp->rx_head)); + obram_write(ioaddr, scboff(OFFSET_SCB, scb_rfa_offset), + (unsigned char *) &lp->rx_head, sizeof(lp->rx_head)); - scb_cs = SCB_CMD_RUC_GO; - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cs, sizeof(scb_cs)); + scb_cs = SCB_CMD_RUC_GO; + obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), + (unsigned char *) &scb_cs, sizeof(scb_cs)); - set_chan_attn(ioaddr, lp->hacr); + set_chan_attn(ioaddr, lp->hacr); - for(i = 1000; i > 0; i--) - { - obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cs, sizeof(scb_cs)); - if (scb_cs == 0) - break; + for (i = 1000; i > 0; i--) { + obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), + (unsigned char *) &scb_cs, sizeof(scb_cs)); + if (scb_cs == 0) + break; - udelay(10); - } + udelay(10); + } - if(i <= 0) - { + if (i <= 0) { #ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO "%s: wavelan_ru_start(): board not accepting command.\n", - dev->name); + printk(KERN_INFO + "%s: wavelan_ru_start(): board not accepting command.\n", + dev->name); #endif - return -1; - } - + return -1; + } #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_ru_start()\n", dev->name); + printk(KERN_DEBUG "%s: <-wv_ru_start()\n", dev->name); #endif - return 0; + return 0; } /*------------------------------------------------------------------*/ @@ -3150,94 +3080,93 @@ wv_ru_start(device * dev) * * (called by wv_hw_reset()) */ -static inline int -wv_cu_start(device * dev) +static inline int wv_cu_start(device * dev) { - net_local * lp = (net_local *) dev->priv; - u_long ioaddr = dev->base_addr; - int i; - u_short txblock; - u_short first_nop; - u_short scb_cs; + net_local *lp = (net_local *) dev->priv; + unsigned long ioaddr = dev->base_addr; + int i; + u16 txblock; + u16 first_nop; + u16 scb_cs; #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_cu_start()\n", dev->name); + printk(KERN_DEBUG "%s: ->wv_cu_start()\n", dev->name); #endif - lp->tx_first_free = OFFSET_CU; - lp->tx_first_in_use = I82586NULL; - - for(i = 0, txblock = OFFSET_CU; - i < NTXBLOCKS; - i++, txblock += TXBLOCKZ) - { - ac_tx_t tx; - ac_nop_t nop; - tbd_t tbd; - unsigned short tx_addr; - unsigned short nop_addr; - unsigned short tbd_addr; - unsigned short buf_addr; - - tx_addr = txblock; - nop_addr = tx_addr + sizeof(tx); - tbd_addr = nop_addr + sizeof(nop); - buf_addr = tbd_addr + sizeof(tbd); - - tx.tx_h.ac_status = 0; - tx.tx_h.ac_command = acmd_transmit | AC_CFLD_I; - tx.tx_h.ac_link = nop_addr; - tx.tx_tbd_offset = tbd_addr; - obram_write(ioaddr, tx_addr, (unsigned char *) &tx, sizeof(tx)); - - nop.nop_h.ac_status = 0; - nop.nop_h.ac_command = acmd_nop; - nop.nop_h.ac_link = nop_addr; - obram_write(ioaddr, nop_addr, (unsigned char *) &nop, sizeof(nop)); - - tbd.tbd_status = TBD_STATUS_EOF; - tbd.tbd_next_bd_offset = I82586NULL; - tbd.tbd_bufl = buf_addr; - tbd.tbd_bufh = 0; - obram_write(ioaddr, tbd_addr, (unsigned char *) &tbd, sizeof(tbd)); - } - - first_nop = OFFSET_CU + (NTXBLOCKS - 1) * TXBLOCKZ + sizeof(ac_tx_t); - obram_write(ioaddr, scboff(OFFSET_SCB, scb_cbl_offset), - (unsigned char *) &first_nop, sizeof(first_nop)); - - scb_cs = SCB_CMD_CUC_GO; - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cs, sizeof(scb_cs)); - - set_chan_attn(ioaddr, lp->hacr); - - for(i = 1000; i > 0; i--) - { - obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cs, sizeof(scb_cs)); - if (scb_cs == 0) - break; - - udelay(10); - } - - if(i <= 0) - { + lp->tx_first_free = OFFSET_CU; + lp->tx_first_in_use = I82586NULL; + + for (i = 0, txblock = OFFSET_CU; + i < NTXBLOCKS; i++, txblock += TXBLOCKZ) { + ac_tx_t tx; + ac_nop_t nop; + tbd_t tbd; + unsigned short tx_addr; + unsigned short nop_addr; + unsigned short tbd_addr; + unsigned short buf_addr; + + tx_addr = txblock; + nop_addr = tx_addr + sizeof(tx); + tbd_addr = nop_addr + sizeof(nop); + buf_addr = tbd_addr + sizeof(tbd); + + tx.tx_h.ac_status = 0; + tx.tx_h.ac_command = acmd_transmit | AC_CFLD_I; + tx.tx_h.ac_link = nop_addr; + tx.tx_tbd_offset = tbd_addr; + obram_write(ioaddr, tx_addr, (unsigned char *) &tx, + sizeof(tx)); + + nop.nop_h.ac_status = 0; + nop.nop_h.ac_command = acmd_nop; + nop.nop_h.ac_link = nop_addr; + obram_write(ioaddr, nop_addr, (unsigned char *) &nop, + sizeof(nop)); + + tbd.tbd_status = TBD_STATUS_EOF; + tbd.tbd_next_bd_offset = I82586NULL; + tbd.tbd_bufl = buf_addr; + tbd.tbd_bufh = 0; + obram_write(ioaddr, tbd_addr, (unsigned char *) &tbd, + sizeof(tbd)); + } + + first_nop = + OFFSET_CU + (NTXBLOCKS - 1) * TXBLOCKZ + sizeof(ac_tx_t); + obram_write(ioaddr, scboff(OFFSET_SCB, scb_cbl_offset), + (unsigned char *) &first_nop, sizeof(first_nop)); + + scb_cs = SCB_CMD_CUC_GO; + obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), + (unsigned char *) &scb_cs, sizeof(scb_cs)); + + set_chan_attn(ioaddr, lp->hacr); + + for (i = 1000; i > 0; i--) { + obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), + (unsigned char *) &scb_cs, sizeof(scb_cs)); + if (scb_cs == 0) + break; + + udelay(10); + } + + if (i <= 0) { #ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO "%s: wavelan_cu_start(): board not accepting command.\n", - dev->name); + printk(KERN_INFO + "%s: wavelan_cu_start(): board not accepting command.\n", + dev->name); #endif - return -1; - } - - lp->tx_n_in_use = 0; - dev->tbusy = 0; + return -1; + } + lp->tx_n_in_use = 0; + netif_wake_queue(dev); #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_cu_start()\n", dev->name); + printk(KERN_DEBUG "%s: <-wv_cu_start()\n", dev->name); #endif - return 0; + return 0; } /*------------------------------------------------------------------*/ @@ -3252,121 +3181,122 @@ wv_cu_start(device * dev) * * (called by wv_hw_reset()) */ -static inline int -wv_82586_start(device * dev) +static inline int wv_82586_start(device * dev) { - net_local * lp = (net_local *) dev->priv; - u_long ioaddr = dev->base_addr; - scp_t scp; /* system configuration pointer */ - iscp_t iscp; /* intermediate scp */ - scb_t scb; /* system control block */ - ach_t cb; /* Action command header */ - u_char zeroes[512]; - int i; + net_local *lp = (net_local *) dev->priv; + unsigned long ioaddr = dev->base_addr; + scp_t scp; /* system configuration pointer */ + iscp_t iscp; /* intermediate scp */ + scb_t scb; /* system control block */ + ach_t cb; /* Action command header */ + u8 zeroes[512]; + int i; #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_82586_start()\n", dev->name); + printk(KERN_DEBUG "%s: ->wv_82586_start()\n", dev->name); #endif - /* - * Clear the onboard RAM. - */ - memset(&zeroes[0], 0x00, sizeof(zeroes)); - for(i = 0; i < I82586_MEMZ; i += sizeof(zeroes)) - obram_write(ioaddr, i, &zeroes[0], sizeof(zeroes)); - - /* - * Construct the command unit structures: - * scp, iscp, scb, cb. - */ - memset(&scp, 0x00, sizeof(scp)); - scp.scp_sysbus = SCP_SY_16BBUS; - scp.scp_iscpl = OFFSET_ISCP; - obram_write(ioaddr, OFFSET_SCP, (unsigned char *)&scp, sizeof(scp)); - - memset(&iscp, 0x00, sizeof(iscp)); - iscp.iscp_busy = 1; - iscp.iscp_offset = OFFSET_SCB; - obram_write(ioaddr, OFFSET_ISCP, (unsigned char *)&iscp, sizeof(iscp)); - - /* Our first command is to reset the i82586. */ - memset(&scb, 0x00, sizeof(scb)); - scb.scb_command = SCB_CMD_RESET; - scb.scb_cbl_offset = OFFSET_CU; - scb.scb_rfa_offset = OFFSET_RU; - obram_write(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb)); - - set_chan_attn(ioaddr, lp->hacr); - - /* Wait for command to finish. */ - for(i = 1000; i > 0; i--) - { - obram_read(ioaddr, OFFSET_ISCP, (unsigned char *) &iscp, sizeof(iscp)); - - if(iscp.iscp_busy == (unsigned short) 0) - break; - - udelay(10); - } - - if(i <= 0) - { + /* + * Clear the onboard RAM. + */ + memset(&zeroes[0], 0x00, sizeof(zeroes)); + for (i = 0; i < I82586_MEMZ; i += sizeof(zeroes)) + obram_write(ioaddr, i, &zeroes[0], sizeof(zeroes)); + + /* + * Construct the command unit structures: + * scp, iscp, scb, cb. + */ + memset(&scp, 0x00, sizeof(scp)); + scp.scp_sysbus = SCP_SY_16BBUS; + scp.scp_iscpl = OFFSET_ISCP; + obram_write(ioaddr, OFFSET_SCP, (unsigned char *) &scp, + sizeof(scp)); + + memset(&iscp, 0x00, sizeof(iscp)); + iscp.iscp_busy = 1; + iscp.iscp_offset = OFFSET_SCB; + obram_write(ioaddr, OFFSET_ISCP, (unsigned char *) &iscp, + sizeof(iscp)); + + /* Our first command is to reset the i82586. */ + memset(&scb, 0x00, sizeof(scb)); + scb.scb_command = SCB_CMD_RESET; + scb.scb_cbl_offset = OFFSET_CU; + scb.scb_rfa_offset = OFFSET_RU; + obram_write(ioaddr, OFFSET_SCB, (unsigned char *) &scb, + sizeof(scb)); + + set_chan_attn(ioaddr, lp->hacr); + + /* Wait for command to finish. */ + for (i = 1000; i > 0; i--) { + obram_read(ioaddr, OFFSET_ISCP, (unsigned char *) &iscp, + sizeof(iscp)); + + if (iscp.iscp_busy == (unsigned short) 0) + break; + + udelay(10); + } + + if (i <= 0) { #ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO "%s: wv_82586_start(): iscp_busy timeout.\n", - dev->name); + printk(KERN_INFO + "%s: wv_82586_start(): iscp_busy timeout.\n", + dev->name); #endif - return -1; - } + return -1; + } - /* Check command completion. */ - for(i = 15; i > 0; i--) - { - obram_read(ioaddr, OFFSET_SCB, (unsigned char *) &scb, sizeof(scb)); + /* Check command completion. */ + for (i = 15; i > 0; i--) { + obram_read(ioaddr, OFFSET_SCB, (unsigned char *) &scb, + sizeof(scb)); - if (scb.scb_status == (SCB_ST_CX | SCB_ST_CNA)) - break; + if (scb.scb_status == (SCB_ST_CX | SCB_ST_CNA)) + break; - udelay(10); - } + udelay(10); + } - if (i <= 0) - { + if (i <= 0) { #ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO "%s: wv_82586_start(): status: expected 0x%02x, got 0x%02x.\n", - dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status); + printk(KERN_INFO + "%s: wv_82586_start(): status: expected 0x%02x, got 0x%02x.\n", + dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status); #endif - return -1; - } + return -1; + } - wv_ack(dev); + wv_ack(dev); - /* Set the action command header. */ - memset(&cb, 0x00, sizeof(cb)); - cb.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_diagnose); - cb.ac_link = OFFSET_CU; - obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); + /* Set the action command header. */ + memset(&cb, 0x00, sizeof(cb)); + cb.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_diagnose); + cb.ac_link = OFFSET_CU; + obram_write(ioaddr, OFFSET_CU, (unsigned char *) &cb, sizeof(cb)); - if(wv_synchronous_cmd(dev, "diag()") == -1) - return -1; + if (wv_synchronous_cmd(dev, "diag()") == -1) + return -1; - obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); - if(cb.ac_status & AC_SFLD_FAIL) - { + obram_read(ioaddr, OFFSET_CU, (unsigned char *) &cb, sizeof(cb)); + if (cb.ac_status & AC_SFLD_FAIL) { #ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO "%s: wv_82586_start(): i82586 Self Test failed.\n", - dev->name); + printk(KERN_INFO + "%s: wv_82586_start(): i82586 Self Test failed.\n", + dev->name); #endif - return -1; - } - + return -1; + } #ifdef DEBUG_I82586_SHOW - wv_scb_show(ioaddr); + wv_scb_show(ioaddr); #endif #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_82586_start()\n", dev->name); + printk(KERN_DEBUG "%s: <-wv_82586_start()\n", dev->name); #endif - return 0; + return 0; } /*------------------------------------------------------------------*/ @@ -3383,184 +3313,179 @@ wv_82586_start(device * dev) * * (called by wv_hw_reset(), wv_82586_reconfig()) */ -static void -wv_82586_config(device * dev) +static void wv_82586_config(device * dev) { - net_local * lp = (net_local *) dev->priv; - u_long ioaddr = dev->base_addr; - unsigned short txblock; - unsigned short txpred; - unsigned short tx_addr; - unsigned short nop_addr; - unsigned short tbd_addr; - unsigned short cfg_addr; - unsigned short ias_addr; - unsigned short mcs_addr; - ac_tx_t tx; - ac_nop_t nop; - ac_cfg_t cfg; /* Configure action */ - ac_ias_t ias; /* IA-setup action */ - ac_mcs_t mcs; /* Multicast setup */ - struct dev_mc_list * dmi; - unsigned long x; + net_local *lp = (net_local *) dev->priv; + unsigned long ioaddr = dev->base_addr; + unsigned short txblock; + unsigned short txpred; + unsigned short tx_addr; + unsigned short nop_addr; + unsigned short tbd_addr; + unsigned short cfg_addr; + unsigned short ias_addr; + unsigned short mcs_addr; + ac_tx_t tx; + ac_nop_t nop; + ac_cfg_t cfg; /* Configure action */ + ac_ias_t ias; /* IA-setup action */ + ac_mcs_t mcs; /* Multicast setup */ + struct dev_mc_list *dmi; + unsigned long flags; #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_82586_config()\n", dev->name); + printk(KERN_DEBUG "%s: ->wv_82586_config()\n", dev->name); #endif - x = wv_splhi(); - - /* Calculate addresses of next block and previous block. */ - txblock = lp->tx_first_free; - txpred = txblock - TXBLOCKZ; - if(txpred < OFFSET_CU) - txpred += NTXBLOCKS * TXBLOCKZ; - lp->tx_first_free += TXBLOCKZ; - if(lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) - lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ; - - lp->tx_n_in_use++; - - /* Calculate addresses of the different parts of the block. */ - tx_addr = txblock; - nop_addr = tx_addr + sizeof(tx); - tbd_addr = nop_addr + sizeof(nop); - cfg_addr = tbd_addr + sizeof(tbd_t); /* beginning of the buffer */ - ias_addr = cfg_addr + sizeof(cfg); - mcs_addr = ias_addr + sizeof(ias); - - /* - * Transmit command - */ - tx.tx_h.ac_status = 0xFFFF; /* Fake completion value */ - obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status), - (unsigned char *) &tx.tx_h.ac_status, - sizeof(tx.tx_h.ac_status)); - - /* - * NOP command - */ - nop.nop_h.ac_status = 0; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), - (unsigned char *) &nop.nop_h.ac_status, - sizeof(nop.nop_h.ac_status)); - nop.nop_h.ac_link = nop_addr; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), - (unsigned char *) &nop.nop_h.ac_link, - sizeof(nop.nop_h.ac_link)); - - /* Create a configure action. */ - memset(&cfg, 0x00, sizeof(cfg)); - - /* - * For Linux we invert AC_CFG_ALOC() so as to conform - * to the way that net packets reach us from above. - * (See also ac_tx_t.) - * - * Updated from Wavelan Manual WCIN085B - */ - cfg.cfg_byte_cnt = AC_CFG_BYTE_CNT(sizeof(ac_cfg_t) - sizeof(ach_t)); - cfg.cfg_fifolim = AC_CFG_FIFOLIM(4); - cfg.cfg_byte8 = AC_CFG_SAV_BF(1) | - AC_CFG_SRDY(0); - cfg.cfg_byte9 = AC_CFG_ELPBCK(0) | - AC_CFG_ILPBCK(0) | - AC_CFG_PRELEN(AC_CFG_PLEN_2) | - AC_CFG_ALOC(1) | - AC_CFG_ADDRLEN(WAVELAN_ADDR_SIZE); - cfg.cfg_byte10 = AC_CFG_BOFMET(1) | - AC_CFG_ACR(6) | - AC_CFG_LINPRIO(0); - cfg.cfg_ifs = 0x20; - cfg.cfg_slotl = 0x0C; - cfg.cfg_byte13 = AC_CFG_RETRYNUM(15) | - AC_CFG_SLTTMHI(0); - cfg.cfg_byte14 = AC_CFG_FLGPAD(0) | - AC_CFG_BTSTF(0) | - AC_CFG_CRC16(0) | - AC_CFG_NCRC(0) | - AC_CFG_TNCRS(1) | - AC_CFG_MANCH(0) | - AC_CFG_BCDIS(0) | - AC_CFG_PRM(lp->promiscuous); - cfg.cfg_byte15 = AC_CFG_ICDS(0) | - AC_CFG_CDTF(0) | - AC_CFG_ICSS(0) | - AC_CFG_CSTF(0); + save_flags(flags); + cli(); + + /* Calculate addresses of next block and previous block. */ + txblock = lp->tx_first_free; + txpred = txblock - TXBLOCKZ; + if (txpred < OFFSET_CU) + txpred += NTXBLOCKS * TXBLOCKZ; + lp->tx_first_free += TXBLOCKZ; + if (lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) + lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ; + + lp->tx_n_in_use++; + + /* Calculate addresses of the different parts of the block. */ + tx_addr = txblock; + nop_addr = tx_addr + sizeof(tx); + tbd_addr = nop_addr + sizeof(nop); + cfg_addr = tbd_addr + sizeof(tbd_t); /* beginning of the buffer */ + ias_addr = cfg_addr + sizeof(cfg); + mcs_addr = ias_addr + sizeof(ias); + + /* + * Transmit command + */ + tx.tx_h.ac_status = 0xFFFF; /* Fake completion value */ + obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status), + (unsigned char *) &tx.tx_h.ac_status, + sizeof(tx.tx_h.ac_status)); + + /* + * NOP command + */ + nop.nop_h.ac_status = 0; + obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), + (unsigned char *) &nop.nop_h.ac_status, + sizeof(nop.nop_h.ac_status)); + nop.nop_h.ac_link = nop_addr; + obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), + (unsigned char *) &nop.nop_h.ac_link, + sizeof(nop.nop_h.ac_link)); + + /* Create a configure action. */ + memset(&cfg, 0x00, sizeof(cfg)); + + /* + * For Linux we invert AC_CFG_ALOC() so as to conform + * to the way that net packets reach us from above. + * (See also ac_tx_t.) + * + * Updated from Wavelan Manual WCIN085B + */ + cfg.cfg_byte_cnt = + AC_CFG_BYTE_CNT(sizeof(ac_cfg_t) - sizeof(ach_t)); + cfg.cfg_fifolim = AC_CFG_FIFOLIM(4); + cfg.cfg_byte8 = AC_CFG_SAV_BF(1) | AC_CFG_SRDY(0); + cfg.cfg_byte9 = AC_CFG_ELPBCK(0) | + AC_CFG_ILPBCK(0) | + AC_CFG_PRELEN(AC_CFG_PLEN_2) | + AC_CFG_ALOC(1) | AC_CFG_ADDRLEN(WAVELAN_ADDR_SIZE); + cfg.cfg_byte10 = AC_CFG_BOFMET(1) | + AC_CFG_ACR(6) | AC_CFG_LINPRIO(0); + cfg.cfg_ifs = 0x20; + cfg.cfg_slotl = 0x0C; + cfg.cfg_byte13 = AC_CFG_RETRYNUM(15) | AC_CFG_SLTTMHI(0); + cfg.cfg_byte14 = AC_CFG_FLGPAD(0) | + AC_CFG_BTSTF(0) | + AC_CFG_CRC16(0) | + AC_CFG_NCRC(0) | + AC_CFG_TNCRS(1) | + AC_CFG_MANCH(0) | + AC_CFG_BCDIS(0) | AC_CFG_PRM(lp->promiscuous); + cfg.cfg_byte15 = AC_CFG_ICDS(0) | + AC_CFG_CDTF(0) | AC_CFG_ICSS(0) | AC_CFG_CSTF(0); /* cfg.cfg_min_frm_len = AC_CFG_MNFRM(64); */ - cfg.cfg_min_frm_len = AC_CFG_MNFRM(8); - - cfg.cfg_h.ac_command = (AC_CFLD_CMD & acmd_configure); - cfg.cfg_h.ac_link = ias_addr; - obram_write(ioaddr, cfg_addr, (unsigned char *)&cfg, sizeof(cfg)); - - /* Set up the MAC address */ - memset(&ias, 0x00, sizeof(ias)); - ias.ias_h.ac_command = (AC_CFLD_CMD & acmd_ia_setup); - ias.ias_h.ac_link = mcs_addr; - memcpy(&ias.ias_addr[0], (unsigned char *)&dev->dev_addr[0], sizeof(ias.ias_addr)); - obram_write(ioaddr, ias_addr, (unsigned char *)&ias, sizeof(ias)); - - /* Initialize adapter's Ethernet multicast addresses */ - memset(&mcs, 0x00, sizeof(mcs)); - mcs.mcs_h.ac_command = AC_CFLD_I | (AC_CFLD_CMD & acmd_mc_setup); - mcs.mcs_h.ac_link = nop_addr; - mcs.mcs_cnt = WAVELAN_ADDR_SIZE * lp->mc_count; - obram_write(ioaddr, mcs_addr, (unsigned char *)&mcs, sizeof(mcs)); - - /* Any address to set? */ - if(lp->mc_count) - { - for(dmi=dev->mc_list; dmi; dmi=dmi->next) - outsw(PIOP1(ioaddr), (u_short *) dmi->dmi_addr, - WAVELAN_ADDR_SIZE >> 1); + cfg.cfg_min_frm_len = AC_CFG_MNFRM(8); + + cfg.cfg_h.ac_command = (AC_CFLD_CMD & acmd_configure); + cfg.cfg_h.ac_link = ias_addr; + obram_write(ioaddr, cfg_addr, (unsigned char *) &cfg, sizeof(cfg)); + + /* Set up the MAC address */ + memset(&ias, 0x00, sizeof(ias)); + ias.ias_h.ac_command = (AC_CFLD_CMD & acmd_ia_setup); + ias.ias_h.ac_link = mcs_addr; + memcpy(&ias.ias_addr[0], (unsigned char *) &dev->dev_addr[0], + sizeof(ias.ias_addr)); + obram_write(ioaddr, ias_addr, (unsigned char *) &ias, sizeof(ias)); + + /* Initialize adapter's Ethernet multicast addresses */ + memset(&mcs, 0x00, sizeof(mcs)); + mcs.mcs_h.ac_command = AC_CFLD_I | (AC_CFLD_CMD & acmd_mc_setup); + mcs.mcs_h.ac_link = nop_addr; + mcs.mcs_cnt = WAVELAN_ADDR_SIZE * lp->mc_count; + obram_write(ioaddr, mcs_addr, (unsigned char *) &mcs, sizeof(mcs)); + + /* Any address to set? */ + if (lp->mc_count) { + for (dmi = dev->mc_list; dmi; dmi = dmi->next) + outsw(PIOP1(ioaddr), (u16 *) dmi->dmi_addr, + WAVELAN_ADDR_SIZE >> 1); #ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "%s: wv_82586_config(): set %d multicast addresses:\n", - dev->name, lp->mc_count); - for(dmi=dev->mc_list; dmi; dmi=dmi->next) - printk(KERN_DEBUG " %02x:%02x:%02x:%02x:%02x:%02x\n", - dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2], - dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5] ); + printk(KERN_DEBUG + "%s: wv_82586_config(): set %d multicast addresses:\n", + dev->name, lp->mc_count); + for (dmi = dev->mc_list; dmi; dmi = dmi->next) + printk(KERN_DEBUG + " %02x:%02x:%02x:%02x:%02x:%02x\n", + dmi->dmi_addr[0], dmi->dmi_addr[1], + dmi->dmi_addr[2], dmi->dmi_addr[3], + dmi->dmi_addr[4], dmi->dmi_addr[5]); #endif - } - - /* - * Overwrite the predecessor NOP link - * so that it points to the configure action. - */ - nop_addr = txpred + sizeof(tx); - nop.nop_h.ac_status = 0; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), - (unsigned char *)&nop.nop_h.ac_status, - sizeof(nop.nop_h.ac_status)); - nop.nop_h.ac_link = cfg_addr; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), - (unsigned char *) &nop.nop_h.ac_link, - sizeof(nop.nop_h.ac_link)); - - /* If watchdog not already active, activate it... */ - if(lp->watchdog.prev == (timer_list *) NULL) - { - /* set timer to expire in WATCHDOG_JIFFIES */ - lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES; - add_timer(&lp->watchdog); - } - - lp->reconfig_82586 = 0; - - if(lp->tx_first_in_use == I82586NULL) - lp->tx_first_in_use = txblock; - - if(lp->tx_n_in_use < NTXBLOCKS - 1) - dev->tbusy = 0; - - wv_splx(x); + } + + /* + * Overwrite the predecessor NOP link + * so that it points to the configure action. + */ + nop_addr = txpred + sizeof(tx); + nop.nop_h.ac_status = 0; + obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), + (unsigned char *) &nop.nop_h.ac_status, + sizeof(nop.nop_h.ac_status)); + nop.nop_h.ac_link = cfg_addr; + obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), + (unsigned char *) &nop.nop_h.ac_link, + sizeof(nop.nop_h.ac_link)); + + /* If watchdog not already active, activate it... */ + if (lp->watchdog.prev == (timer_list *) NULL) { + /* set timer to expire in WATCHDOG_JIFFIES */ + lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES; + add_timer(&lp->watchdog); + } + + lp->reconfig_82586 = 0; + if (lp->tx_first_in_use == I82586NULL) + lp->tx_first_in_use = txblock; + + if (lp->tx_n_in_use < NTXBLOCKS - 1) + netif_wake_queue(dev); + + restore_flags(flags); #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_82586_config()\n", dev->name); + printk(KERN_DEBUG "%s: <-wv_82586_config()\n", dev->name); #endif } @@ -3569,28 +3494,29 @@ wv_82586_config(device * dev) * This routine, called by wavelan_close(), gracefully stops the * WaveLAN controller (i82586). */ -static inline void -wv_82586_stop(device * dev) +static inline void wv_82586_stop(device * dev) { - net_local * lp = (net_local *) dev->priv; - u_long ioaddr = dev->base_addr; - u_short scb_cmd; + net_local *lp = (net_local *) dev->priv; + unsigned long ioaddr = dev->base_addr; + u16 scb_cmd; #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_82586_stop()\n", dev->name); + printk(KERN_DEBUG "%s: ->wv_82586_stop()\n", dev->name); #endif - /* Suspend both command unit and receive unit. */ - scb_cmd = (SCB_CMD_CUC & SCB_CMD_CUC_SUS) | (SCB_CMD_RUC & SCB_CMD_RUC_SUS); - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *)&scb_cmd, sizeof(scb_cmd)); - set_chan_attn(ioaddr, lp->hacr); + /* Suspend both command unit and receive unit. */ + scb_cmd = + (SCB_CMD_CUC & SCB_CMD_CUC_SUS) | (SCB_CMD_RUC & + SCB_CMD_RUC_SUS); + obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), + (unsigned char *) &scb_cmd, sizeof(scb_cmd)); + set_chan_attn(ioaddr, lp->hacr); - /* No more interrupts */ - wv_ints_off(dev); + /* No more interrupts */ + wv_ints_off(dev); #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_82586_stop()\n", dev->name); + printk(KERN_DEBUG "%s: <-wv_82586_stop()\n", dev->name); #endif } @@ -3604,49 +3530,47 @@ wv_82586_stop(device * dev) * 4. Start the LAN controller's command unit * 5. Start the LAN controller's receive unit */ -static int -wv_hw_reset(device * dev) +static int wv_hw_reset(device * dev) { - net_local * lp = (net_local *)dev->priv; - u_long ioaddr = dev->base_addr; + net_local *lp = (net_local *) dev->priv; + unsigned long ioaddr = dev->base_addr; #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_hw_reset(dev=0x%x)\n", dev->name, - (unsigned int)dev); + printk(KERN_DEBUG "%s: ->wv_hw_reset(dev=0x%x)\n", dev->name, + (unsigned int) dev); #endif - /* If watchdog was activated, kill it! */ - if(lp->watchdog.prev != (timer_list *) NULL) - del_timer(&lp->watchdog); + /* If watchdog was activated, kill it! */ + if (lp->watchdog.prev != (timer_list *) NULL) + del_timer(&lp->watchdog); - /* Increase the number of resets done. */ - lp->nresets++; + /* Increase the number of resets done. */ + lp->nresets++; - wv_hacr_reset(ioaddr); - lp->hacr = HACR_DEFAULT; + wv_hacr_reset(ioaddr); + lp->hacr = HACR_DEFAULT; - if((wv_mmc_init(dev) < 0) || - (wv_82586_start(dev) < 0)) - return -1; + if ((wv_mmc_init(dev) < 0) || (wv_82586_start(dev) < 0)) + return -1; - /* Enable the card to send interrupts. */ - wv_ints_on(dev); + /* Enable the card to send interrupts. */ + wv_ints_on(dev); - /* Start card functions */ - if(wv_cu_start(dev) < 0) - return -1; + /* Start card functions */ + if (wv_cu_start(dev) < 0) + return -1; - /* Setup the controller and parameters */ - wv_82586_config(dev); + /* Setup the controller and parameters */ + wv_82586_config(dev); - /* Finish configuration with the receive unit */ - if(wv_ru_start(dev) < 0) - return -1; + /* Finish configuration with the receive unit */ + if (wv_ru_start(dev) < 0) + return -1; #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_hw_reset()\n", dev->name); + printk(KERN_DEBUG "%s: <-wv_hw_reset()\n", dev->name); #endif - return 0; + return 0; } /*------------------------------------------------------------------*/ @@ -3655,40 +3579,39 @@ wv_hw_reset(device * dev) * As a side effect, this reads the MAC address. * (called in wavelan_probe() and init_module()) */ -static int -wv_check_ioaddr(u_long ioaddr, - u_char * mac) +static int wv_check_ioaddr(unsigned long ioaddr, u8 * mac) { - int i; /* Loop counter */ - - /* Check if the base address if available. */ - if(check_region(ioaddr, sizeof(ha_t))) - return EADDRINUSE; /* ioaddr already used */ - - /* Reset host interface */ - wv_hacr_reset(ioaddr); - - /* Read the MAC address from the parameter storage area. */ - psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_univ_mac_addr), - mac, 6); - - /* - * Check the first three octets of the address for the manufacturer's code. - * Note: if this can't find your WaveLAN card, you've got a - * non-NCR/AT&T/Lucent ISA card. See wavelan.p.h for detail on - * how to configure your card. - */ - for(i = 0; i < (sizeof(MAC_ADDRESSES) / sizeof(char) / 3); i++) - if((mac[0] == MAC_ADDRESSES[i][0]) && - (mac[1] == MAC_ADDRESSES[i][1]) && - (mac[2] == MAC_ADDRESSES[i][2])) - return 0; + int i; /* Loop counter */ + + /* Check if the base address if available. */ + if (check_region(ioaddr, sizeof(ha_t))) + return EADDRINUSE; /* ioaddr already used */ + + /* Reset host interface */ + wv_hacr_reset(ioaddr); + + /* Read the MAC address from the parameter storage area. */ + psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_univ_mac_addr), + mac, 6); + + /* + * Check the first three octets of the address for the manufacturer's code. + * Note: if this can't find your WaveLAN card, you've got a + * non-NCR/AT&T/Lucent ISA card. See wavelan.p.h for detail on + * how to configure your card. + */ + for (i = 0; i < (sizeof(MAC_ADDRESSES) / sizeof(char) / 3); i++) + if ((mac[0] == MAC_ADDRESSES[i][0]) && + (mac[1] == MAC_ADDRESSES[i][1]) && + (mac[2] == MAC_ADDRESSES[i][2])) + return 0; #ifdef DEBUG_CONFIG_INFO - printk(KERN_WARNING "WaveLAN (0x%3X): your MAC address might be %02X:%02X:%02X.\n", - ioaddr, mac[0], mac[1], mac[2]); + printk(KERN_WARNING + "WaveLAN (0x%3X): your MAC address might be %02X:%02X:%02X.\n", + ioaddr, mac[0], mac[1], mac[2]); #endif - return ENODEV; + return ENODEV; } /************************ INTERRUPT HANDLING ************************/ @@ -3697,133 +3620,121 @@ wv_check_ioaddr(u_long ioaddr, * This function is the interrupt handler for the WaveLAN card. This * routine will be called whenever: */ -static void -wavelan_interrupt(int irq, - void * dev_id, - struct pt_regs * regs) +static void wavelan_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - device * dev; - u_long ioaddr; - net_local * lp; - u_short hasr; - u_short status; - u_short ack_cmd; + device *dev; + unsigned long ioaddr; + net_local *lp; + u16 hasr; + u16 status; + u16 ack_cmd; - dev = dev_id; + dev = dev_id; #ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name); + printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name); #endif - lp = (net_local *) dev->priv; - ioaddr = dev->base_addr; + lp = (net_local *) dev->priv; + ioaddr = dev->base_addr; - /* Prevent reentrance. What should we do here? */ -#ifdef DEBUG_INTERRUPT_ERROR - if(dev->interrupt) - printk(KERN_INFO "%s: wavelan_interrupt(): Re-entering the interrupt handler.\n", - dev->name); -#endif - dev->interrupt = 1; + /* Prevent reentrance. What should we do here? */ - if((hasr = hasr_read(ioaddr)) & HASR_MMC_INTR) - { - u_char dce_status; + if ((hasr = hasr_read(ioaddr)) & HASR_MMC_INTR) { + u8 dce_status; - /* - * Interrupt from the modem management controller. - * This will clear it -- ignored for now. - */ - mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status, sizeof(dce_status)); + /* + * Interrupt from the modem management controller. + * This will clear it -- ignored for now. + */ + mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status, + sizeof(dce_status)); #ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n", - dev->name, dce_status); + printk(KERN_INFO + "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n", + dev->name, dce_status); #endif - } + } - if((hasr & HASR_82586_INTR) == 0) - { - dev->interrupt = 0; + if ((hasr & HASR_82586_INTR) == 0) { #ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wavelan_interrupt(): interrupt not coming from i82586\n", - dev->name); + printk(KERN_INFO + "%s: wavelan_interrupt(): interrupt not coming from i82586\n", + dev->name); #endif - return; - } + return; + } - /* Read interrupt data. */ - obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), - (unsigned char *) &status, sizeof(status)); + /* Read interrupt data. */ + obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), + (unsigned char *) &status, sizeof(status)); - /* - * Acknowledge the interrupt(s). - */ - ack_cmd = status & SCB_ST_INT; - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &ack_cmd, sizeof(ack_cmd)); - set_chan_attn(ioaddr, lp->hacr); + /* + * Acknowledge the interrupt(s). + */ + ack_cmd = status & SCB_ST_INT; + obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), + (unsigned char *) &ack_cmd, sizeof(ack_cmd)); + set_chan_attn(ioaddr, lp->hacr); #ifdef DEBUG_INTERRUPT_INFO - printk(KERN_DEBUG "%s: wavelan_interrupt(): status 0x%04x.\n", - dev->name, status); + printk(KERN_DEBUG "%s: wavelan_interrupt(): status 0x%04x.\n", + dev->name, status); #endif - /* Command completed. */ - if((status & SCB_ST_CX) == SCB_ST_CX) - { + /* Command completed. */ + if ((status & SCB_ST_CX) == SCB_ST_CX) { #ifdef DEBUG_INTERRUPT_INFO - printk(KERN_DEBUG "%s: wavelan_interrupt(): command completed.\n", - dev->name); + printk(KERN_DEBUG + "%s: wavelan_interrupt(): command completed.\n", + dev->name); #endif - wv_complete(dev, ioaddr, lp); - - /* If watchdog was activated, kill it ! */ - if(lp->watchdog.prev != (timer_list *) NULL) - del_timer(&lp->watchdog); - if(lp->tx_n_in_use > 0) - { - /* set timer to expire in WATCHDOG_JIFFIES */ - lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES; - add_timer(&lp->watchdog); + wv_complete(dev, ioaddr, lp); + + /* If watchdog was activated, kill it ! */ + if (lp->watchdog.prev != (timer_list *) NULL) + del_timer(&lp->watchdog); + if (lp->tx_n_in_use > 0) { + /* set timer to expire in WATCHDOG_JIFFIES */ + lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES; + add_timer(&lp->watchdog); + } } - } - /* Frame received. */ - if((status & SCB_ST_FR) == SCB_ST_FR) - { + /* Frame received. */ + if ((status & SCB_ST_FR) == SCB_ST_FR) { #ifdef DEBUG_INTERRUPT_INFO - printk(KERN_DEBUG "%s: wavelan_interrupt(): received packet.\n", - dev->name); + printk(KERN_DEBUG + "%s: wavelan_interrupt(): received packet.\n", + dev->name); #endif - wv_receive(dev); - } + wv_receive(dev); + } - /* Check the state of the command unit. */ - if(((status & SCB_ST_CNA) == SCB_ST_CNA) || - (((status & SCB_ST_CUS) != SCB_ST_CUS_ACTV) && dev->start)) - { + /* Check the state of the command unit. */ + if (((status & SCB_ST_CNA) == SCB_ST_CNA) || + (((status & SCB_ST_CUS) != SCB_ST_CUS_ACTV) && test_bit(LINK_STATE_START, &dev->state))) { #ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wavelan_interrupt(): CU inactive -- restarting\n", - dev->name); + printk(KERN_INFO + "%s: wavelan_interrupt(): CU inactive -- restarting\n", + dev->name); #endif - wv_hw_reset(dev); - } + wv_hw_reset(dev); + } - /* Check the state of the command unit. */ - if(((status & SCB_ST_RNR) == SCB_ST_RNR) || - (((status & SCB_ST_RUS) != SCB_ST_RUS_RDY) && dev->start)) - { + /* Check the state of the command unit. */ + if (((status & SCB_ST_RNR) == SCB_ST_RNR) || + (((status & SCB_ST_RUS) != SCB_ST_RUS_RDY) && test_bit(LINK_STATE_START, &dev->state))) { #ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wavelan_interrupt(): RU not ready -- restarting\n", - dev->name); + printk(KERN_INFO + "%s: wavelan_interrupt(): RU not ready -- restarting\n", + dev->name); #endif - wv_hw_reset(dev); - } - - dev->interrupt = 0; + wv_hw_reset(dev); + } #ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name); + printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name); #endif } @@ -3838,83 +3749,81 @@ wavelan_interrupt(int irq, * way because the overhead of add_timer() and del_timer() is nothing * and because it avoids calling the watchdog, saving some CPU. */ -static void -wavelan_watchdog(u_long a) +static void wavelan_watchdog(unsigned long a) { - device * dev; - net_local * lp; - u_long ioaddr; - unsigned long x; - unsigned int nreaped; + device *dev; + net_local *lp; + unsigned long ioaddr; + unsigned long flags; + unsigned int nreaped; - dev = (device *) a; - ioaddr = dev->base_addr; - lp = (net_local *) dev->priv; + dev = (device *) a; + ioaddr = dev->base_addr; + lp = (net_local *) dev->priv; #ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: ->wavelan_watchdog()\n", dev->name); + printk(KERN_DEBUG "%s: ->wavelan_watchdog()\n", dev->name); #endif #ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wavelan_watchdog: watchdog timer expired\n", - dev->name); + printk(KERN_INFO "%s: wavelan_watchdog: watchdog timer expired\n", + dev->name); #endif - x = wv_splhi(); - - dev = (device *) a; - ioaddr = dev->base_addr; - lp = (net_local *) dev->priv; + save_flags(flags); + cli(); + + dev = (device *) a; + ioaddr = dev->base_addr; + lp = (net_local *) dev->priv; - if(lp->tx_n_in_use <= 0) - { - wv_splx(x); - return; - } + if (lp->tx_n_in_use <= 0) { + restore_flags(flags); + return; + } - nreaped = wv_complete(dev, ioaddr, lp); + nreaped = wv_complete(dev, ioaddr, lp); #ifdef DEBUG_INTERRUPT_INFO - printk(KERN_DEBUG "%s: wavelan_watchdog(): %d reaped, %d remain.\n", - dev->name, nreaped, lp->tx_n_in_use); + printk(KERN_DEBUG + "%s: wavelan_watchdog(): %d reaped, %d remain.\n", + dev->name, nreaped, lp->tx_n_in_use); #endif #ifdef DEBUG_PSA_SHOW - { - psa_t psa; - psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa)); - wv_psa_show(&psa); - } + { + psa_t psa; + psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa)); + wv_psa_show(&psa); + } #endif #ifdef DEBUG_MMC_SHOW - wv_mmc_show(dev); + wv_mmc_show(dev); #endif #ifdef DEBUG_I82586_SHOW - wv_cu_show(dev); + wv_cu_show(dev); #endif - /* If no buffer has been freed */ - if(nreaped == 0) - { + /* If no buffer has been freed */ + if (nreaped == 0) { #ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wavelan_watchdog(): cleanup failed, trying reset\n", - dev->name); + printk(KERN_INFO + "%s: wavelan_watchdog(): cleanup failed, trying reset\n", + dev->name); #endif - wv_hw_reset(dev); - } - else - /* Reset watchdog for next transmission. */ - if(lp->tx_n_in_use > 0) - { - /* set timer to expire in WATCHDOG_JIFFIES */ - lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES; - add_timer(&lp->watchdog); - } - - wv_splx(x); + wv_hw_reset(dev); + } else + /* Reset watchdog for next transmission. */ + if (lp->tx_n_in_use > 0) { + /* set timer to expire in WATCHDOG_JIFFIES */ + lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES; + add_timer(&lp->watchdog); + } + restore_flags(flags); + #ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name); + printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name); #endif } @@ -3930,56 +3839,55 @@ wavelan_watchdog(u_long a) * Configure and start up the WaveLAN PCMCIA adaptor. * Called by NET3 when it "opens" the device. */ -static int -wavelan_open(device * dev) +static int wavelan_open(device * dev) { - u_long x; + unsigned long flags; #ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: ->wavelan_open(dev=0x%x)\n", dev->name, - (unsigned int) dev); + printk(KERN_DEBUG "%s: ->wavelan_open(dev=0x%x)\n", dev->name, + (unsigned int) dev); #endif - /* Check irq */ - if(dev->irq == 0) - { + /* Check irq */ + if (dev->irq == 0) { #ifdef DEBUG_CONFIG_ERROR - printk(KERN_WARNING "%s: wavelan_open(): no IRQ\n", dev->name); + printk(KERN_WARNING "%s: wavelan_open(): no IRQ\n", + dev->name); #endif - return -ENXIO; - } + return -ENXIO; + } - if(request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN", dev) != 0) - { + if (request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN", dev) != 0) + { #ifdef DEBUG_CONFIG_ERROR - printk(KERN_WARNING "%s: wavelan_open(): invalid IRQ\n", dev->name); + printk(KERN_WARNING "%s: wavelan_open(): invalid IRQ\n", + dev->name); #endif - return -EAGAIN; - } - - x = wv_splhi(); - if(wv_hw_reset(dev) != -1) - { - dev->interrupt = 0; - dev->start = 1; - } - else - { - free_irq(dev->irq, dev); + return -EAGAIN; + } + + save_flags(flags); + cli(); + + if (wv_hw_reset(dev) != -1) { + netif_start_queue(dev); + } else { + free_irq(dev->irq, dev); #ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO "%s: wavelan_open(): impossible to start the card\n", - dev->name); + printk(KERN_INFO + "%s: wavelan_open(): impossible to start the card\n", + dev->name); #endif - return -EAGAIN; - } - wv_splx(x); - - MOD_INC_USE_COUNT; + return -EAGAIN; + } + restore_flags(flags); + + MOD_INC_USE_COUNT; #ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: <-wavelan_open()\n", dev->name); + printk(KERN_DEBUG "%s: <-wavelan_open()\n", dev->name); #endif - return 0; + return 0; } /*------------------------------------------------------------------*/ @@ -3987,40 +3895,34 @@ wavelan_open(device * dev) * Shut down the WaveLAN ISA card. * Called by NET3 when it "closes" the device. */ -static int -wavelan_close(device * dev) +static int wavelan_close(device * dev) { - net_local * lp = (net_local *)dev->priv; + net_local *lp = (net_local *) dev->priv; #ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: ->wavelan_close(dev=0x%x)\n", dev->name, - (unsigned int) dev); + printk(KERN_DEBUG "%s: ->wavelan_close(dev=0x%x)\n", dev->name, + (unsigned int) dev); #endif - /* Don't do the job twice. */ - if(dev->start == 0) - return 0; - - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue(dev); - /* If watchdog was activated, kill it! */ - if(lp->watchdog.prev != (timer_list *) NULL) - del_timer(&lp->watchdog); + /* If watchdog was activated, kill it! */ + if (lp->watchdog.prev != (timer_list *) NULL) + del_timer(&lp->watchdog); - /* - * Flush the Tx and disable Rx. - */ - wv_82586_stop(dev); + /* + * Flush the Tx and disable Rx. + */ + wv_82586_stop(dev); - free_irq(dev->irq, dev); + free_irq(dev->irq, dev); - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; #ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: <-wavelan_close()\n", dev->name); + printk(KERN_DEBUG "%s: <-wavelan_close()\n", dev->name); #endif - return 0; + return 0; } /*------------------------------------------------------------------*/ @@ -4029,113 +3931,111 @@ wavelan_close(device * dev) * device structure * (called by wavelan_probe() and via init_module()). */ -static int __init -wavelan_config(device * dev) +static int __init wavelan_config(device * dev) { - u_long ioaddr = dev->base_addr; - u_char irq_mask; - int irq; - net_local * lp; + unsigned long ioaddr = dev->base_addr; + u8 irq_mask; + int irq; + net_local *lp; #ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: ->wavelan_config(dev=0x%x, ioaddr=0x%x)\n", dev->name, - (unsigned int)dev, ioaddr); + printk(KERN_DEBUG "%s: ->wavelan_config(dev=0x%x, ioaddr=0x%x)\n", + dev->name, (unsigned int) dev, ioaddr); #endif - /* Check IRQ argument on command line. */ - if(dev->irq != 0) - { - irq_mask = wv_irq_to_psa(dev->irq); + /* Check IRQ argument on command line. */ + if (dev->irq != 0) { + irq_mask = wv_irq_to_psa(dev->irq); - if(irq_mask == 0) - { + if (irq_mask == 0) { #ifdef DEBUG_CONFIG_ERROR - printk(KERN_WARNING "%s: wavelan_config(): invalid IRQ %d ignored.\n", - dev->name, dev->irq); + printk(KERN_WARNING + "%s: wavelan_config(): invalid IRQ %d ignored.\n", + dev->name, dev->irq); #endif - dev->irq = 0; - } - else - { + dev->irq = 0; + } else { #ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "%s: wavelan_config(): changing IRQ to %d\n", - dev->name, dev->irq); + printk(KERN_DEBUG + "%s: wavelan_config(): changing IRQ to %d\n", + dev->name, dev->irq); #endif - psa_write(ioaddr, HACR_DEFAULT, - psaoff(0, psa_int_req_no), &irq_mask, 1); - /* update the Wavelan checksum */ - update_psa_checksum(dev, ioaddr, HACR_DEFAULT); - wv_hacr_reset(ioaddr); + psa_write(ioaddr, HACR_DEFAULT, + psaoff(0, psa_int_req_no), &irq_mask, 1); + /* update the Wavelan checksum */ + update_psa_checksum(dev, ioaddr, HACR_DEFAULT); + wv_hacr_reset(ioaddr); + } } - } - psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_int_req_no), &irq_mask, 1); - if((irq = wv_psa_to_irq(irq_mask)) == -1) - { + psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_int_req_no), + &irq_mask, 1); + if ((irq = wv_psa_to_irq(irq_mask)) == -1) { #ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO "%s: wavelan_config(): could not wavelan_map_irq(%d).\n", - dev->name, irq_mask); + printk(KERN_INFO + "%s: wavelan_config(): could not wavelan_map_irq(%d).\n", + dev->name, irq_mask); #endif - return EAGAIN; - } - - dev->irq = irq; - - request_region(ioaddr, sizeof(ha_t), "wavelan"); - - dev->mem_start = 0x0000; - dev->mem_end = 0x0000; - dev->if_port = 0; - - /* Initialize device structures */ - dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL); - if(dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0x00, sizeof(net_local)); - lp = (net_local *)dev->priv; - - /* Back link to the device structure. */ - lp->dev = dev; - /* Add the device at the beginning of the linked list. */ - lp->next = wavelan_list; - wavelan_list = lp; - - lp->hacr = HACR_DEFAULT; - - lp->watchdog.function = wavelan_watchdog; - lp->watchdog.data = (unsigned long) dev; - lp->promiscuous = 0; - lp->mc_count = 0; - - /* - * Fill in the fields of the device structure - * with generic Ethernet values. - */ - ether_setup(dev); - - dev->open = wavelan_open; - dev->stop = wavelan_close; - dev->hard_start_xmit = wavelan_packet_xmit; - dev->get_stats = wavelan_get_stats; - dev->set_multicast_list = &wavelan_set_multicast_list; + return EAGAIN; + } + + dev->irq = irq; + + request_region(ioaddr, sizeof(ha_t), "wavelan"); + + dev->mem_start = 0x0000; + dev->mem_end = 0x0000; + dev->if_port = 0; + + /* Initialize device structures */ + dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + memset(dev->priv, 0x00, sizeof(net_local)); + lp = (net_local *) dev->priv; + + /* Back link to the device structure. */ + lp->dev = dev; + /* Add the device at the beginning of the linked list. */ + lp->next = wavelan_list; + wavelan_list = lp; + + lp->hacr = HACR_DEFAULT; + + lp->watchdog.function = wavelan_watchdog; + lp->watchdog.data = (unsigned long) dev; + lp->promiscuous = 0; + lp->mc_count = 0; + + /* + * Fill in the fields of the device structure + * with generic Ethernet values. + */ + ether_setup(dev); + + dev->open = wavelan_open; + dev->stop = wavelan_close; + dev->hard_start_xmit = wavelan_packet_xmit; + dev->get_stats = wavelan_get_stats; + dev->set_multicast_list = &wavelan_set_multicast_list; #ifdef SET_MAC_ADDRESS - dev->set_mac_address = &wavelan_set_mac_address; -#endif /* SET_MAC_ADDRESS */ + dev->set_mac_address = &wavelan_set_mac_address; +#endif /* SET_MAC_ADDRESS */ -#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */ - dev->do_ioctl = wavelan_ioctl; - dev->get_wireless_stats = wavelan_get_wireless_stats; +#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */ + dev->do_ioctl = wavelan_ioctl; + dev->get_wireless_stats = wavelan_get_wireless_stats; #endif - dev->mtu = WAVELAN_MTU; + dev->mtu = WAVELAN_MTU; - /* Display nice information. */ - wv_init_info(dev); + /* Display nice information. */ + wv_init_info(dev); #ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: <-wavelan_config()\n", dev->name); + printk(KERN_DEBUG "%s: <-wavelan_config()\n", dev->name); #endif - return 0; + return 0; } /*------------------------------------------------------------------*/ @@ -4146,90 +4046,88 @@ wavelan_config(device * dev) * We follow the example in drivers/net/ne.c. * (called in "Space.c") */ -int __init -wavelan_probe(device * dev) +int __init wavelan_probe(device * dev) { - short base_addr; - mac_addr mac; /* MAC address (check existence of WaveLAN) */ - int i; - int r; + short base_addr; + mac_addr mac; /* MAC address (check existence of WaveLAN) */ + int i; + int r; #ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: ->wavelan_probe(dev=0x%x (base_addr=0x%x))\n", - dev->name, (unsigned int)dev, (unsigned int)dev->base_addr); + printk(KERN_DEBUG + "%s: ->wavelan_probe(dev=0x%x (base_addr=0x%x))\n", + dev->name, (unsigned int) dev, + (unsigned int) dev->base_addr); #endif #ifdef STRUCT_CHECK - if (wv_struct_check() != (char *) NULL) - { - printk(KERN_WARNING "%s: wavelan_probe(): structure/compiler botch: \"%s\"\n", - dev->name, wv_struct_check()); - return ENODEV; - } -#endif /* STRUCT_CHECK */ - - /* Check the value of the command line parameter for base address. */ - base_addr = dev->base_addr; - - /* Don't probe at all. */ - if(base_addr < 0) - { + if (wv_struct_check() != (char *) NULL) { + printk(KERN_WARNING + "%s: wavelan_probe(): structure/compiler botch: \"%s\"\n", + dev->name, wv_struct_check()); + return ENODEV; + } +#endif /* STRUCT_CHECK */ + + /* Check the value of the command line parameter for base address. */ + base_addr = dev->base_addr; + + /* Don't probe at all. */ + if (base_addr < 0) { #ifdef DEBUG_CONFIG_ERROR - printk(KERN_WARNING "%s: wavelan_probe(): invalid base address\n", - dev->name); + printk(KERN_WARNING + "%s: wavelan_probe(): invalid base address\n", + dev->name); #endif - return ENXIO; - } - - /* Check a single specified location. */ - if(base_addr > 0x100) - { - /* Check if there is something at this base address */ - if((r = wv_check_ioaddr(base_addr, mac)) == 0) - { - memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */ - r = wavelan_config(dev); + return ENXIO; } + /* Check a single specified location. */ + if (base_addr > 0x100) { + /* Check if there is something at this base address */ + if ((r = wv_check_ioaddr(base_addr, mac)) == 0) { + memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */ + r = wavelan_config(dev); + } #ifdef DEBUG_CONFIG_INFO - if(r != 0) - printk(KERN_DEBUG "%s: wavelan_probe(): no device at specified base address (0x%X) or address already in use\n", - dev->name, base_addr); + if (r != 0) + printk(KERN_DEBUG + "%s: wavelan_probe(): no device at specified base address (0x%X) or address already in use\n", + dev->name, base_addr); #endif #ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name); + printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name); #endif - return r; - } - - /* Scan all possible addresses of the WaveLAN hardware. */ - for(i = 0; i < NELS(iobase); i++) - { - /* Check whether there is something at this base address. */ - if(wv_check_ioaddr(iobase[i], mac) == 0) - { - dev->base_addr = iobase[i]; /* Copy base address. */ - memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */ - if(wavelan_config(dev) == 0) - { + return r; + } + + /* Scan all possible addresses of the WaveLAN hardware. */ + for (i = 0; i < NELS(iobase); i++) { + /* Check whether there is something at this base address. */ + if (wv_check_ioaddr(iobase[i], mac) == 0) { + dev->base_addr = iobase[i]; /* Copy base address. */ + memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */ + if (wavelan_config(dev) == 0) { #ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name); + printk(KERN_DEBUG + "%s: <-wavelan_probe()\n", + dev->name); #endif - return 0; - } + return 0; + } + } } - } - /* We may have touched base_addr. Another driver may not like it. */ - dev->base_addr = base_addr; + /* We may have touched base_addr. Another driver may not like it. */ + dev->base_addr = base_addr; #ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "%s: wavelan_probe(): no device found\n", - dev->name); + printk(KERN_DEBUG "%s: wavelan_probe(): no device found\n", + dev->name); #endif - return ENODEV; + return ENODEV; } /****************************** MODULE ******************************/ @@ -4243,120 +4141,115 @@ wavelan_probe(device * dev) * Insertion of the module * I'm now quite proud of the multi-device support. */ -int -init_module(void) +int init_module(void) { - mac_addr mac; /* MAC address (check WaveLAN existence) */ - int ret = -EIO; /* Return error if no cards found */ - int i; + mac_addr mac; /* MAC address (check WaveLAN existence) */ + int ret = -EIO; /* Return error if no cards found */ + int i; #ifdef DEBUG_MODULE_TRACE - printk(KERN_DEBUG "-> init_module()\n"); + printk(KERN_DEBUG "-> init_module()\n"); #endif - /* If probing is asked */ - if(io[0] == 0) - { + /* If probing is asked */ + if (io[0] == 0) { #ifdef DEBUG_CONFIG_ERROR - printk(KERN_WARNING "WaveLAN init_module(): doing device probing (bad !)\n"); - printk(KERN_WARNING "Specify base addresses while loading module to correct the problem\n"); + printk(KERN_WARNING + "WaveLAN init_module(): doing device probing (bad !)\n"); + printk(KERN_WARNING + "Specify base addresses while loading module to correct the problem\n"); #endif - /* Copy the basic set of address to be probed. */ - for(i = 0; i < NELS(iobase); i++) - io[i] = iobase[i]; - } + /* Copy the basic set of address to be probed. */ + for (i = 0; i < NELS(iobase); i++) + io[i] = iobase[i]; + } - /* Loop on all possible base addresses. */ - i = -1; - while((io[++i] != 0) && (i < NELS(io))) - { - /* Check if there is something at this base address. */ - if(wv_check_ioaddr(io[i], mac) == 0) - { - device * dev; - - /* Create device and set basic arguments. */ - dev = kmalloc(sizeof(struct net_device), GFP_KERNEL); - if(dev==NULL) - { - ret = -ENOMEM; - break; - } - memset(dev, 0x00, sizeof(struct net_device)); - dev->name = name[i]; - dev->base_addr = io[i]; - dev->irq = irq[i]; - dev->init = &wavelan_config; - memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */ - - /* Try to create the device. */ - if(register_netdev(dev) != 0) - { - /* Deallocate everything. */ - /* Note: if dev->priv is mallocated, there is no way to fail. */ - kfree_s(dev, sizeof(struct net_device)); - } - else - { - /* If at least one device OK, we do not fail */ - ret = 0; - } - } /* if there is something at the address */ - } /* Loop on all addresses. */ + /* Loop on all possible base addresses. */ + i = -1; + while ((io[++i] != 0) && (i < NELS(io))) { + /* Check if there is something at this base address. */ + if (wv_check_ioaddr(io[i], mac) == 0) { + device *dev; + + /* Create device and set basic arguments. */ + dev = + kmalloc(sizeof(struct net_device), GFP_KERNEL); + if (dev == NULL) { + ret = -ENOMEM; + break; + } + memset(dev, 0x00, sizeof(struct net_device)); + dev->name = name[i]; + dev->base_addr = io[i]; + dev->irq = irq[i]; + dev->init = &wavelan_config; + memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */ + + /* Try to create the device. */ + if (register_netdev(dev) != 0) { + /* Deallocate everything. */ + /* Note: if dev->priv is mallocated, there is no way to fail. */ + kfree_s(dev, sizeof(struct net_device)); + } else { + /* If at least one device OK, we do not fail */ + ret = 0; + } + } /* if there is something at the address */ + } /* Loop on all addresses. */ #ifdef DEBUG_CONFIG_ERROR - if(wavelan_list == (net_local *) NULL) - printk(KERN_WARNING "WaveLAN init_module(): no device found\n"); + if (wavelan_list == (net_local *) NULL) + printk(KERN_WARNING + "WaveLAN init_module(): no device found\n"); #endif #ifdef DEBUG_MODULE_TRACE - printk(KERN_DEBUG "<- init_module()\n"); + printk(KERN_DEBUG "<- init_module()\n"); #endif - return ret; + return ret; } /*------------------------------------------------------------------*/ /* * Removal of the module */ -void -cleanup_module(void) +void cleanup_module(void) { #ifdef DEBUG_MODULE_TRACE - printk(KERN_DEBUG "-> cleanup_module()\n"); + printk(KERN_DEBUG "-> cleanup_module()\n"); #endif - /* Loop on all devices and release them. */ - while(wavelan_list != (net_local *) NULL) - { - device * dev = wavelan_list->dev; + /* Loop on all devices and release them. */ + while (wavelan_list != (net_local *) NULL) { + device *dev = wavelan_list->dev; #ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "%s: cleanup_module(): removing device at 0x%x\n", - dev->name, (unsigned int) dev); + printk(KERN_DEBUG + "%s: cleanup_module(): removing device at 0x%x\n", + dev->name, (unsigned int) dev); #endif - /* Release the ioport region. */ - release_region(dev->base_addr, sizeof(ha_t)); + /* Release the ioport region. */ + release_region(dev->base_addr, sizeof(ha_t)); - /* Definitely remove the device. */ - unregister_netdev(dev); + /* Definitely remove the device. */ + unregister_netdev(dev); - /* Unlink the device. */ - wavelan_list = wavelan_list->next; + /* Unlink the device. */ + wavelan_list = wavelan_list->next; - /* Free pieces. */ - kfree_s(dev->priv, sizeof(struct net_local)); - kfree_s(dev, sizeof(struct net_device)); - } + /* Free pieces. */ + kfree_s(dev->priv, sizeof(struct net_local)); + kfree_s(dev, sizeof(struct net_device)); + } #ifdef DEBUG_MODULE_TRACE - printk(KERN_DEBUG "<- cleanup_module()\n"); + printk(KERN_DEBUG "<- cleanup_module()\n"); #endif } -#endif /* MODULE */ +#endif /* MODULE */ /* * This software may only be used and distributed @@ -4379,7 +4272,7 @@ cleanup_module(void) * * Thanks go also to: * James Ashton (jaa101@syseng.anu.edu.au), - * Alan Cox (iialan@iiit.swan.ac.uk), + * Alan Cox (alan@redhat.com), * Allan Creighton (allanc@cs.usyd.edu.au), * Matthew Geier (matthew@cs.usyd.edu.au), * Remo di Giovanni (remo@cs.usyd.edu.au), diff --git a/drivers/net/znet.c b/drivers/net/znet.c index f48e41e7ed68..7ca88c26a6a7 100644 --- a/drivers/net/znet.c +++ b/drivers/net/znet.c @@ -119,10 +119,13 @@ static unsigned int znet_debug = ZNET_DEBUG; #define CMD0_STAT2 (2 << 5) #define CMD0_STAT3 (3 << 5) +#define TX_TIMEOUT 10 + #define net_local znet_private struct znet_private { int rx_dma, tx_dma; struct net_device_stats stats; + spinlock_t lock; /* The starting, current, and end pointers for the packet buffers. */ ushort *rx_start, *rx_cur, *rx_end; ushort *tx_start, *tx_cur, *tx_end; @@ -190,6 +193,7 @@ static struct net_device_stats *net_get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); static void hardware_init(struct net_device *dev); static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset); +static void znet_tx_timeout (struct net_device *dev); #ifdef notdef static struct sigaction znet_sigaction = { &znet_interrupt, 0, 0, NULL, }; @@ -245,6 +249,7 @@ int __init znet_probe(struct net_device *dev) dev->priv = (void *) &zn; zn.rx_dma = netinfo->dma1; zn.tx_dma = netinfo->dma2; + zn.lock = SPIN_LOCK_UNLOCKED; /* These should never fail. You can't add devices to a sealed box! */ if (request_irq(dev->irq, &znet_interrupt, 0, "ZNet", dev) @@ -275,6 +280,8 @@ int __init znet_probe(struct net_device *dev) dev->stop = &znet_close; dev->get_stats = net_get_stats; dev->set_multicast_list = &set_multicast_list; + dev->tx_timeout = znet_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; /* Fill in the 'dev' with ethernet-generic values. */ ether_setup(dev); @@ -306,41 +313,47 @@ static int znet_open(struct net_device *dev) printk(KERN_WARNING "%s: Problem turning on the transceiver power.\n", dev->name); - dev->tbusy = 0; - dev->interrupt = 0; hardware_init(dev); - dev->start = 1; + netif_start_queue (dev); return 0; } + +static void znet_tx_timeout (struct net_device *dev) +{ + int ioaddr = dev->base_addr; + ushort event, tx_status, rx_offset, state; + + outb (CMD0_STAT0, ioaddr); + event = inb (ioaddr); + outb (CMD0_STAT1, ioaddr); + tx_status = inw (ioaddr); + outb (CMD0_STAT2, ioaddr); + rx_offset = inw (ioaddr); + outb (CMD0_STAT3, ioaddr); + state = inb (ioaddr); + printk (KERN_WARNING "%s: transmit timed out, status %02x %04x %04x %02x," + " resetting.\n", dev->name, event, tx_status, rx_offset, state); + if (tx_status == 0x0400) + printk (KERN_WARNING "%s: Tx carrier error, check transceiver cable.\n", + dev->name); + outb (CMD0_RESET, ioaddr); + hardware_init (dev); + netif_start_queue (dev); +} + static int znet_send_packet(struct sk_buff *skb, struct net_device *dev) { int ioaddr = dev->base_addr; struct net_local *lp = (struct net_local *)dev->priv; + unsigned long flags; if (znet_debug > 4) - printk(KERN_DEBUG "%s: ZNet_send_packet(%ld).\n", dev->name, dev->tbusy); - - /* Transmitter timeout, likely just recovery after suspending the machine. */ - if (dev->tbusy) { - ushort event, tx_status, rx_offset, state; - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 10) - return 1; - outb(CMD0_STAT0, ioaddr); event = inb(ioaddr); - outb(CMD0_STAT1, ioaddr); tx_status = inw(ioaddr); - outb(CMD0_STAT2, ioaddr); rx_offset = inw(ioaddr); - outb(CMD0_STAT3, ioaddr); state = inb(ioaddr); - printk(KERN_WARNING "%s: transmit timed out, status %02x %04x %04x %02x," - " resetting.\n", dev->name, event, tx_status, rx_offset, state); - if (tx_status == 0x0400) - printk(KERN_WARNING "%s: Tx carrier error, check transceiver cable.\n", - dev->name); - outb(CMD0_RESET, ioaddr); - hardware_init(dev); - } + printk(KERN_DEBUG "%s: ZNet_send_packet.\n", dev->name); + netif_stop_queue (dev); + /* Check that the part hasn't reset itself, probably from suspend. */ outb(CMD0_STAT0, ioaddr); if (inw(ioaddr) == 0x0010 @@ -348,11 +361,7 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev) && inw(ioaddr) == 0x0010) hardware_init(dev); - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) - printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); - else { + if (1) { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = (void *)skb->data; ushort *tx_link = zn.tx_cur - 1; @@ -385,13 +394,18 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev) zn.tx_cur += rnd_len; } *zn.tx_cur++ = 0; - cli(); { + + spin_lock_irqsave(&lp->lock, flags); + { *tx_link = CMD0_TRANSMIT + CMD0_CHNL_1; /* Is this always safe to do? */ outb(CMD0_TRANSMIT + CMD0_CHNL_1,ioaddr); - } sti(); + } + spin_unlock_irqrestore (&lp->lock, flags); dev->trans_start = jiffies; + netif_start_queue (dev); + if (znet_debug > 4) printk(KERN_DEBUG "%s: Transmitter queued, length %d.\n", dev->name, length); } @@ -403,6 +417,7 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev) static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct net_device *dev = dev_id; + struct net_local *lp = (struct net_local *)dev->priv; int ioaddr; int boguscnt = 20; @@ -411,7 +426,8 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs) return; } - dev->interrupt = 1; + spin_lock (&lp->lock); + ioaddr = dev->base_addr; outb(CMD0_STAT0, ioaddr); @@ -432,7 +448,6 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs) break; if ((status & 0x0F) == 4) { /* Transmit done. */ - struct net_local *lp = (struct net_local *)dev->priv; int tx_status; outb(CMD0_STAT1, ioaddr); tx_status = inw(ioaddr); @@ -449,8 +464,7 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs) if ((tx_status | 0x0760) != 0x0760) lp->stats.tx_errors++; } - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ + netif_wake_queue (dev); } if ((status & 0x40) @@ -461,7 +475,8 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs) outb(CMD0_ACK,ioaddr); } while (boguscnt--); - dev->interrupt = 0; + spin_unlock (&lp->lock); + return; } @@ -594,8 +609,7 @@ static int znet_close(struct net_device *dev) unsigned long flags; int ioaddr = dev->base_addr; - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue (dev); outb(CMD0_RESET, ioaddr); /* CMD0_RESET */ @@ -728,7 +742,7 @@ static void hardware_init(struct net_device *dev) update_stop_hit(ioaddr, 8192); if (znet_debug > 1) printk("enabling Rx.\n"); outb(CMD0_Rx_ENABLE+CMD0_CHNL_0, ioaddr); - dev->tbusy = 0; + netif_start_queue (dev); } static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset) diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 543a98419ef1..e216ef03a0eb 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -182,6 +182,7 @@ END OF TERMS AND CONDITIONS - Initial Beta Release. *****************************************************************************/ + #ifdef MODULE #include #endif @@ -2789,7 +2790,7 @@ qla1280_setup_chip(scsi_qla_host_t *ha) DEBUG(sprintf(debug_buff,"qla1280_setup_chip: loading risc @ =(0x%p),%d,%d(0x%x).\n\r",risc_code_address,cnt,num,risc_address);) DEBUG(qla1280_print(debug_buff)); - printk("qla1280_setup_chip: loading risc @ =code=(0x%p),cnt=%d,seg=%d,addr=0x%x\n\r",risc_code_address,cnt,num,risc_address); + DEBUG(printk("qla1280_setup_chip: loading risc @ =code=(0x%p),cnt=%d,seg=%d,addr=0x%x\n\r",risc_code_address,cnt,num,risc_address)); BCOPY((caddr_t) risc_code_address,(caddr_t) ha->request_ring, (cnt <<1)); mb[0] = MBC_LOAD_RAM; /* mb[0] = MBC_LOAD_RAM_A64; */ @@ -2799,7 +2800,7 @@ qla1280_setup_chip(scsi_qla_host_t *ha) mb[2] = (uint16_t) (ha->request_dma >> 16) & 0xffff; mb[7] = (uint16_t) (MS_64BITS(ha->request_dma) & 0xffff); mb[6] = (uint16_t) (MS_64BITS(ha->request_dma) >> 16) & 0xffff; - printk("qla1280_setup_chip: op=%d 0x%lx = 0x%4x,0x%4x,0x%4x,0x%4x\n",mb[0],ha->request_dma,mb[6],mb[7],mb[2],mb[3]); + DEBUG(printk("qla1280_setup_chip: op=%d 0x%lx = 0x%4x,0x%4x,0x%4x,0x%4x\n",mb[0],ha->request_dma,mb[6],mb[7],mb[2],mb[3])); if( (status = qla1280_mailbox_command(ha, BIT_4|BIT_3|BIT_2|BIT_1|BIT_0, &mb[0])) ) { diff --git a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c index f0630dadaffd..1456858ee379 100644 --- a/drivers/scsi/qlogicisp.c +++ b/drivers/scsi/qlogicisp.c @@ -811,6 +811,7 @@ int isp1020_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *)) ds = cmd->dataseg; sg_count = pci_map_sg(hostdata->pci_dev, sg, Cmnd->use_sg); + Cmnd->use_sg = sg_count; cmd->segment_cnt = cpu_to_le16(sg_count); diff --git a/drivers/sound/dmasound.c b/drivers/sound/dmasound.c index ae627ed3b761..06be153261de 100644 --- a/drivers/sound/dmasound.c +++ b/drivers/sound/dmasound.c @@ -116,6 +116,7 @@ History: #include #include #include +#include #include "awacs_defs.h" #include #include @@ -178,6 +179,7 @@ static volatile struct dbdma_regs *awacs_txdma, *awacs_rxdma; static int awacs_rate_index; static int awacs_subframe; static int awacs_spkr_vol; +static struct device_node* awacs_node; static int awacs_revision; #define AWACS_BURGUNDY 100 /* fake revision # for burgundy */ @@ -898,7 +900,7 @@ static inline int ioctl_return(int *addr, int value) void dmasound_init(void); -void dmasound_setup(char *str, int *ints); +static int dmasound_setup(char *str); /*** Translations ************************************************************/ @@ -3208,9 +3210,15 @@ static void PMacIrqCleanup(void) out_le32(&awacs_txdma->control, RUN<<16); /* disable interrupts from awacs interface */ out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff); - free_irq(awacs_irq, pmac_awacs_intr); - free_irq(awacs_tx_irq, pmac_awacs_tx_intr); - free_irq(awacs_rx_irq, pmac_awacs_rx_intr); +#ifdef CONFIG_PMAC_PBOOK + if (is_pbook_G3) { + feature_clear(awacs_node, FEATURE_Sound_power); + feature_clear(awacs_node, FEATURE_Sound_CLK_enable); + } +#endif + free_irq(awacs_irq, 0); + free_irq(awacs_tx_irq, 0); + free_irq(awacs_rx_irq, 0); kfree(awacs_tx_cmd_space); if (awacs_rx_cmd_space) kfree(awacs_rx_cmd_space); @@ -3281,12 +3289,10 @@ static void PMacInit(void) /* We really want to execute a DMA stop command, after the AWACS * is initialized. * For reasons I don't understand, it stops the hissing noise - * common to many PowerBook G3 systems (like mine :-). Maybe it - * is just the AWACS control register change...... + * common to many PowerBook G3 systems (like mine :-). */ out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); st_le16(&beep_dbdma_cmd->command, DBDMA_STOP); - out_le32(&awacs->control, (in_le32(&awacs->control) & ~0x1f00)); out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd)); out_le32(&awacs_txdma->control, RUN | (RUN << 16)); @@ -3544,6 +3550,11 @@ static void awacs_nosound(unsigned long xx) save_flags(flags); cli(); if (beep_playing) { st_le16(&beep_dbdma_cmd->command, DBDMA_STOP); + out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + out_le32(&awacs->control, + (in_le32(&awacs->control) & ~0x1f00) + | (awacs_rate_index << 8)); + out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE); beep_playing = 0; } restore_flags(flags); @@ -3645,8 +3656,23 @@ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) PMacSilence(); disable_irq(awacs_irq); disable_irq(awacs_tx_irq); + if (is_pbook_G3) { + feature_clear(awacs_node, FEATURE_Sound_CLK_enable); + feature_clear(awacs_node, FEATURE_Sound_power); + } break; case PBOOK_WAKE: + /* There is still a problem on wake. Sound seems to work fine + if I launch mpg123 and resumes fine if mpg123 was playing, + but the console beep is dead until I do something with the + mixer. Probably yet another timing issue */ + if (!feature_test(awacs_node, FEATURE_Sound_CLK_enable) + || !feature_test(awacs_node, FEATURE_Sound_power)) { + /* these aren't present on the 3400 AFAIK -- paulus */ + feature_set(awacs_node, FEATURE_Sound_CLK_enable); + feature_set(awacs_node, FEATURE_Sound_power); + mdelay(1000); + } out_le32(&awacs->control, MASK_IEPC | (awacs_rate_index << 8) | 0x11 | (awacs_revision < AWACS_BURGUNDY? MASK_IEE: 0)); @@ -3663,6 +3689,16 @@ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) mdelay(2); awacs_write(awacs_reg[1] | MASK_ADDR1); } + /* enable CD sound input */ + if (macio_base && is_pbook_G3) { + out_8(macio_base + 0x37, 3); + } else if (is_pbook_3400) { + feature_set(awacs_node, FEATURE_IOBUS_enable); + udelay(10); + in_8((unsigned char *)0xf301a190); + } + /* Resume pending sounds. */ + PMacPlay(); } return PBOOK_SLEEP_OK; } @@ -5139,6 +5175,7 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long fmt; int data; int size, nbufs; + audio_buf_info info; switch (cmd) { case SNDCTL_DSP_RESET: @@ -5214,6 +5251,14 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, sq_setup(numBufs, size, sound_buffers); sq.max_active = nbufs; return 0; + case SNDCTL_DSP_GETOSPACE: + info.fragments = sq.max_active - sq.count; + info.fragstotal = sq.max_active; + info.fragsize = sq.block_size; + info.bytes = info.fragments * info.fragsize; + if (copy_to_user((void *)arg, &info, sizeof(info))) + return -EFAULT; + return 0; default: return mixer_ioctl(inode, file, cmd, arg); @@ -5308,7 +5353,7 @@ static int state_open(struct inode *inode, struct file *file) { char *buffer = state.buf, *mach = ""; #ifdef CONFIG_PPC - char awacs_buf[50]; + char awacs_buf[64]; #endif int len = 0; @@ -5576,6 +5621,16 @@ void __init dmasound_init(void) printk(KERN_ERR "DMA sound driver: Not enough buffer memory, driver disabled!\n"); return; } + awacs_node = np; +#ifdef CONFIG_PMAC_PBOOK + if (machine_is_compatible("PowerBook1,1") + || machine_is_compatible("AAPL,PowerBook1998")) { + feature_set(np, FEATURE_Sound_CLK_enable); + feature_set(np, FEATURE_Sound_power); + /* Shorter delay will not work */ + mdelay(1000); + } +#endif awacs_tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(awacs_tx_cmd_space); @@ -5607,7 +5662,10 @@ void __init dmasound_init(void) awacs_revision = (in_le32(&awacs->codec_stat) >> 12) & 0xf; if (awacs_revision == 3) { + mdelay(100); awacs_write(0x6000); + mdelay(2); + awacs_write(awacs_reg[1] + MASK_ADDR1); awacs_enable_amp(100 * 0x101); } } @@ -5629,26 +5687,34 @@ void __init dmasound_init(void) /* Powerbooks have odd ways of enabling inputs such as an expansion-bay CD or sound from an internal modem or a PC-card modem. */ - if (machine_is_compatible("AAPL,3400/2400")) { + if (machine_is_compatible("AAPL,3400/2400") + || machine_is_compatible("AAPL,3500")) { is_pbook_3400 = 1; /* * Enable CD and PC-card sound inputs. * This is done by reading from address * f301a000, + 0x10 to enable the expansion-bay * CD sound input, + 0x80 to enable the PC-card - * sound input. The 0x100 seems to enable the - * MESH and/or its SCSI bus drivers. + * sound input. The 0x100 enables the SCSI bus + * terminator power. */ in_8((unsigned char *)0xf301a190); - } else if (machine_is_compatible("PowerBook1,1")) { - np = find_devices("mac-io"); - if (np && np->n_addrs > 0) { - is_pbook_G3 = 1; - macio_base = (unsigned char *) - ioremap(np->addrs[0].address, 0x40); - /* enable CD sound input */ - out_8(macio_base + 0x37, 3); + } else if (machine_is_compatible("PowerBook1,1") + || machine_is_compatible("AAPL,PowerBook1998")) { + struct device_node* mio; + macio_base = 0; + is_pbook_G3 = 1; + for (mio = np->parent; mio; mio = mio->parent) { + if (strcmp(mio->name, "mac-io") == 0 + && mio->n_addrs > 0) { + macio_base = (unsigned char *) ioremap + (mio->addrs[0].address, 0x40); + break; + } } + /* enable CD sound input */ + if (macio_base) + out_8(macio_base + 0x37, 3); } } #endif /* CONFIG_PPC */ diff --git a/drivers/usb/keybdev.c b/drivers/usb/keybdev.c index c157e62f7aba..b2fd41ca49c3 100644 --- a/drivers/usb/keybdev.c +++ b/drivers/usb/keybdev.c @@ -36,7 +36,7 @@ #include #include -#ifdef CONFIG_X86 +#if defined(CONFIG_X86) || defined(CONFIG_IA64) static unsigned char keybdev_x86_e0s[] = { 0x1c, 0x1d, 0x35, 0x2a, 0x38, 0x39, 0x47, 0x48, @@ -77,7 +77,7 @@ void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int { if (type != EV_KEY || code > 255) return; -#ifdef CONFIG_X86 +#if defined(CONFIG_X86) || defined(CONFIG_IA64) if (code >= 189) { printk(KERN_WARNING "keybdev.c: can't emulate keycode %d\n", code); diff --git a/drivers/video/aty128fb.c b/drivers/video/aty128fb.c index cfd83644f18f..cc806fbce3a9 100644 --- a/drivers/video/aty128fb.c +++ b/drivers/video/aty128fb.c @@ -1675,9 +1675,9 @@ aty128_init(struct fb_info_aty128 *info, const char *name) #endif /* CONFIG_PPC */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,1) - if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, - &defaultmode, 8)) - var = default_var; + if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, + &defaultmode, 8)) + var = default_var; #endif #ifdef CONFIG_PPC @@ -1685,6 +1685,7 @@ aty128_init(struct fb_info_aty128 *info, const char *name) if (mac_vmode_to_var(default_vmode, default_cmode, &var)) var = default_var; #endif /* CONFIG_PPC */ + } #endif /* MODULE */ if (noaccel) diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c index a132dada1b07..57ae6e15ebcf 100644 --- a/drivers/video/atyfb.c +++ b/drivers/video/atyfb.c @@ -1,4 +1,4 @@ -/* $Id: atyfb.c,v 1.138 2000/02/10 02:52:12 davem Exp $ +/* $Id: atyfb.c,v 1.139 2000/02/12 22:47:04 davem Exp $ * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64 * * Copyright (C) 1997-1998 Geert Uytterhoeven diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index eb3a6df36f48..d462fb621ac8 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c @@ -713,8 +713,8 @@ int __init igafb_init(void) info->mmap_map = kmalloc(4 * sizeof(*info->mmap_map), GFP_ATOMIC); if (!info->mmap_map) { printk("igafb_init: can't alloc mmap_map\n"); - iounmap(info->io_base); - iounmap((void *)info->frame_buffer); + iounmap((void *)info->io_base); + iounmap(info->frame_buffer); kfree(info); return -ENOMEM; } @@ -768,8 +768,8 @@ int __init igafb_init(void) #endif if (!iga_init(info)) { - iounmap(info->io_base); - iounmap((void *)info->frame_buffer); + iounmap((void *)info->io_base); + iounmap(info->frame_buffer); if (info->mmap_map) kfree(info->mmap_map); kfree(info); diff --git a/fs/Config.in b/fs/Config.in index 934a7a70aaec..07b80515cdcc 100644 --- a/fs/Config.in +++ b/fs/Config.in @@ -60,7 +60,9 @@ tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS dep_bool ' SYSV filesystem write support (DANGEROUS)' CONFIG_SYSV_FS_WRITE $CONFIG_SYSV_FS $CONFIG_EXPERIMENTAL tristate 'UDF filesystem support (read only)' CONFIG_UDF_FS -dep_bool ' UDF write support (DANGEROUS)' CONFIG_UDF_RW $CONFIG_UDF_FS $CONFIG_EXPERIMENTAL +if [ "$CONFIG_UDF_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then + dep_bool ' UDF write support (DANGEROUS)' CONFIG_UDF_RW +fi tristate 'UFS filesystem support (read only)' CONFIG_UFS_FS dep_bool ' UFS filesystem write support (DANGEROUS)' CONFIG_UFS_FS_WRITE $CONFIG_UFS_FS $CONFIG_EXPERIMENTAL diff --git a/fs/adfs/file.c b/fs/adfs/file.c index a2f105b06d85..0d5f4346e2b6 100644 --- a/fs/adfs/file.c +++ b/fs/adfs/file.c @@ -44,4 +44,8 @@ static struct file_operations adfs_file_operations = { struct inode_operations adfs_file_inode_operations = { &adfs_file_operations, /* default file operations */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) + readpage: generic_readpage, + bmap: adfs_bmap, +#endif }; diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index 30398d62f9c8..96b3370ff4e0 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c @@ -48,30 +48,36 @@ abort_negative: abort_toobig: return 0; } + static int adfs_writepage(struct dentry *dentry, struct page *page) { - return block_write_full_page(page,adfs_get_block); + return block_write_full_page(page, adfs_get_block); } + static int adfs_readpage(struct dentry *dentry, struct page *page) { - return block_read_full_page(page,adfs_get_block); + return block_read_full_page(page, adfs_get_block); } -static int adfs_prepare_write(struct page *page, unsigned from, unsigned to) + +static int adfs_prepare_write(struct page *page, unsigned int from, unsigned int to) { - return cont_prepare_write(page,from,to,adfs_get_block, - &((struct inode*)page->mapping->host)->u.adfs_i.mmu_private); + return cont_prepare_write(page, from, to, adfs_get_block, + &((struct inode *)page->mapping->host)->u.adfs_i.mmu_private); } + static int _adfs_bmap(struct address_space *mapping, long block) { - return generic_block_bmap(mapping,block,adfs_get_block); + return generic_block_bmap(mapping, block, adfs_get_block); } -struct address_space_operations adfs_aops = { - readpage: adfs_readpage, - writepage: adfs_writepage, - prepare_write: adfs_prepare_write, - commit_write: generic_commit_write, - bmap: _adfs_bmap + +static struct address_space_operations adfs_aops = { + readpage: adfs_readpage, + writepage: adfs_writepage, + prepare_write: adfs_prepare_write, + commit_write: generic_commit_write, + bmap: _adfs_bmap }; + #else int adfs_bmap(struct inode *inode, int block) { @@ -280,7 +286,7 @@ adfs_iget(struct super_block *sb, struct object_info *obj) if (S_ISDIR(inode->i_mode)) inode->i_op = &adfs_dir_inode_operations; else if (S_ISREG(inode->i_mode)) { - inode->i_op = &adfs_file_inode_operations; + inode->i_op = &adfs_file_inode_operations; inode->i_mapping->a_ops = &adfs_aops; inode->u.adfs_i.mmu_private = inode->i_size; } diff --git a/fs/adfs/map.c b/fs/adfs/map.c index 0fde11f5da95..0c6507411ab9 100644 --- a/fs/adfs/map.c +++ b/fs/adfs/map.c @@ -44,7 +44,6 @@ lookup_zone(const struct adfs_discmap *dm, const unsigned int idlen, /* * get fragment id */ - //asm("@ get fragment id start"); { unsigned long v2; unsigned int tmp; @@ -60,14 +59,12 @@ lookup_zone(const struct adfs_discmap *dm, const unsigned int idlen, frag &= idmask; } - //asm("@ get fragment id end"); mapptr = start + idlen; /* * find end of fragment */ - //asm("@ find end of fragment start"); { unsigned long v2; @@ -79,7 +76,6 @@ lookup_zone(const struct adfs_discmap *dm, const unsigned int idlen, mapptr += 1 + ffz(~v2); } - //asm("@ find end of fragment end"); if (frag == frag_id) goto found; @@ -122,7 +118,6 @@ scan_free_map(struct adfs_sb_info *asb, struct adfs_discmap *dm) /* * get fragment id */ - //asm("@ get fragment id start"); { unsigned long v2; unsigned int tmp; @@ -138,7 +133,6 @@ scan_free_map(struct adfs_sb_info *asb, struct adfs_discmap *dm) frag &= idmask; } - //asm("@ get fragment id end"); /* * If the freelink is null, then no free fragments @@ -153,7 +147,6 @@ scan_free_map(struct adfs_sb_info *asb, struct adfs_discmap *dm) /* * get fragment id */ - //asm("@ get fragment id start"); { unsigned long v2; unsigned int tmp; @@ -169,14 +162,12 @@ scan_free_map(struct adfs_sb_info *asb, struct adfs_discmap *dm) frag &= idmask; } - //asm("@ get fragment id end"); mapptr = start + idlen; /* * find end of fragment */ - //asm("@ find end of fragment start"); { unsigned long v2; @@ -188,7 +179,6 @@ scan_free_map(struct adfs_sb_info *asb, struct adfs_discmap *dm) mapptr += 1 + ffz(~v2); } - //asm("@ find end of fragment end"); total += mapptr - start; } while (frag >= idlen + 1); diff --git a/fs/attr.c b/fs/attr.c index 21adfd00ebbb..d49af37d1951 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -99,5 +99,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr) if (!error) inode_setattr(inode, attr); } + if (!error && (attr->ia_valid & ATTR_SIZE)) + vmtruncate(inode, attr->ia_size); return error; } diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 3ca25fedf081..663817085812 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c @@ -329,21 +329,18 @@ int hpfs_unlink(struct inode *dir, struct dentry *dentry) d_delete(dentry); } else { /* no space for deleting, try to truncate file */ struct iattr newattrs; + int err; hpfs_unlock_2inodes(dir, inode); if (rep || dentry->d_count > 1 || permission(inode, MAY_WRITE) || get_write_access(inode)) goto ret; /*printk("HPFS: truncating file before delete.\n");*/ - down(&inode->i_sem); /* do_truncate should be called here, but it's */ - newattrs.ia_size = 0; /* not exported */ + down(&inode->i_sem); + newattrs.ia_size = 0; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; - if (notify_change(dentry, &newattrs)) { - up(&inode->i_sem); - put_write_access(inode); - goto ret; - } - vmtruncate(inode, 0); - if (inode->i_op && inode->i_op->truncate) inode->i_op->truncate(inode); + err = notify_change(dentry, &newattrs); up(&inode->i_sem); put_write_access(inode); + if (err) + goto ret; rep = 1; goto again; } diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 3b9927c7a745..2532104cc991 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -301,7 +301,7 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath) struct dentry *dentry, *result = NULL; struct dentry *tmp; int found =0; - u32 err; + long err; /* This semaphore is needed to make sure that only one unconnected (free) * dcache path ever exists, as otherwise two partial paths might get * joined together, which would be very confusing. diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index b1af9399ea47..1cfa0515ba2e 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -310,11 +310,6 @@ printk("nfsd_setattr: size change??\n"); if (iap->ia_valid & ATTR_SIZE) { fh_lock(fhp); err = notify_change(dentry, iap); - if (!err) { - vmtruncate(inode,iap->ia_size); - if (inode->i_op && inode->i_op->truncate) - inode->i_op->truncate(inode); - } fh_unlock(fhp); put_write_access(inode); } @@ -1082,11 +1077,6 @@ nfsd_truncate(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned long size) cap_clear(current->cap_effective); } err = notify_change(dentry, &newattrs); - if (!err) { - vmtruncate(inode, size); - if (inode->i_op && inode->i_op->truncate) - inode->i_op->truncate(inode); - } if (current->fsuid != 0) current->cap_effective = saved_cap; put_write_access(inode); diff --git a/fs/open.c b/fs/open.c index 159b08bf7ddb..808ddcaf8c30 100644 --- a/fs/open.c +++ b/fs/open.c @@ -69,12 +69,6 @@ int do_truncate(struct dentry *dentry, loff_t length) newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; error = notify_change(dentry, &newattrs); - if (!error) { - /* truncate virtual mappings of this file */ - vmtruncate(inode, length); - if (inode->i_op && inode->i_op->truncate) - inode->i_op->truncate(inode); - } up(&inode->i_sem); return error; } diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h index 7ef200cce159..ff8c6e9d1d79 100644 --- a/include/asm-alpha/pgtable.h +++ b/include/asm-alpha/pgtable.h @@ -249,8 +249,9 @@ extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= __ACCESS_BITS; retu #define pgd_offset_k(address) pgd_offset(&init_mm, address) /* to find an entry in a page-table-directory. */ -#define __pgd_offset(address) ((address >> PGDIR_SHIFT) & PTRS_PER_PGD) -#define pgd_offset(mm, address) ((mm)->pgd+__pgd_offset(address)) +#define pgd_index(address) ((address >> PGDIR_SHIFT) & PTRS_PER_PGD) +#define __pgd_offset(address) pgd_index(address) +#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) /* Find an entry in the second-level page table.. */ extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) diff --git a/include/asm-arm/hardirq.h b/include/asm-arm/hardirq.h index 79aec2cf6040..399ba566db89 100644 --- a/include/asm-arm/hardirq.h +++ b/include/asm-arm/hardirq.h @@ -9,7 +9,10 @@ extern unsigned int local_irq_count[NR_CPUS]; * Are we in an interrupt context? Either doing bottom half * or hardware interrupt processing? */ -#define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0) +#define in_interrupt() ({ const int __cpu = smp_processor_id(); \ + (local_irq_count[__cpu] + local_bh_count[__cpu] != 0); }) + +#define in_irq() (local_irq_count[smp_processor_id()] != 0) #ifndef __SMP__ diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h index 7e2192902fca..871e50a6517f 100644 --- a/include/asm-arm/io.h +++ b/include/asm-arm/io.h @@ -15,6 +15,7 @@ #ifndef __ASM_ARM_IO_H #define __ASM_ARM_IO_H +#include #include #include #include @@ -66,21 +67,31 @@ extern __inline__ void *phys_to_virt(unsigned long x) /* * ioremap and friends */ -extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags); +extern void * __ioremap(unsigned long offset, size_t size, unsigned long flags); extern void __iounmap(void *addr); #define ioremap(off,sz) __arch_ioremap((off),(sz),0) #define ioremap_nocache(off,sz) __arch_ioremap((off),(sz),1) #define iounmap(_addr) __iounmap(_addr) +/* + * DMA-consistent mapping functions. These allocate/free a region of + * uncached, unwrite-buffered mapped memory space for use with DMA + * devices. This is the "generic" version. The PCI specific version + * is in pci.h + */ +extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle); +extern void consistent_free(void *vaddr); +extern void consistent_sync(void *vaddr, size_t size, int rw); + extern void __readwrite_bug(const char *fn); /* * String version of IO memory access ops: */ -extern void _memcpy_fromio(void *, unsigned long, unsigned long); -extern void _memcpy_toio(unsigned long, const void *, unsigned long); -extern void _memset_io(unsigned long, int, unsigned long); +extern void _memcpy_fromio(void *, unsigned long, size_t); +extern void _memcpy_toio(unsigned long, const void *, size_t); +extern void _memset_io(unsigned long, int, size_t); #define __raw_writeb(val,addr) __arch_putb(val,addr) #define __raw_writew(val,addr) __arch_putw(val,addr) diff --git a/include/asm-arm/md.h b/include/asm-arm/md.h deleted file mode 100644 index 0a2c5dd01c0c..000000000000 --- a/include/asm-arm/md.h +++ /dev/null @@ -1,13 +0,0 @@ -/* $Id: md.h,v 1.1 1997/12/15 15:11:57 jj Exp $ - * md.h: High speed xor_block operation for RAID4/5 - * - */ - -#ifndef __ASM_MD_H -#define __ASM_MD_H - -/* #define HAVE_ARCH_XORBLOCK */ - -#define MD_XORBLOCK_ALIGNMENT sizeof(long) - -#endif /* __ASM_MD_H */ diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h index 5505909d4577..86ade5703166 100644 --- a/include/asm-arm/pci.h +++ b/include/asm-arm/pci.h @@ -3,5 +3,153 @@ #define pcibios_assign_all_busses() 0 -#endif +#define PCIBIOS_MIN_IO 0x8000 +#define PCIBIOS_MIN_MEM 0x40000000 + +#ifdef __KERNEL__ + +#include +#include + +struct pci_dev; + +/* Allocate and map kernel buffer using consistent mode DMA for a device. + * hwdev should be valid struct pci_dev pointer for PCI devices, + * NULL for PCI-like buses (ISA, EISA). + * Returns non-NULL cpu-view pointer to the buffer if successful and + * sets *dma_addrp to the pci side dma address as well, else *dma_addrp + * is undefined. + */ +#define pci_alloc_consistent(hwdev,size,handle) \ + ({ \ + void *__ret; \ + int __gfp = GFP_KERNEL; \ + \ + if ((hwdev) == NULL || \ + (hwdev)->dma_mask != 0xffffffff) \ + __gfp |= GFP_DMA; \ + \ + __ret = consistent_alloc(__gfp, (size), \ + (handle)); \ + __ret; \ + }) + +/* Free and unmap a consistent DMA buffer. + * cpu_addr is what was returned from pci_alloc_consistent, + * size must be the same as what as passed into pci_alloc_consistent, + * and likewise dma_addr must be the same as what *dma_addrp was set to. + * + * References to the memory and mappings associated with cpu_addr/dma_addr + * past this call are illegal. + */ +extern inline void +pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, + dma_addr_t dma_handle) +{ + consistent_free(vaddr); +} + +/* Map a single buffer of the indicated size for DMA in streaming mode. + * The 32-bit bus address to use is returned. + * + * Once the device is given the dma address, the device owns this memory + * until either pci_unmap_single or pci_dma_sync_single is performed. + */ +extern inline dma_addr_t +pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size) +{ + consistent_sync(ptr, size, 3); + return virt_to_bus(ptr); +} + +/* Unmap a single streaming mode DMA translation. The dma_addr and size + * must match what was provided for in a previous pci_map_single call. All + * other usages are undefined. + * + * After this call, reads by the cpu to the buffer are guarenteed to see + * whatever the device wrote there. + */ +extern inline void +pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size) +{ + /* nothing to do */ +} + +/* Map a set of buffers described by scatterlist in streaming + * mode for DMA. This is the scather-gather version of the + * above pci_map_single interface. Here the scatter gather list + * elements are each tagged with the appropriate dma address + * and length. They are obtained via sg_dma_{address,length}(SG). + * + * NOTE: An implementation may be able to use a smaller number of + * DMA address/length pairs than there are SG table elements. + * (for example via virtual mapping capabilities) + * The routine returns the number of addr/length pairs actually + * used, at most nents. + * + * Device ownership issues as mentioned above for pci_map_single are + * the same here. + */ +extern inline int +pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents) +{ + int i; + for (i = 0; i < nents; i++, sg++) + consistent_sync(sg->address, sg->length, 3); + + return nents; +} + +/* Unmap a set of streaming mode DMA translations. + * Again, cpu read rules concerning calls here are the same as for + * pci_unmap_single() above. + */ +extern inline void +pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents) +{ + /* nothing to do */ +} + +/* Make physical memory consistent for a single + * streaming mode DMA translation after a transfer. + * + * If you perform a pci_map_single() but wish to interrogate the + * buffer using the cpu, yet do not wish to teardown the PCI dma + * mapping, you must call this function before doing so. At the + * next point you give the PCI dma address back to the card, the + * device again owns the buffer. + */ +extern inline void +pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size) +{ + consistent_sync(bus_to_virt(dma_handle), size, 3); +} + +/* Make physical memory consistent for a set of streaming + * mode DMA translations after a transfer. + * + * The same as pci_dma_sync_single but for a scatter-gather list, + * same rules and usage. + */ +extern inline void +pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nelems) +{ + int i; + + for (i = 0; i < nelems; i++, sg++) + consistent_sync(sg->address, sg->length, 3); +} + +/* These macros should be used after a pci_map_sg call has been done + * to get bus addresses of each of the SG entries and their lengths. + * You should only work with the number of sg entries pci_map_sg + * returns, or alternatively stop on the first sg_dma_len(sg) which + * is 0. + */ +#define sg_dma_address(sg) (virt_to_bus((sg)->address)) +#define sg_dma_len(sg) ((sg)->length) + +#endif /* __KERNEL__ */ + +#endif diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h index 033541764a6b..418ed812abcd 100644 --- a/include/asm-arm/pgtable.h +++ b/include/asm-arm/pgtable.h @@ -122,9 +122,10 @@ extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) #define page_pte(page) mk_pte(page, __pgprot(0)) /* to find an entry in a page-table-directory */ -#define __pgd_offset(addr) ((addr) >> PGDIR_SHIFT) +#define pgd_index(addr) ((addr) >> PGDIR_SHIFT) +#define __pgd_offset(addr) pgd_index(addr) -#define pgd_offset(mm, addr) ((mm)->pgd+__pgd_offset(addr)) +#define pgd_offset(mm, addr) ((mm)->pgd+pgd_index(addr)) /* to find an entry in a kernel page-table-directory */ #define pgd_offset_k(addr) pgd_offset(&init_mm, addr) diff --git a/include/asm-arm/proc-armo/semaphore.h b/include/asm-arm/proc-armo/semaphore.h index 19fa29bf9ea9..6926fad126af 100644 --- a/include/asm-arm/proc-armo/semaphore.h +++ b/include/asm-arm/proc-armo/semaphore.h @@ -1,109 +1,75 @@ /* - * linux/include/asm-arm/proc-armo/semaphore.h + * linux/include/asm-arm/proc-armo/locks.h + * + * Copyright (C) 2000 Russell King + * + * Interrupt safe locking assembler. */ -#ifndef __ASM_PROC_SEMAPHORE_H -#define __ASM_PROC_SEMAPHORE_H +#ifndef __ASM_PROC_LOCKS_H +#define __ASM_PROC_LOCKS_H -/* - * This is ugly, but we want the default case to fall through. - * "__down" is the actual routine that waits... - */ -extern inline void down(struct semaphore * sem) -{ - __asm__ __volatile__ (" - @ atomic down operation - mov r0, pc - orr lr, r0, #0x08000000 - teqp lr, #0 - ldr lr, [%0] - and r0, r0, #0x0c000003 - subs lr, lr, #1 - str lr, [%0] - orrmi r0, r0, #0x80000000 @ set N - teqp r0, #0 - movmi r0, %0 - blmi " SYMBOL_NAME_STR(__down_failed) - : - : "r" (sem) - : "r0", "lr", "cc"); -} +#define __down_op(ptr,fail) \ + ({ \ + __asm__ __volatile__ ( \ + "@ atomic down operation\n" \ +" mov r0, pc\n" \ +" orr lr, r0, #0x08000000\n" \ +" teqp lr, #0\n" \ +" ldr lr, [%0]\n" \ +" and r0, r0, #0x0c000003\n" \ +" subs lr, lr, #1\n" \ +" str lr, [%0]\n" \ +" orrmi r0, r0, #0x80000000 @ set N\n" \ +" teqp r0, #0\n" \ +" movmi r0, %0\n" \ + blmi " SYMBOL_NAME_STR(fail) \ + : \ + : "r" (ptr) \ + : "r0", "lr", "cc"); \ + }) -/* - * This is ugly, but we want the default case to fall through. - * "__down_interruptible" is the actual routine that waits... - */ -extern inline int down_interruptible (struct semaphore * sem) -{ - int result; - __asm__ __volatile__ (" - @ atomic down operation - mov r0, pc - orr lr, r0, #0x08000000 - teqp lr, #0 - ldr lr, [%1] - and r0, r0, #0x0c000003 - subs lr, lr, #1 - str lr, [%1] - orrmi r0, r0, #0x80000000 @ set N - teqp r0, #0 - movmi r0, %1 - movpl r0, #0 - blmi " SYMBOL_NAME_STR(__down_interruptible_failed) " - mov %0, r0" - : "=r" (result) - : "r" (sem) - : "r0", "lr", "cc"); - return result; -} +#define __down_op_ret(ptr,fail) \ + ({ \ + unsigned int result; \ + __asm__ __volatile__ ( \ +" @ down_op_ret\n" \ +" mov r0, pc\n" \ +" orr lr, r0, #0x08000000\n" \ +" teqp lr, #0\n" \ +" ldr lr, [%1]\m" \ +" and r0, r0, #0x0c000003\n" \ +" subs lr, lr, #1\n" \ +" str lr, [%1]\n" \ +" orrmi r0, r0, #0x80000000 @ set N\n" \ +" teqp r0, #0\n" \ +" movmi r0, %1\n" \ +" movpl r0, #0\n" \ +" blmi " SYMBOL_NAME_STR(fail) "\n" \ +" mov %0, r0" \ + : "=&r" (result) \ + : "r" (ptr) \ + : "r0", "lr", "cc"); \ + result; \ + }) -extern inline int down_trylock(struct semaphore * sem) -{ - int result; - __asm__ __volatile__ (" - @ atomic down operation - mov r0, pc - orr lr, r0, #0x08000000 - teqp lr, #0 - ldr lr, [%1] - and r0, r0, #0x0c000003 - subs lr, lr, #1 - str lr, [%1] - orrmi r0, r0, #0x80000000 @ set N - teqp r0, #0 - movmi r0, %1 - movpl r0, #0 - blmi " SYMBOL_NAME_STR(__down_trylock_failed) " - mov %0, r0" - : "=r" (result) - : "r" (sem) - : "r0", "lr", "cc"); - return result; -} - -/* - * Note! This is subtle. We jump to wake people up only if - * the semaphore was negative (== somebody was waiting on it). - * The default case (no contention) will result in NO - * jumps for both down() and up(). - */ -extern inline void up(struct semaphore * sem) -{ - __asm__ __volatile__ (" - @ atomic up operation - mov r0, pc - orr lr, r0, #0x08000000 - teqp lr, #0 - ldr lr, [%0] - and r0, r0, #0x0c000003 - adds lr, lr, #1 - str lr, [%0] - orrle r0, r0, #0x80000000 @ set N - teqp r0, #0 - movmi r0, %0 - blmi " SYMBOL_NAME_STR(__up_wakeup) - : - : "r" (sem) - : "r0", "lr", "cc"); -} +#define __up_op(ptr,wake) \ + ({ \ + __asm__ __volatile__ ( \ + "@ up_op\n" \ + mov r0, pc\n" \ + orr lr, r0, #0x08000000\n" \ + teqp lr, #0\n" \ + ldr lr, [%0]\n" \ + and r0, r0, #0x0c000003\n" \ + adds lr, lr, #1\n" \ + str lr, [%0]\n" \ + orrle r0, r0, #0x80000000 @ set N\n" \ + teqp r0, #0\n" \ + movmi r0, %0\n" \ + blmi " SYMBOL_NAME_STR(wake) \ + : \ + : "r" (ptr) \ + : "r0", "lr", "cc"); \ + }) #endif diff --git a/include/asm-arm/proc-armv/locks.h b/include/asm-arm/proc-armv/locks.h new file mode 100644 index 000000000000..c1cfded3e4d8 --- /dev/null +++ b/include/asm-arm/proc-armv/locks.h @@ -0,0 +1,134 @@ +/* + * linux/include/asm-arm/proc-armv/locks.h + * + * Copyright (C) 2000 Russell King + * + * Interrupt safe locking assembler. + */ +#ifndef __ASM_PROC_LOCKS_H +#define __ASM_PROC_LOCKS_H + +#define __down_op(ptr,fail) \ + ({ \ + __asm__ __volatile__( \ + "@ down_op\n" \ +" mrs r0, cpsr\n" \ +" orr lr, r0, #128\n" \ +" msr cpsr_c, lr\n" \ +" ldr lr, [%0]\n" \ +" subs lr, lr, %1\n" \ +" str lr, [%0]\n" \ +" msr cpsr_c, r0\n" \ +" movmi r0, %0\n" \ +" blmi " SYMBOL_NAME_STR(fail) \ + : \ + : "r" (ptr), "I" (1) \ + : "r0", "lr", "cc"); \ + }) + +#define __down_op_ret(ptr,fail) \ + ({ \ + unsigned int ret; \ + __asm__ __volatile__( \ + "@ down_op_ret\n" \ +" mrs r0, cpsr\n" \ +" orr lr, r0, #128\n" \ +" msr cpsr_c, lr\n" \ +" ldr lr, [%1]\n" \ +" subs lr, lr, %2\n" \ +" str lr, [%1]\n" \ +" msr cpsr_c, r0\n" \ +" movmi r0, %1\n" \ +" movpl r0, #0\n" \ +" blmi " SYMBOL_NAME_STR(fail) "\n" \ +" mov %0, r0" \ + : "=&r" (ret) \ + : "r" (ptr), "I" (1) \ + : "r0", "lr", "cc"); \ + ret; \ + }) + +#define __up_op(ptr,wake) \ + ({ \ + __asm__ __volatile__( \ + "@ up_op\n" \ +" mrs r0, cpsr\n" \ +" orr lr, r0, #128\n" \ +" msr cpsr_c, lr\n" \ +" ldr lr, [%0]\n" \ +" adds lr, lr, %1\n" \ +" str lr, [%0]\n" \ +" msr cpsr_c, r0\n" \ +" movle r0, %0\n" \ +" blle " SYMBOL_NAME_STR(wake) \ + : \ + : "r" (ptr), "I" (1) \ + : "r0", "lr", "cc"); \ + }) + +/* + * The value 0x01000000 supports up to 128 processors and + * lots of processes. BIAS must be chosen such that sub'ing + * BIAS once per CPU will result in the long remaining + * negative. + */ +#define RW_LOCK_BIAS 0x01000000 + +#define __down_op_write(ptr,fail) \ + ({ \ + __asm__ __volatile__( \ + "@ down_op_write\n" \ +" mrs r0, cpsr\n" \ +" orr lr, r0, #128\n" \ +" msr cpsr_c, lr\n" \ +" ldr lr, [%0]\n" \ +" subs lr, lr, %1\n" \ +" str lr, [%0]\n" \ +" msr cpsr_c, r0\n" \ +" movne r0, %0\n" \ +" blne " SYMBOL_NAME_STR(fail) \ + : \ + : "r" (ptr), "I" (RW_LOCK_BIAS) \ + : "r0", "lr", "cc"); \ + }) + +#define __up_op_write(ptr,wake) \ + ({ \ + __asm__ __volatile__( \ + "@ up_op_read\n" \ +" mrs r0, cpsr\n" \ +" orr lr, r0, #128\n" \ +" msr cpsr_c, lr\n" \ +" ldr lr, [%0]\n" \ +" adds lr, lr, %1\n" \ +" str lr, [%0]\n" \ +" msr cpsr_c, r0\n" \ +" movcs r0, %0\n" \ +" blcs " SYMBOL_NAME_STR(wake) \ + : \ + : "r" (ptr), "I" (RW_LOCK_BIAS) \ + : "r0", "lr", "cc"); \ + }) + +#define __down_op_read(ptr,fail) \ + __down_op(ptr, fail) + +#define __up_op_read(ptr,wake) \ + ({ \ + __asm__ __volatile__( \ + "@ up_op_read\n" \ +" mrs r0, cpsr\n" \ +" orr lr, r0, #128\n" \ +" msr cpsr_c, lr\n" \ +" ldr lr, [%0]\n" \ +" adds lr, lr, %1\n" \ +" str lr, [%0]\n" \ +" msr cpsr_c, r0\n" \ +" moveq r0, %0\n" \ +" bleq " SYMBOL_NAME_STR(wake) \ + : \ + : "r" (ptr), "I" (1) \ + : "r0", "lr", "cc"); \ + }) + +#endif diff --git a/include/asm-arm/proc-armv/semaphore.h b/include/asm-arm/proc-armv/semaphore.h deleted file mode 100644 index 45ceaa3f1099..000000000000 --- a/include/asm-arm/proc-armv/semaphore.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * linux/include/asm-arm/semaphore.h - */ -#ifndef __ASM_PROC_SEMAPHORE_H -#define __ASM_PROC_SEMAPHORE_H - -/* - * This is ugly, but we want the default case to fall through. - * "__down" is the actual routine that waits... - */ -extern inline void down(struct semaphore * sem) -{ - unsigned int cpsr, temp; - - __asm__ __volatile__ (" - @ atomic down operation - mrs %0, cpsr - orr %1, %0, #128 @ disable IRQs - msr cpsr, %1 - ldr %1, [%2] - bic %0, %0, #0x80000000 @ clear N - subs %1, %1, #1 - str %1, [%2] - orrmi %0, %0, #0x80000000 @ set N - msr cpsr, %0 - movmi r0, %2 - blmi " SYMBOL_NAME_STR(__down_failed) - : "=&r" (cpsr), "=&r" (temp) - : "r" (sem) - : "r0", "lr", "cc"); -} - -/* - * This is ugly, but we want the default case to fall through. - * "__down_interruptible" is the actual routine that waits... - */ -extern inline int down_interruptible (struct semaphore * sem) -{ - unsigned int cpsr, temp; - - __asm__ __volatile__ (" - @ atomic down interruptible operation - mrs %0, cpsr - orr %1, %0, #128 @ disable IRQs - msr cpsr, %1 - ldr %1, [%2] - bic %0, %0, #0x80000000 @ clear N - subs %1, %1, #1 - str %1, [%2] - orrmi %0, %0, #0x80000000 @ set N - msr cpsr, %0 - movmi r0, %2 - movpl r0, #0 - blmi " SYMBOL_NAME_STR(__down_interruptible_failed) " - mov %1, r0" - : "=&r" (cpsr), "=&r" (temp) - : "r" (sem) - : "r0", "lr", "cc"); - - return temp; -} - -extern inline int down_trylock(struct semaphore *sem) -{ - unsigned int cpsr, temp; - - __asm__ __volatile__ (" - @ atomic down try lock operation - mrs %0, cpsr - orr %1, %0, #128 @ disable IRQs - msr cpsr, %1 - ldr %1, [%2] - bic %0, %0, #0x80000000 @ clear N - subs %1, %1, #1 - str %1, [%2] - orrmi %0, %0, #0x80000000 @ set N - msr cpsr, %0 - movmi r0, %2 - movpl r0, #0 - blmi " SYMBOL_NAME_STR(__down_trylock_failed) " - mov %1, r0" - : "=&r" (cpsr), "=&r" (temp) - : "r" (sem) - : "r0", "lr", "cc"); - - return temp; -} - -/* - * Note! This is subtle. We jump to wake people up only if - * the semaphore was negative (== somebody was waiting on it). - * The default case (no contention) will result in NO - * jumps for both down() and up(). - */ -extern inline void up(struct semaphore * sem) -{ - unsigned int cpsr, temp; - - __asm__ __volatile__ (" - @ atomic up operation - mrs %0, cpsr - orr %1, %0, #128 @ disable IRQs - msr cpsr, %1 - ldr %1, [%2] - bic %0, %0, #0x80000000 @ clear N - adds %1, %1, #1 - str %1, [%2] - orrle %0, %0, #0x80000000 @ set N - msr cpsr, %0 - movmi r0, %2 - blmi " SYMBOL_NAME_STR(__up_wakeup) - : "=&r" (cpsr), "=&r" (temp) - : "r" (sem) - : "r0", "lr", "cc"); -} - -#endif diff --git a/include/asm-arm/semaphore.h b/include/asm-arm/semaphore.h index 5ba171be8a28..0ce171a3f263 100644 --- a/include/asm-arm/semaphore.h +++ b/include/asm-arm/semaphore.h @@ -9,16 +9,28 @@ #include #include +#include struct semaphore { atomic_t count; int sleepers; wait_queue_head_t wait; +#if WAITQUEUE_DEBUG + long __magic; +#endif }; +#if WAITQUEUE_DEBUG +# define __SEM_DEBUG_INIT(name) \ + , (long)&(name).__magic +#else +# define __SEM_DEBUG_INIT(name) +#endif + #define __SEMAPHORE_INIT(name,count) \ { ATOMIC_INIT(count), 0, \ - __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) } + __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ + __SEM_DEBUG_INIT(name) } #define __MUTEX_INITIALIZER(name) \ __SEMAPHORE_INIT(name,1) @@ -29,12 +41,15 @@ struct semaphore { #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0) -#define sema_init(sem, val) \ -do { \ - atomic_set(&((sem)->count), (val)); \ - (sem)->sleepers = 0; \ - init_waitqueue_head(&(sem)->wait); \ -} while (0) +extern inline void sema_init(struct semaphore *sem, int val) +{ + atomic_set(&sem->count, val); + sem->sleepers = 0; + init_waitqueue_head(&sem->wait); +#if WAITQUEUE_DEBUG + sem->__magic = (long)&sem->__magic; +#endif +} static inline void init_MUTEX(struct semaphore *sem) { @@ -46,18 +61,196 @@ static inline void init_MUTEX_LOCKED(struct semaphore *sem) sema_init(sem, 0); } -asmlinkage void __down_failed (void /* special register calling convention */); -asmlinkage int __down_interruptible_failed (void /* special register calling convention */); -asmlinkage int __down_trylock_failed(void /* params in registers */); -asmlinkage void __up_wakeup (void /* special register calling convention */); +/* + * special register calling convention + */ +asmlinkage void __down_failed(void); +asmlinkage int __down_interruptible_failed(void); +asmlinkage int __down_trylock_failed(void); +asmlinkage void __up_wakeup(void); extern void __down(struct semaphore * sem); extern int __down_interruptible(struct semaphore * sem); extern int __down_trylock(struct semaphore * sem); extern void __up(struct semaphore * sem); -extern spinlock_t semaphore_wake_lock; +/* + * This is ugly, but we want the default case to fall through. + * "__down" is the actual routine that waits... + */ +extern inline void down(struct semaphore * sem) +{ +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); +#endif + + __down_op(sem, __down_failed); +} + +/* + * This is ugly, but we want the default case to fall through. + * "__down_interruptible" is the actual routine that waits... + */ +extern inline int down_interruptible (struct semaphore * sem) +{ +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); +#endif + + return __down_op_ret(sem, __down_interruptible_failed); +} + +extern inline int down_trylock(struct semaphore *sem) +{ +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); +#endif + + return __down_op_ret(sem, __down_trylock_failed); +} + +/* + * Note! This is subtle. We jump to wake people up only if + * the semaphore was negative (== somebody was waiting on it). + * The default case (no contention) will result in NO + * jumps for both down() and up(). + */ +extern inline void up(struct semaphore * sem) +{ +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); +#endif + + __up_op(sem, __up_wakeup); +} + +/* rw mutexes (should that be mutices? =) -- throw rw + * spinlocks and semaphores together, and this is what we + * end up with... + * + * The lock is initialized to BIAS. This way, a writer + * subtracts BIAS ands gets 0 for the case of an uncontended + * lock. Readers decrement by 1 and see a positive value + * when uncontended, negative if there are writers waiting + * (in which case it goes to sleep). + * + * In terms of fairness, this should result in the lock + * flopping back and forth between readers and writers + * under heavy use. + * + * -ben + */ +struct rw_semaphore { + atomic_t count; + volatile unsigned char write_bias_granted; + volatile unsigned char read_bias_granted; + volatile unsigned char pad1; + volatile unsigned char pad2; + wait_queue_head_t wait; + wait_queue_head_t write_bias_wait; +#if WAITQUEUE_DEBUG + long __magic; + atomic_t readers; + atomic_t writers; +#endif +}; + +#if WAITQUEUE_DEBUG +#define __RWSEM_DEBUG_INIT , ATOMIC_INIT(0), ATOMIC_INIT(0) +#else +#define __RWSEM_DEBUG_INIT /* */ +#endif + +#define __RWSEM_INITIALIZER(name,count) \ +{ ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \ + __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \ + __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT } + +#define __DECLARE_RWSEM_GENERIC(name,count) \ + struct rw_semaphore name = __RWSEM_INITIALIZER(name,count) + +#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS) +#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1) +#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0) + +extern inline void init_rwsem(struct rw_semaphore *sem) +{ + atomic_set(&sem->count, RW_LOCK_BIAS); + sem->read_bias_granted = 0; + sem->write_bias_granted = 0; + init_waitqueue_head(&sem->wait); + init_waitqueue_head(&sem->write_bias_wait); +#if WAITQUEUE_DEBUG + sem->__magic = (long)&sem->__magic; + atomic_set(&sem->readers, 0); + atomic_set(&sem->writers, 0); +#endif +} + +extern struct rw_semaphore *__down_read_failed(struct rw_semaphore *sem); +extern struct rw_semaphore *__down_write_failed(struct rw_semaphore *sem); +extern struct rw_semaphore *__rwsem_wake(struct rw_semaphore *sem); + +extern inline void down_read(struct rw_semaphore *sem) +{ +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); +#endif + __down_op_read(sem, __down_read_failed); +#if WAITQUEUE_DEBUG + if (sem->write_bias_granted) + BUG(); + if (atomic_read(&sem->writers)) + BUG(); + atomic_inc(&sem->readers); +#endif +} + +extern inline void down_write(struct rw_semaphore *sem) +{ +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); +#endif + __down_op_write(sem, __down_write_failed); +#if WAITQUEUE_DEBUG + if (atomic_read(&sem->writers)) + BUG(); + if (atomic_read(&sem->readers)) + BUG(); + if (sem->read_bias_granted) + BUG(); + if (sem->write_bias_granted) + BUG(); + atomic_inc(&sem->writers); +#endif +} + +extern inline void up_read(struct rw_semaphore *sem) +{ +#if WAITQUEUE_DEBUG + if (sem->write_bias_granted) + BUG(); + if (atomic_read(&sem->writers)) + BUG(); + atomic_dec(&sem->readers); +#endif + __up_op_read(sem, __rwsem_wake); +} -#include +extern inline void up_write(struct rw_semaphore *sem) +{ +#if WAITQUEUE_DEBUG + if (sem->read_bias_granted) + BUG(); + if (sem->write_bias_granted) + BUG(); + if (atomic_read(&sem->readers)) + BUG(); + if (atomic_read(&sem->writers) != 1) + BUG(); + atomic_dec(&sem->writers); +#endif + __up_op_write(sem, __rwsem_wake); +} #endif diff --git a/include/asm-arm/softirq.h b/include/asm-arm/softirq.h index 28ac2eb2a367..f98754813137 100644 --- a/include/asm-arm/softirq.h +++ b/include/asm-arm/softirq.h @@ -9,72 +9,9 @@ extern unsigned int local_bh_count[NR_CPUS]; #define cpu_bh_disable(cpu) do { local_bh_count[(cpu)]++; barrier(); } while (0) #define cpu_bh_enable(cpu) do { barrier(); local_bh_count[(cpu)]--; } while (0) -#define cpu_bh_trylock(cpu) (local_bh_count[(cpu)] ? 0 : (local_bh_count[(cpu)] = 1)) -#define cpu_bh_endlock(cpu) (local_bh_count[(cpu)] = 0) - #define local_bh_disable() cpu_bh_disable(smp_processor_id()) #define local_bh_enable() cpu_bh_enable(smp_processor_id()) -#define get_active_bhs() (bh_mask & bh_active) -#define clear_active_bhs(x) atomic_clear_mask((x),&bh_active) - -extern inline void init_bh(int nr, void (*routine)(void)) -{ - bh_base[nr] = routine; - atomic_set(&bh_mask_count[nr], 0); - bh_mask |= 1 << nr; -} - -extern inline void remove_bh(int nr) -{ - bh_mask &= ~(1 << nr); - mb(); - bh_base[nr] = NULL; -} - -extern inline void mark_bh(int nr) -{ - set_bit(nr, &bh_active); -} - -#ifdef __SMP__ -#error SMP not supported -#else - -extern inline void start_bh_atomic(void) -{ - local_bh_disable(); - barrier(); -} - -extern inline void end_bh_atomic(void) -{ - barrier(); - local_bh_enable(); -} - -/* These are for the irq's testing the lock */ -#define softirq_trylock(cpu) (cpu_bh_trylock(cpu)) -#define softirq_endlock(cpu) (cpu_bh_endlock(cpu)) -#define synchronize_bh() barrier() - -#endif /* SMP */ - -/* - * These use a mask count to correctly handle - * nested disable/enable calls - */ -extern inline void disable_bh(int nr) -{ - bh_mask &= ~(1 << nr); - atomic_inc(&bh_mask_count[nr]); - synchronize_bh(); -} - -extern inline void enable_bh(int nr) -{ - if (atomic_dec_and_test(&bh_mask_count[nr])) - bh_mask |= 1 << nr; -} +#define in_softirq() (local_bh_count[smp_processor_id()] != 0) #endif /* __ASM_SOFTIRQ_H */ diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index 0a37bbfb9196..7716dc422e4e 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -292,10 +292,11 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) /* to find an entry in a page-table-directory. */ -#define __pgd_offset(address) \ - ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) +#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) -#define pgd_offset(mm, address) ((mm)->pgd+__pgd_offset(address)) +#define __pgd_offset(address) pgd_index(address) + +#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) /* to find an entry in a kernel page-table-directory */ #define pgd_offset_k(address) pgd_offset(&init_mm, address) diff --git a/include/asm-ia64/dma.h b/include/asm-ia64/dma.h index 3e6185064e7a..4e9b30a918c8 100644 --- a/include/asm-ia64/dma.h +++ b/include/asm-ia64/dma.h @@ -6,11 +6,11 @@ * Copyright (C) 1998, 1999 David Mosberger-Tang */ -#include /* need byte IO */ #include #include /* And spinlocks */ #include +#include /* need byte IO */ #ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER #define dma_outb outb_p diff --git a/include/asm-ia64/fpswa.h b/include/asm-ia64/fpswa.h index a6facbd8cab3..bbf8afcfdd44 100644 --- a/include/asm-ia64/fpswa.h +++ b/include/asm-ia64/fpswa.h @@ -9,7 +9,7 @@ * Copyright (C) 1999 Goutham Rao */ -#if 0 +#if 1 #define FPSWA_BUG #endif diff --git a/include/asm-ia64/hardirq.h b/include/asm-ia64/hardirq.h index 95523854eb7c..567243650243 100644 --- a/include/asm-ia64/hardirq.h +++ b/include/asm-ia64/hardirq.h @@ -17,12 +17,16 @@ extern unsigned long hardirq_no[NR_CPUS]; * or hardware interrupt processing? */ +#define in_irq() (local_irq_count[smp_processor_id()] != 0) + #define in_interrupt() \ ({ \ int __cpu = smp_processor_id(); \ (local_irq_count[__cpu] + local_bh_count[__cpu]) != 0; \ }) + + #ifndef CONFIG_SMP # define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) # define hardirq_endlock(cpu) ((void) 0) diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h index b775d0a9a236..22c2b2297331 100644 --- a/include/asm-ia64/mmu_context.h +++ b/include/asm-ia64/mmu_context.h @@ -60,6 +60,11 @@ extern unsigned long ia64_next_context; extern void get_new_mmu_context (struct mm_struct *mm); +static inline void +enter_lazy_tlb (struct mm_struct *mm, struct task_struct *tsk, unsigned cpu) +{ +} + extern inline unsigned long ia64_rid (unsigned long context, unsigned long region_addr) { diff --git a/include/asm-ia64/offsets.h b/include/asm-ia64/offsets.h index 9639a9e40878..d989cb911aa6 100644 --- a/include/asm-ia64/offsets.h +++ b/include/asm-ia64/offsets.h @@ -10,7 +10,7 @@ #define PF_PTRACED_BIT 4 -#define IA64_TASK_SIZE 2752 /* 0xac0 */ +#define IA64_TASK_SIZE 3280 /* 0xcd0 */ #define IA64_PT_REGS_SIZE 400 /* 0x190 */ #define IA64_SWITCH_STACK_SIZE 560 /* 0x230 */ #define IA64_SIGINFO_SIZE 136 /* 0x88 */ @@ -18,8 +18,9 @@ #define IA64_TASK_FLAGS_OFFSET 8 /* 0x8 */ #define IA64_TASK_SIGPENDING_OFFSET 16 /* 0x10 */ #define IA64_TASK_NEED_RESCHED_OFFSET 40 /* 0x28 */ -#define IA64_TASK_THREAD_OFFSET 912 /* 0x390 */ -#define IA64_TASK_THREAD_KSP_OFFSET 912 /* 0x390 */ +#define IA64_TASK_PROCESSOR_OFFSET 108 /* 0x6c */ +#define IA64_TASK_THREAD_OFFSET 1424 /* 0x590 */ +#define IA64_TASK_THREAD_KSP_OFFSET 1424 /* 0x590 */ #define IA64_TASK_PID_OFFSET 188 /* 0xbc */ #define IA64_TASK_MM_OFFSET 88 /* 0x58 */ #define IA64_PT_REGS_CR_IPSR_OFFSET 0 /* 0x0 */ diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index 2defe7cdfb9c..203005b5c7de 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h @@ -187,9 +187,14 @@ #define flush_cache_page(vma, vmaddr) do { } while (0) #define flush_page_to_ram(page) do { } while (0) #define flush_icache_range(start, end) do { } while (0) + extern void ia64_flush_icache_page (unsigned long addr); -#define flush_icache_page(pg) ia64_flush_icache_page(page_address(pg)) +#define flush_icache_page(vma,pg) \ +do { \ + if ((vma)->vm_flags & PROT_EXEC) \ + ia64_flush_icache_page(page_address(pg)); \ +} while (0) /* * Now come the defines and routines to manage and access the three-level @@ -289,15 +294,21 @@ extern pmd_t *ia64_bad_pagetable (void); */ #define pgprot_noncached(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_UC) +extern __inline__ unsigned long +pgd_index (unsigned long address) +{ + unsigned long region = address >> 61; + unsigned long l1index = (address >> PGDIR_SHIFT) & ((PTRS_PER_PGD >> 3) - 1); + + return (region << (PAGE_SHIFT - 6)) | l1index; +} + /* The offset in the 1-level directory is given by the 3 region bits (61..63) and the seven level-1 bits (33-39). */ extern __inline__ pgd_t* pgd_offset (struct mm_struct *mm, unsigned long address) { - unsigned long region = address >> 61; - unsigned long l1index = (address >> PGDIR_SHIFT) & ((PTRS_PER_PGD >> 3) - 1); - - return mm->pgd + ((region << (PAGE_SHIFT - 6)) | l1index); + return mm->pgd + pgd_index(address); } /* In the kernel's mapped region we have a full 43 bit space available and completely diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h index b2d0cc906410..d50ce82e7995 100644 --- a/include/asm-ia64/ptrace.h +++ b/include/asm-ia64/ptrace.h @@ -145,10 +145,10 @@ struct pt_regs { * Floating point registers that the kernel considers * scratch: */ - struct ia64_fpreg f6; /* scratch*/ - struct ia64_fpreg f7; /* scratch*/ - struct ia64_fpreg f8; /* scratch*/ - struct ia64_fpreg f9; /* scratch*/ + struct ia64_fpreg f6; /* scratch */ + struct ia64_fpreg f7; /* scratch */ + struct ia64_fpreg f8; /* scratch */ + struct ia64_fpreg f9; /* scratch */ }; /* diff --git a/include/asm-ia64/semaphore.h b/include/asm-ia64/semaphore.h index 2c75056c58bc..a50ee01e39f6 100644 --- a/include/asm-ia64/semaphore.h +++ b/include/asm-ia64/semaphore.h @@ -137,13 +137,6 @@ up (struct semaphore * sem) * In terms of fairness, when there is heavy use of the lock, we want * to see the lock being passed back and forth between readers and * writers (like in a producer/consumer style of communication). - * - - For - * liveness, it would be necessary to process the blocked readers and - * writers in FIFO order. However, we don't do this (yet). I suppose - * if you have a lock that is _that_ heavily contested, you're in big - * trouble anyhow. * * -ben (with clarifications & IA-64 comments by davidm) */ diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h index 1ad1a8149664..a6ea5c17d293 100644 --- a/include/asm-ia64/smp.h +++ b/include/asm-ia64/smp.h @@ -8,6 +8,7 @@ #define _ASM_IA64_SMP_H #include + #include #include #include @@ -25,9 +26,10 @@ extern unsigned long cpu_present_map; extern unsigned long cpu_online_map; extern unsigned long ipi_base_addr; extern int bootstrap_processor; -extern volatile int cpu_number_map[NR_CPUS]; +extern volatile int __cpu_number_map[NR_CPUS]; extern volatile int __cpu_logical_map[NR_CPUS]; +#define cpu_number_map(i) __cpu_number_map[i] #define cpu_logical_map(i) __cpu_logical_map[i] #if defined(CONFIG_KDB) diff --git a/include/asm-ia64/softirq.h b/include/asm-ia64/softirq.h index 8b92f4442a4e..fb40999e244e 100644 --- a/include/asm-ia64/softirq.h +++ b/include/asm-ia64/softirq.h @@ -2,13 +2,9 @@ #define _ASM_IA64_SOFTIRQ_H /* - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998-2000 David Mosberger-Tang */ -#include -#include - -#include #include extern unsigned int local_bh_count[NR_CPUS]; @@ -16,137 +12,9 @@ extern unsigned int local_bh_count[NR_CPUS]; #define cpu_bh_disable(cpu) do { local_bh_count[(cpu)]++; barrier(); } while (0) #define cpu_bh_enable(cpu) do { barrier(); local_bh_count[(cpu)]--; } while (0) -#define cpu_bh_trylock(cpu) (local_bh_count[(cpu)] ? 0 : (local_bh_count[(cpu)] = 1)) -#define cpu_bh_endlock(cpu) (local_bh_count[(cpu)] = 0) - #define local_bh_disable() cpu_bh_disable(smp_processor_id()) #define local_bh_enable() cpu_bh_enable(smp_processor_id()) -#define get_active_bhs() (bh_mask & bh_active) - -static inline void -clear_active_bhs (unsigned long x) -{ - unsigned long old, new; - volatile unsigned long *bh_activep = (void *) &bh_active; - CMPXCHG_BUGCHECK_DECL - - do { - CMPXCHG_BUGCHECK(bh_activep); - old = *bh_activep; - new = old & ~x; - } while (ia64_cmpxchg(bh_activep, old, new, 8) != old); -} - -extern inline void -init_bh (int nr, void (*routine)(void)) -{ - bh_base[nr] = routine; - atomic_set(&bh_mask_count[nr], 0); - bh_mask |= 1 << nr; -} - -extern inline void -remove_bh (int nr) -{ - bh_mask &= ~(1 << nr); - mb(); - bh_base[nr] = NULL; -} - -extern inline void -mark_bh (int nr) -{ - set_bit(nr, &bh_active); -} - -#ifdef CONFIG_SMP - -/* - * The locking mechanism for base handlers, to prevent re-entrancy, - * is entirely private to an implementation, it should not be - * referenced at all outside of this file. - */ -extern atomic_t global_bh_lock; -extern atomic_t global_bh_count; - -extern void synchronize_bh(void); - -static inline void -start_bh_atomic (void) -{ - atomic_inc(&global_bh_lock); - synchronize_bh(); -} - -static inline void -end_bh_atomic (void) -{ - atomic_dec(&global_bh_lock); -} - -/* These are for the irq's testing the lock */ -static inline int -softirq_trylock (int cpu) -{ - if (cpu_bh_trylock(cpu)) { - if (!test_and_set_bit(0, &global_bh_count)) { - if (atomic_read(&global_bh_lock) == 0) - return 1; - clear_bit(0,&global_bh_count); - } - cpu_bh_endlock(cpu); - } - return 0; -} - -static inline void -softirq_endlock (int cpu) -{ - cpu_bh_enable(cpu); - clear_bit(0,&global_bh_count); -} - -#else /* !CONFIG_SMP */ - -extern inline void -start_bh_atomic (void) -{ - local_bh_disable(); - barrier(); -} - -extern inline void -end_bh_atomic (void) -{ - barrier(); - local_bh_enable(); -} - -/* These are for the irq's testing the lock */ -#define softirq_trylock(cpu) (cpu_bh_trylock(cpu)) -#define softirq_endlock(cpu) (cpu_bh_endlock(cpu)) -#define synchronize_bh() barrier() - -#endif /* !CONFIG_SMP */ - -/* - * These use a mask count to correctly handle - * nested disable/enable calls - */ -extern inline void -disable_bh (int nr) -{ - bh_mask &= ~(1 << nr); - atomic_inc(&bh_mask_count[nr]); - synchronize_bh(); -} - -extern inline void -enable_bh (int nr) -{ - if (atomic_dec_and_test(&bh_mask_count[nr])) - bh_mask |= 1 << nr; -} +#define in_softirq() (local_bh_count[smp_processor_id()] != 0) #endif /* _ASM_IA64_SOFTIRQ_H */ diff --git a/include/asm-ia64/types.h b/include/asm-ia64/types.h index a86d0a7f3424..d4b1732e2d2b 100644 --- a/include/asm-ia64/types.h +++ b/include/asm-ia64/types.h @@ -8,8 +8,8 @@ * not a major issue. However, for interoperability, libraries still * need to be careful to avoid a name clashes. * - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998-2000 David Mosberger-Tang */ #ifdef __ASSEMBLY__ @@ -38,52 +38,28 @@ typedef unsigned short __u16; typedef __signed__ int __s32; typedef unsigned int __u32; -/* - * There are 32-bit compilers for the ia-64 out there.. - */ -# if ((~0UL) == 0xffffffff) -# if defined(__GNUC__) && !defined(__STRICT_ANSI__) -typedef __signed__ long long __s64; -typedef unsigned long long __u64; -# endif -# else typedef __signed__ long __s64; typedef unsigned long __u64; -# endif /* * These aren't exported outside the kernel to avoid name space clashes */ # ifdef __KERNEL__ -typedef signed char s8; -typedef unsigned char u8; +typedef __s8 s8; +typedef __u8 u8; -typedef signed short s16; -typedef unsigned short u16; +typedef __s16 s16; +typedef __u16 u16; -typedef signed int s32; -typedef unsigned int u32; +typedef __s32 s32; +typedef __u32 u32; -/* - * There are 32-bit compilers for the ia-64 out there... (don't rely - * on cpp because that may cause su problem in a 32->64 bit - * cross-compilation environment). - */ -# ifdef __LP64__ +typedef __s64 s64; +typedef __u64 u64; -typedef signed long s64; -typedef unsigned long u64; #define BITS_PER_LONG 64 -# else - -typedef signed long long s64; -typedef unsigned long long u64; -#define BITS_PER_LONG 32 - -# endif - /* DMA addresses are 64-bits wide, in general. */ typedef u64 dma_addr_t; diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h index 9df773f9fc8a..a92c28b12d5c 100644 --- a/include/asm-m68k/pgtable.h +++ b/include/asm-m68k/pgtable.h @@ -285,10 +285,12 @@ extern inline pte_t pte_mkcache(pte_t pte) { pte_val(pte) = (pte_val(pte) & _CAC #define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address)) +#define pgd_index(address) ((address) >> PGDIR_SHIFT) + /* to find an entry in a page-table-directory */ extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) { - return mm->pgd + (address >> PGDIR_SHIFT); + return mm->pgd + pgd_index(address); } #define swapper_pg_dir kernel_pg_dir diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h index 9b23b03c5ae5..8cb15ede743f 100644 --- a/include/asm-mips/pgtable.h +++ b/include/asm-mips/pgtable.h @@ -371,10 +371,12 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) /* to find an entry in a kernel page-table-directory */ #define pgd_offset_k(address) pgd_offset(&init_mm, address) +#define pgd_index(address) ((address) >> PGDIR_SHIFT) + /* to find an entry in a page-table-directory */ extern inline pgd_t *pgd_offset(struct mm_struct *mm, unsigned long address) { - return mm->pgd + (address >> PGDIR_SHIFT); + return mm->pgd + pgd_index(address); } /* Find an entry in the second-level page table.. */ diff --git a/include/asm-ppc/elf.h b/include/asm-ppc/elf.h index 002736abf1ce..3ae89d9cc9ec 100644 --- a/include/asm-ppc/elf.h +++ b/include/asm-ppc/elf.h @@ -8,6 +8,7 @@ #define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ #define ELF_NFPREG 33 /* includes fpscr */ +#define ELF_NVRREG 33 /* includes vscr */ /* * This is used to ensure we don't load something for the wrong architecture. @@ -37,6 +38,10 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; +/* Altivec registers */ +typedef vector128 elf_vrreg_t; +typedef elf_vrreg_t elf_vrregset_t[ELF_NVRREG]; + #define ELF_CORE_COPY_REGS(gregs, regs) \ memcpy(gregs, regs, \ sizeof(struct pt_regs) < sizeof(elf_gregset_t)? \ diff --git a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h index ac5ac69fc18d..80c3e1de6748 100644 --- a/include/asm-ppc/hardirq.h +++ b/include/asm-ppc/hardirq.h @@ -3,22 +3,24 @@ #include -extern unsigned int ppc_local_irq_count[NR_CPUS]; +extern unsigned int local_irq_count[NR_CPUS]; /* * Are we in an interrupt context? Either doing bottom half * or hardware interrupt processing? */ #define in_interrupt() ({ int __cpu = smp_processor_id(); \ - (ppc_local_irq_count[__cpu] + ppc_local_bh_count[__cpu] != 0); }) + (local_irq_count[__cpu] + local_bh_count[__cpu] != 0); }) + +#define in_irq() (local_irq_count[smp_processor_id()] != 0) #ifndef __SMP__ -#define hardirq_trylock(cpu) (ppc_local_irq_count[cpu] == 0) +#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) #define hardirq_endlock(cpu) do { } while (0) -#define hardirq_enter(cpu) (ppc_local_irq_count[cpu]++) -#define hardirq_exit(cpu) (ppc_local_irq_count[cpu]--) +#define hardirq_enter(cpu) (local_irq_count[cpu]++) +#define hardirq_exit(cpu) (local_irq_count[cpu]--) #define synchronize_irq() do { } while (0) @@ -41,14 +43,31 @@ static inline void release_irqlock(int cpu) static inline void hardirq_enter(int cpu) { - ++ppc_local_irq_count[cpu]; + unsigned int loops = 10000000; + + ++local_irq_count[cpu]; atomic_inc(&global_irq_count); + while (test_bit(0,&global_irq_lock)) { + if (smp_processor_id() == global_irq_holder) { + printk("uh oh, interrupt while we hold global irq lock!\n"); +#ifdef CONFIG_XMON + xmon(0); +#endif + break; + } + if (loops-- == 0) { + printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder); +#ifdef CONFIG_XMON + xmon(0); +#endif + } + } } static inline void hardirq_exit(int cpu) { atomic_dec(&global_irq_count); - --ppc_local_irq_count[cpu]; + --local_irq_count[cpu]; } static inline int hardirq_trylock(int cpu) diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h index 55168a8b2b3e..8c8b8895480e 100644 --- a/include/asm-ppc/page.h +++ b/include/asm-ppc/page.h @@ -77,7 +77,7 @@ typedef unsigned long pgprot_t; #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) extern void clear_page(void *page); -#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) +extern void copy_page(void *to, void *from); /* map phys->virtual and virtual->phys for RAM pages */ static inline unsigned long ___pa(unsigned long v) diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index f1f0f578a6bc..6ab7eb70d2a6 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h @@ -413,7 +413,8 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #define pgd_offset_k(address) pgd_offset(&init_mm, address) /* to find an entry in a page-table-directory */ -#define pgd_offset(mm, address) ((mm)->pgd + ((address) >> PGDIR_SHIFT)) +#define pgd_index(address) ((address) >> PGDIR_SHIFT) +#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) /* Find an entry in the second-level page table.. */ extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) diff --git a/include/asm-ppc/posix_types.h b/include/asm-ppc/posix_types.h index f6d0d70ea79f..04c59a5b3db1 100644 --- a/include/asm-ppc/posix_types.h +++ b/include/asm-ppc/posix_types.h @@ -24,8 +24,8 @@ typedef long __kernel_clock_t; typedef int __kernel_daddr_t; typedef char * __kernel_caddr_t; typedef short __kernel_ipc_pid_t; -typedef unsigned int __kernel_uid16_t; -typedef unsigned int __kernel_gid16_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; typedef unsigned int __kernel_uid32_t; typedef unsigned int __kernel_gid32_t; diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h index 20e337f34ec8..704bd68ab524 100644 --- a/include/asm-ppc/processor.h +++ b/include/asm-ppc/processor.h @@ -11,6 +11,7 @@ #include #include +#include /* Machine State Register (MSR) Fields */ @@ -625,9 +626,11 @@ struct thread_struct { double fpr[32]; /* Complete floating point set */ unsigned long fpscr_pad; /* fpr ... fpscr must be contiguous */ unsigned long fpscr; /* Floating point status */ - unsigned long vrf[128]; - unsigned long vscr; +#ifdef CONFIG_ALTIVEC + vector128 vr[32]; /* Complete AltiVec set */ + vector128 vscr; /* AltiVec status */ unsigned long vrsave; +#endif /* CONFIG_ALTIVEC */ }; #define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack) diff --git a/include/asm-ppc/smp.h b/include/asm-ppc/smp.h index ac1442861337..156d8db72e4c 100644 --- a/include/asm-ppc/smp.h +++ b/include/asm-ppc/smp.h @@ -33,7 +33,7 @@ void smp_send_tlb_invalidate(int); /* 1 to 1 mapping on PPC -- Cort */ #define cpu_logical_map(cpu) (cpu) -extern int cpu_number_map[NR_CPUS]; +#define cpu_number_map(x) (x) extern volatile unsigned long cpu_callin_map[NR_CPUS]; #define hard_smp_processor_id() (0) diff --git a/include/asm-ppc/softirq.h b/include/asm-ppc/softirq.h index 1188809e9b51..550b46192481 100644 --- a/include/asm-ppc/softirq.h +++ b/include/asm-ppc/softirq.h @@ -4,116 +4,11 @@ #include #include -#define get_active_bhs() (bh_mask & bh_active) -#define clear_active_bhs(x) atomic_clear_mask((x),&bh_active) +extern unsigned int local_bh_count[NR_CPUS]; -extern unsigned int ppc_local_bh_count[NR_CPUS]; +#define local_bh_disable() do { local_bh_count[smp_processor_id()]++; barrier(); } while (0) +#define local_bh_enable() do { barrier(); local_bh_count[smp_processor_id()]--; } while (0) -extern inline void init_bh(int nr, void (*routine)(void)) -{ - bh_base[nr] = routine; - atomic_set(&bh_mask_count[nr], 0); - bh_mask |= 1 << nr; -} - -extern inline void remove_bh(int nr) -{ - bh_mask &= ~(1 << nr); - wmb(); - bh_base[nr] = 0; -} - -extern inline void mark_bh(int nr) -{ - set_bit(nr, &bh_active); -} - -#ifdef __SMP__ - -/* - * The locking mechanism for base handlers, to prevent re-entrancy, - * is entirely private to an implementation, it should not be - * referenced at all outside of this file. - */ -extern atomic_t global_bh_lock; -extern atomic_t global_bh_count; - -extern void synchronize_bh(void); - -static inline void start_bh_atomic(void) -{ - atomic_inc(&global_bh_lock); - synchronize_bh(); -} - -static inline void end_bh_atomic(void) -{ - atomic_dec(&global_bh_lock); -} - -/* These are for the IRQs testing the lock */ -static inline int softirq_trylock(int cpu) -{ - if (ppc_local_bh_count[cpu] == 0) { - ppc_local_bh_count[cpu] = 1; - if (!test_and_set_bit(0,&global_bh_count)) { - mb(); - if (atomic_read(&global_bh_lock) == 0) - return 1; - clear_bit(0,&global_bh_count); - } - ppc_local_bh_count[cpu] = 0; - mb(); - } - return 0; -} - -static inline void softirq_endlock(int cpu) -{ - mb(); - ppc_local_bh_count[cpu]--; - clear_bit(0,&global_bh_count); -} - -#else - -extern inline void start_bh_atomic(void) -{ - ppc_local_bh_count[smp_processor_id()]++; - barrier(); -} - -extern inline void end_bh_atomic(void) -{ - barrier(); - ppc_local_bh_count[smp_processor_id()]--; -} - -/* These are for the irq's testing the lock */ -#define softirq_trylock(cpu) (ppc_local_bh_count[cpu] ? 0 : (ppc_local_bh_count[cpu]=1)) -#define softirq_endlock(cpu) (ppc_local_bh_count[cpu] = 0) -#define synchronize_bh() barrier() - -#endif /* SMP */ - -#define local_bh_disable() (ppc_local_bh_count[smp_processor_id()]++) -#define local_bh_enable() (ppc_local_bh_count[smp_processor_id()]--) - -/* - * These use a mask count to correctly handle - * nested disable/enable calls - */ -extern inline void disable_bh(int nr) -{ - bh_mask &= ~(1 << nr); - atomic_inc(&bh_mask_count[nr]); - synchronize_bh(); -} - -extern inline void enable_bh(int nr) -{ - if (atomic_dec_and_test(&bh_mask_count[nr])) - bh_mask |= 1 << nr; -} +#define in_softirq() (local_bh_count[smp_processor_id()] != 0) #endif /* __ASM_SOFTIRQ_H */ diff --git a/include/asm-ppc/spinlock.h b/include/asm-ppc/spinlock.h index ad1fdda173b2..5e7e2a19eba4 100644 --- a/include/asm-ppc/spinlock.h +++ b/include/asm-ppc/spinlock.h @@ -14,6 +14,7 @@ typedef struct { #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 0, 0 } #define spin_lock_init(lp) do { (lp)->lock = 0; } while(0) #define spin_unlock_wait(lp) do { barrier(); } while((lp)->lock) +#define spin_is_locked(x) ((x)->lock != 0) extern void _spin_lock(spinlock_t *lock); extern void _spin_unlock(spinlock_t *lock); diff --git a/include/asm-ppc/types.h b/include/asm-ppc/types.h index 4c5e9766e6ef..d39f91cf9c62 100644 --- a/include/asm-ppc/types.h +++ b/include/asm-ppc/types.h @@ -1,6 +1,7 @@ #ifndef _PPC_TYPES_H #define _PPC_TYPES_H +#ifndef __ASSEMBLY__ /* * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the * header files exported to user space @@ -41,10 +42,15 @@ typedef unsigned long long u64; #define BITS_PER_LONG 32 +typedef struct { + u32 u[4]; +} __attribute((aligned(16))) vector128; + /* DMA addresses are 32-bits wide */ typedef u32 dma_addr_t; #endif /* __KERNEL__ */ +#endif /* __ASSEMBLY__ */ #endif diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index cd6dc704afa2..9dbd7005c79f 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -250,10 +250,9 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) /* to find an entry in a page-table-directory. */ -#define __pgd_offset(address) \ - ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) - -#define pgd_offset(mm, address) ((mm)->pgd+__pgd_offset(address)) +#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) +#define __pgd_offset(address) pgd_index(address) +#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) /* to find an entry in a kernel page-table-directory */ #define pgd_offset_k(address) pgd_offset(&init_mm, address) diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h index fb65d46dc1cf..4d178602db58 100644 --- a/include/asm-sparc64/floppy.h +++ b/include/asm-sparc64/floppy.h @@ -1,4 +1,4 @@ -/* $Id: floppy.h,v 1.25 2000/01/28 13:43:14 jj Exp $ +/* $Id: floppy.h,v 1.26 2000/02/12 23:32:35 davem Exp $ * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -727,8 +727,8 @@ static unsigned long __init sun_floppy_init(void) * which the generic floppy driver tries to do once again. */ sun_fdc = (struct sun_flpy_controller *) - (PAGE_OFFSET + fd_regs[0].phys_addr + - (((unsigned long)fd_regs[0].which_io) << 32)); + ((unsigned long)fd_regs[0].phys_addr + + (((unsigned long)fd_regs[0].which_io) << 32UL)); /* Last minute sanity check... */ if(sbus_readb(&sun_fdc->status1_82077) == 0xff) { diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index 3b93b20c14a3..878b99142c6f 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -235,7 +235,8 @@ static __inline__ pte_t pte_mkdirty(pte_t _pte) } /* to find an entry in a page-table-directory. */ -#define pgd_offset(mm, address) ((mm)->pgd + ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD))) +#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD)) +#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) /* to find an entry in a kernel page-table-directory */ #define pgd_offset_k(address) pgd_offset(&init_mm, address) diff --git a/include/linux/adfs_fs_i.h b/include/linux/adfs_fs_i.h index 94d5607bfa54..7da1ceda02d6 100644 --- a/include/linux/adfs_fs_i.h +++ b/include/linux/adfs_fs_i.h @@ -11,7 +11,7 @@ * adfs file system inode data in memory */ struct adfs_inode_info { - unsigned long mmu_private; + unsigned long mmu_private; unsigned long parent_id; /* object id of parent */ __u32 loadaddr; /* RISC OS load address */ __u32 execaddr; /* RISC OS exec address */ diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 55e103dd583d..22a5ed28ada4 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -68,6 +68,7 @@ #define I2C_DRIVERID_SAA7110 22 /* */ #define I2C_DRIVERID_MGATVO 23 /* Matrox TVOut */ #define I2C_DRIVERID_SAA5249 24 /* SAA5249 and compatibles */ +#define I2C_DRIVERID_PCF8583 25 /* real time clock */ #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ #define I2C_DRIVERID_EXP1 0xF1 @@ -119,6 +120,7 @@ #define I2C_HW_B_G400 0x09 /* Matrox G400 */ #define I2C_HW_B_I810 0x0a /* Intel I810 */ #define I2C_HW_B_RIVA 0x10 /* Riva based graphics cards */ +#define I2C_HW_B_IOC 0x11 /* IOC bit-wiggling */ /* --- PCF 8584 based algorithms */ #define I2C_HW_P_LP 0x00 /* Parallel port interface */ diff --git a/include/linux/kmod.h b/include/linux/kmod.h index 4256df6d9519..83abfcf92fb4 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -3,6 +3,7 @@ */ #include +#include #ifdef CONFIG_KMOD extern int request_module(const char * name); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f0a220f72545..61efca7db2f5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -427,7 +427,7 @@ struct softnet_data extern struct softnet_data softnet_data[NR_CPUS]; -#define HAS_NETIF_QUEUE +#define HAVE_NETIF_QUEUE extern __inline__ void __netif_schedule(struct net_device *dev) { diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 2838a23ac573..614fd3a58ba2 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -126,6 +126,7 @@ EXPORT_SYMBOL(highmem_start_page); #endif /* filesystem internal functions */ +EXPORT_SYMBOL(def_blk_fops); EXPORT_SYMBOL(in_group_p); EXPORT_SYMBOL(update_atime); EXPORT_SYMBOL(get_super); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 2980059b2492..c3f75124f47a 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -53,6 +53,7 @@ repeat: maddr = kmap(page); memcpy((char *)maddr + (addr & ~PAGE_MASK), buf, len); flush_page_to_ram(page); + flush_icache_page(vma, page); kunmap(page); } else { maddr = kmap(page); diff --git a/mm/memory.c b/mm/memory.c index 9e7525245d7c..6abcf9bb0d1c 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -904,6 +904,8 @@ void vmtruncate(struct inode * inode, loff_t offset) } while ((mpnt = mpnt->vm_next_share) != NULL); out_unlock: spin_unlock(&inode->i_shared_lock); + if (inode->i_op && inode->i_op->truncate) + inode->i_op->truncate(inode); } @@ -957,6 +959,7 @@ static int do_swap_page(struct task_struct * tsk, return -1; flush_page_to_ram(page); + flush_icache_page(vma, page); } vma->vm_mm->rss++; @@ -1057,6 +1060,7 @@ static int do_no_page(struct task_struct * tsk, struct vm_area_struct * vma, * handle that later. */ flush_page_to_ram(new_page); + flush_icache_page(vma, new_page); entry = mk_pte(new_page, vma->vm_page_prot); if (write_access) { entry = pte_mkwrite(pte_mkdirty(entry)); diff --git a/mm/mmap.c b/mm/mmap.c index d6d89e5f53fb..aca4d99d8bb4 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -580,6 +580,7 @@ static void free_pgtables(struct mm_struct * mm, struct vm_area_struct *prev, { unsigned long first = start & PGDIR_MASK; unsigned long last = (end + PGDIR_SIZE - 1) & PGDIR_MASK; + unsigned long start_index, end_index; if (!prev) { prev = mm->mmap; @@ -607,12 +608,14 @@ static void free_pgtables(struct mm_struct * mm, struct vm_area_struct *prev, break; } no_mmaps: - first = first >> PGDIR_SHIFT; - last = last >> PGDIR_SHIFT; - if (last > first) { - clear_page_tables(mm, first, last-first); - flush_tlb_pgtables(mm, first << PGDIR_SHIFT, last << PGDIR_SHIFT); - } + /* + * If the PGD bits are not consecutive in the virtual address, the + * old method of shifting the VA >> by PGDIR_SHIFT doesn't work. + */ + start_index = pgd_index(first); + end_index = pgd_index(last); + if (end_index > start_index) + clear_page_tables(mm, start_index, end_index - start_index); } /* Munmap is split into 2 main parts -- this part which finds diff --git a/net/core/dev.c b/net/core/dev.c index 00d5caa2a37b..32c8143fba11 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -911,15 +911,14 @@ static __inline__ void skb_bond(struct sk_buff *skb) static void net_tx_action(struct softirq_action *h) { int cpu = smp_processor_id(); - unsigned long flags; if (softnet_data[cpu].completion_queue) { struct sk_buff *clist; - local_irq_save(flags); + local_irq_disable(); clist = softnet_data[cpu].completion_queue; softnet_data[cpu].completion_queue = NULL; - local_irq_restore(flags); + local_irq_enable(); while (clist != NULL) { struct sk_buff *skb = clist; @@ -933,10 +932,10 @@ static void net_tx_action(struct softirq_action *h) if (softnet_data[cpu].output_queue) { struct net_device *head; - local_irq_save(flags); + local_irq_disable(); head = softnet_data[cpu].output_queue; softnet_data[cpu].output_queue = NULL; - local_irq_restore(flags); + local_irq_enable(); while (head != NULL) { struct net_device *dev = head; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 06d620952182..09b9c1a11752 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/af_inet.c * - * $Id: af_inet6.c,v 1.53 2000/02/04 21:04:08 davem Exp $ + * $Id: af_inet6.c,v 1.54 2000/02/12 23:34:45 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -451,7 +451,7 @@ struct proto_ops inet6_dgram_ops = { inet6_bind, inet_dgram_connect, /* ok */ sock_no_socketpair, /* a do nothing */ - inet_accept, /* ok */ + sock_no_accept, /* a do nothing */ inet6_getname, datagram_poll, /* ok */ inet6_ioctl, /* must change */ diff --git a/net/khttpd/sockets.c b/net/khttpd/sockets.c index 0d575abdfb5f..60e66fdf884a 100644 --- a/net/khttpd/sockets.c +++ b/net/khttpd/sockets.c @@ -71,8 +71,6 @@ int StartListening(const int Port) /* Grrr... setsockopt() does this. */ sock->sk->reuse = 1; - /* Wow!!! */ - sock->sk->linger = 1; /* Now, start listening on the socket */ diff --git a/net/netsyms.c b/net/netsyms.c index b6f367df23ce..1a1e7513eebd 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -540,6 +540,7 @@ EXPORT_SYMBOL(unregister_hipdev); #ifdef CONFIG_SYSCTL EXPORT_SYMBOL(sysctl_wmem_max); EXPORT_SYMBOL(sysctl_rmem_max); +EXPORT_SYMBOL(sysctl_ip_default_ttl); #endif #if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) diff --git a/scripts/tkcond.c b/scripts/tkcond.c index f1a36bb25be4..ab0f74832f5a 100644 --- a/scripts/tkcond.c +++ b/scripts/tkcond.c @@ -498,6 +498,7 @@ void fix_conditionals( struct kconfig * scfg ) case token_define_int: case token_define_string: case token_define_tristate: + case token_endmenu: case token_hex: case token_int: case token_mainmenu_option: -- 2.39.5